pax_global_header00006660000000000000000000000064120711253230014506gustar00rootroot0000000000000052 comment=616aed4ec2889f379b9d1e840230d9a33cda8bf0 FreeRDP-1.0.2/000077500000000000000000000000001207112532300127355ustar00rootroot00000000000000FreeRDP-1.0.2/.gitignore000066400000000000000000000010411207112532300147210ustar00rootroot00000000000000# CMake CMakeFiles/ CMakeCache.txt config.h install_manifest.txt CTestTestfile.cmake freerdp.pc Makefile cmake_install.cmake CPackConfig.cmake CPackSourceConfig.cmake # Eclipse *.project *.cproject *.settings # Documentation docs/api client/X11/xfreerdp.1 # Mac OS X .DS_Store # Windows *.vcxproj *.vcxproj.* *.sdf *.sln *.suo *.opensdf ipch Debug # Binaries *.a *.so *.so.* *.dylib cunit/test_freerdp client/X11/xfreerdp client/test/freerdp-test client/DirectFB/dfreerdp server/test/tfreerdp-server server/X11/xfreerdp-server # Other *~ FreeRDP-1.0.2/CMakeLists.txt000066400000000000000000000126011207112532300154750ustar00rootroot00000000000000# FreeRDP: A Remote Desktop Protocol Client # FreeRDP cmake build script # # Copyright 2011 O.S. Systems Software Ltda. # Copyright 2011 Otavio Salvador # Copyright 2011 Marc-Andre Moreau # # 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. cmake_minimum_required(VERSION 2.6) project(FreeRDP C) set(CMAKE_COLOR_MAKEFILE ON) # Include cmake modules include(CheckIncludeFiles) include(CheckLibraryExists) include(FindPkgConfig) include(TestBigEndian) # Include our extra modules set(CMAKE_MODULE_PATH ${CMAKE_SOURCE_DIR}/cmake/) include(AutoVersioning) include(ConfigOptions) include(FindOptionalPackage) include(CheckCCompilerFlag) include(GNUInstallDirsWrapper) # Soname versioning set(FREERDP_VERSION_MAJOR "1") set(FREERDP_VERSION_MINOR "0") set(FREERDP_VERSION_REVISION "2") set(FREERDP_VERSION_SUFFIX "") set(FREERDP_VERSION "${FREERDP_VERSION_MAJOR}.${FREERDP_VERSION_MINOR}") set(FREERDP_VERSION_FULL "${FREERDP_VERSION}.${FREERDP_VERSION_REVISION}") # Default to release build type if(NOT CMAKE_BUILD_TYPE) set(CMAKE_BUILD_TYPE "Release") endif() # build shared libs if(NOT BUILD_SHARED_LIBS) set(BUILD_SHARED_LIBS ON) endif() # Compiler-specific flags if(CMAKE_COMPILER_IS_GNUCC) set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -Wall") CHECK_C_COMPILER_FLAG (-Wno-unused-result Wno-unused-result) if(Wno-unused-result) set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -Wno-unused-result") endif() CHECK_C_COMPILER_FLAG (-Wno-unused-but-set-variable Wno-unused-but-set-variable) if(Wno-unused-but-set-variable) set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -Wno-unused-but-set-variable") endif() if(CMAKE_BUILD_TYPE STREQUAL "Release") set(CMAKE_C_FLAGS_RELEASE "-DNDEBUG") set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -O2") endif() if(WITH_SSE2_TARGET) set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -msse2") endif() endif() if(MSVC) set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} /Gd /MT") set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} /O2 /Ob2") set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -D_X86_") set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -D_UNICODE") set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -DFREERDP_EXPORTS") set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -D_CRT_SECURE_NO_WARNINGS") set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -DWIN32_LEAN_AND_MEAN") SET(EXECUTABLE_OUTPUT_PATH ${PROJECT_BINARY_DIR}) SET(LIBRARY_OUTPUT_PATH ${PROJECT_BINARY_DIR}) endif() # Include files check_include_files(sys/param.h HAVE_SYS_PARAM_H) check_include_files(sys/socket.h HAVE_SYS_SOCKET_H) check_include_files(netdb.h HAVE_NETDB_H) check_include_files(fcntl.h HAVE_FCNTL_H) check_include_files(unistd.h HAVE_UNISTD_H) check_include_files(limits.h HAVE_LIMITS_H) check_include_files(stdint.h HAVE_STDINT_H) check_include_files(stdbool.h HAVE_STDBOOL_H) check_include_files(inttypes.h HAVE_INTTYPES_H) # Libraries that we have a hard dependency on find_required_package(OpenSSL) # Mac OS X if(APPLE) include_directories(/opt/local/include) link_directories(/opt/local/lib) set(CMAKE_SHARED_LINKER_FLAGS "-mmacosx-version-min=10.4") endif() if(NOT WIN32) find_required_package(ZLIB) find_optional_package(PulseAudio) find_optional_package(PCSC) find_suggested_package(Cups) if(NOT APPLE) find_suggested_package(FFmpeg) find_suggested_package(ALSA) else(NOT APPLE) find_optional_package(FFmpeg) endif() endif() # Endian test_big_endian(BIG_ENDIAN) # Path to put keymaps set(FREERDP_KEYMAP_PATH "${CMAKE_INSTALL_PREFIX}/freerdp/keymaps") # Path to put plugins set(FREERDP_PLUGIN_PATH "${CMAKE_INSTALL_PREFIX}/${CMAKE_INSTALL_LIBDIR}/freerdp") # Include directories include_directories(${CMAKE_CURRENT_BINARY_DIR}) include_directories(${CMAKE_SOURCE_DIR}/include) # Configure files configure_file(${CMAKE_CURRENT_SOURCE_DIR}/config.h.in ${CMAKE_CURRENT_BINARY_DIR}/config.h) # Generate pkg-config configure_file(${CMAKE_CURRENT_SOURCE_DIR}/freerdp.pc.in ${CMAKE_CURRENT_BINARY_DIR}/freerdp.pc @ONLY) install(FILES ${CMAKE_CURRENT_BINARY_DIR}/freerdp.pc DESTINATION ${CMAKE_INSTALL_LIBDIR}/pkgconfig) # Build CUnit find_optional_package(CUnit) if(WITH_CUNIT) enable_testing() add_subdirectory(cunit) endif() # Sub-directories add_subdirectory(include) add_subdirectory(libfreerdp-utils) if(NOT WIN32) add_subdirectory(libfreerdp-kbd) endif() add_subdirectory(libfreerdp-gdi) add_subdirectory(libfreerdp-rail) add_subdirectory(libfreerdp-cache) add_subdirectory(libfreerdp-codec) add_subdirectory(libfreerdp-channels) add_subdirectory(libfreerdp-core) if(NOT WIN32) add_subdirectory(channels) endif() option(WITH_CLIENT "Build client binaries" ON) if(WITH_CLIENT) add_subdirectory(client) endif() option(WITH_SERVER "Build server binaries" OFF) if(WITH_SERVER) add_subdirectory(server) endif() add_subdirectory(keymaps) # Source package set(CPACK_SOURCE_IGNORE_FILES "/\\\\.git/;/\\\\.gitignore;/CMakeCache.txt") string(TOLOWER ${CMAKE_PROJECT_NAME} CMAKE_PROJECT_NAME_lower) set(CPACK_SOURCE_PACKAGE_FILE_NAME "${CMAKE_PROJECT_NAME_lower}-${FREERDP_VERSION_FULL}") include(CPack) FreeRDP-1.0.2/ChangeLog000066400000000000000000000074771207112532300145260ustar00rootroot000000000000002013-01-02 Version 1.0.2 FreeRDP 1.0.2 is a maintenance release which contains several bug and stability fixes. * xfreerdp: * new parameter --from-stdin - prompts for unspecified arguments username, password, domain and host. * fix compability with x2go * fix keyboard state in remote app * documentation fixes * fixed crash when started with --authonly (#843) * libfreerdp-core: * several memory leaks and double frees were fixed * support for FastPath PDUs up to 32767 * register audio only if plugin is registered * load extensions after argument parsing * libfreerdp-utils: * fixed crash when HOME environment variable wasn't set * xfreerdp-server * deadlock fixed * accept TLSv1 and SSLv3 * smartcard * don't incorrectly set SCARD_STATE_IGNORE * libfreerdp-codec * performance improvement * libfreerdp-gdi * support for PatBlt DPa operation * plugin * ignore CHANNEL_FLAG_SUSPEND/CHANNEL_FLAG_RESUME to prevent possible crash For a detailed list of changes use "git log 1.0.1..1.0.2" Known problems: * If windows input language is set to german pressing the divde key (/) on the keypad results in minus (-) (see issue #811) 2012-02-07 Version 1.0.1 FreeRDP 1.0.1 is a maintenance release to address a certain number of issues found in 1.0.0. This release also brings corrective measures to certificate validation which were required for inclusion in Ubuntu. * Certificate Validation * Improved validation logic and robustness * Added validation of certificate name against hostname * Token-based Server Redirection * Fixed redirection logic * HAProxy load-balancer support * xfreerdp-server * better event handling * capture performance improvements * wfreerdp * Fix RemoteFX support * Fix mingw64 compilation * libfreerdp-core: * Fix severe TCP sending bug * Added server-side Standard RDP security 2012-01-16 Version 1.0.0 License: FreeRDP 1.0 is the first release of FreeRDP under the Apache License 2.0. The FreeRDP 1.x series is a rewrite, meaning there is no continuity with the previous FreeRDP 0.x series which were released under GPLv2. New Features: * RemoteFX * Both encoder and decoder * SSE2 and NEON optimization * NSCodec * RemoteApp * Working, minor glitches * Multimedia Redirection * ffmpeg support * Network Level Authentication (NLA) * NTLMv2 * Certificate validation * FIPS-compliant RDP security * new build system (cmake) * added official logo and icon New Architecture: * libfreerdp-core * core protocol * highly portable * both client and server * libfreerdp-cache * caching operations * libfreerdp-codec * bitmap decompression * codec encoding/decoding * libfreerdp-kbd * keyboard mapping * libfreerdp-channels * virtual channel management * client and server side support * libfreerdp-gdi * extensively unit tested * portable software GDI implementation * libfreerdp-rail * RemoteApp library * libfreerdp-utils * shared utility library FreeRDP Clients: * client/X11 (xfreerdp) * official client * RemoteApp support * X11 GDI implementation * client/DirectFB (dfreerdp) * DirectFB support * software-based GDI (libfreerdp-gdi) * client/Windows (wfreerdp) * Native Win32 support FreeRDP Servers (experimental): * server/X11 (xfreerdp-server) * RemoteFX-only * no authentication * highly experimental * keyboard and mouse input supported Virtual Channels: * cliprdr (Clipboard Redirection) * rail (RemoteApp) * drdynvc (Dynamic Virtual Channels) * audin (Audio Input Redirection) * alsa support * pulse support * tsmf (Multimedia Redirection) * alsa support * pulse support * ffmpeg support * rdpdr (Device Redirection) * disk (Disk Redirection) * parallel (Parallel Port Redirection) * serial (Serial Port Redirection) * printer (Printer Redirection) * CUPS support * smartcard (Smartcard Redirection) * rdpsnd (Sound Redirection) * alsa support * pulse support FreeRDP-1.0.2/LICENSE000066400000000000000000000261361207112532300137520ustar00rootroot00000000000000 Apache License Version 2.0, January 2004 http://www.apache.org/licenses/ TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION 1. Definitions. "License" shall mean the terms and conditions for use, reproduction, and distribution as defined by Sections 1 through 9 of this document. "Licensor" shall mean the copyright owner or entity authorized by the copyright owner that is granting the License. "Legal Entity" shall mean the union of the acting entity and all other entities that control, are controlled by, or are under common control with that entity. For the purposes of this definition, "control" means (i) the power, direct or indirect, to cause the direction or management of such entity, whether by contract or otherwise, or (ii) ownership of fifty percent (50%) or more of the outstanding shares, or (iii) beneficial ownership of such entity. "You" (or "Your") shall mean an individual or Legal Entity exercising permissions granted by this License. "Source" form shall mean the preferred form for making modifications, including but not limited to software source code, documentation source, and configuration files. "Object" form shall mean any form resulting from mechanical transformation or translation of a Source form, including but not limited to compiled object code, generated documentation, and conversions to other media types. "Work" shall mean the work of authorship, whether in Source or Object form, made available under the License, as indicated by a copyright notice that is included in or attached to the work (an example is provided in the Appendix below). "Derivative Works" shall mean any work, whether in Source or Object form, that is based on (or derived from) the Work and for which the editorial revisions, annotations, elaborations, or other modifications represent, as a whole, an original work of authorship. For the purposes of this License, Derivative Works shall not include works that remain separable from, or merely link (or bind by name) to the interfaces of, the Work and Derivative Works thereof. "Contribution" shall mean any work of authorship, including the original version of the Work and any modifications or additions to that Work or Derivative Works thereof, that is intentionally submitted to Licensor for inclusion in the Work by the copyright owner or by an individual or Legal Entity authorized to submit on behalf of the copyright owner. For the purposes of this definition, "submitted" means any form of electronic, verbal, or written communication sent to the Licensor or its representatives, including but not limited to communication on electronic mailing lists, source code control systems, and issue tracking systems that are managed by, or on behalf of, the Licensor for the purpose of discussing and improving the Work, but excluding communication that is conspicuously marked or otherwise designated in writing by the copyright owner as "Not a Contribution." "Contributor" shall mean Licensor and any individual or Legal Entity on behalf of whom a Contribution has been received by Licensor and subsequently incorporated within the Work. 2. Grant of Copyright License. Subject to the terms and conditions of this License, each Contributor hereby grants to You a perpetual, worldwide, non-exclusive, no-charge, royalty-free, irrevocable copyright license to reproduce, prepare Derivative Works of, publicly display, publicly perform, sublicense, and distribute the Work and such Derivative Works in Source or Object form. 3. Grant of Patent License. Subject to the terms and conditions of this License, each Contributor hereby grants to You a perpetual, worldwide, non-exclusive, no-charge, royalty-free, irrevocable (except as stated in this section) patent license to make, have made, use, offer to sell, sell, import, and otherwise transfer the Work, where such license applies only to those patent claims licensable by such Contributor that are necessarily infringed by their Contribution(s) alone or by combination of their Contribution(s) with the Work to which such Contribution(s) was submitted. If You institute patent litigation against any entity (including a cross-claim or counterclaim in a lawsuit) alleging that the Work or a Contribution incorporated within the Work constitutes direct or contributory patent infringement, then any patent licenses granted to You under this License for that Work shall terminate as of the date such litigation is filed. 4. Redistribution. You may reproduce and distribute copies of the Work or Derivative Works thereof in any medium, with or without modifications, and in Source or Object form, provided that You meet the following conditions: (a) You must give any other recipients of the Work or Derivative Works a copy of this License; and (b) You must cause any modified files to carry prominent notices stating that You changed the files; and (c) You must retain, in the Source form of any Derivative Works that You distribute, all copyright, patent, trademark, and attribution notices from the Source form of the Work, excluding those notices that do not pertain to any part of the Derivative Works; and (d) If the Work includes a "NOTICE" text file as part of its distribution, then any Derivative Works that You distribute must include a readable copy of the attribution notices contained within such NOTICE file, excluding those notices that do not pertain to any part of the Derivative Works, in at least one of the following places: within a NOTICE text file distributed as part of the Derivative Works; within the Source form or documentation, if provided along with the Derivative Works; or, within a display generated by the Derivative Works, if and wherever such third-party notices normally appear. The contents of the NOTICE file are for informational purposes only and do not modify the License. You may add Your own attribution notices within Derivative Works that You distribute, alongside or as an addendum to the NOTICE text from the Work, provided that such additional attribution notices cannot be construed as modifying the License. You may add Your own copyright statement to Your modifications and may provide additional or different license terms and conditions for use, reproduction, or distribution of Your modifications, or for any such Derivative Works as a whole, provided Your use, reproduction, and distribution of the Work otherwise complies with the conditions stated in this License. 5. Submission of Contributions. Unless You explicitly state otherwise, any Contribution intentionally submitted for inclusion in the Work by You to the Licensor shall be under the terms and conditions of this License, without any additional terms or conditions. Notwithstanding the above, nothing herein shall supersede or modify the terms of any separate license agreement you may have executed with Licensor regarding such Contributions. 6. Trademarks. This License does not grant permission to use the trade names, trademarks, service marks, or product names of the Licensor, except as required for reasonable and customary use in describing the origin of the Work and reproducing the content of the NOTICE file. 7. Disclaimer of Warranty. Unless required by applicable law or agreed to in writing, Licensor provides the Work (and each Contributor provides its Contributions) on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied, including, without limitation, any warranties or conditions of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A PARTICULAR PURPOSE. You are solely responsible for determining the appropriateness of using or redistributing the Work and assume any risks associated with Your exercise of permissions under this License. 8. Limitation of Liability. In no event and under no legal theory, whether in tort (including negligence), contract, or otherwise, unless required by applicable law (such as deliberate and grossly negligent acts) or agreed to in writing, shall any Contributor be liable to You for damages, including any direct, indirect, special, incidental, or consequential damages of any character arising as a result of this License or out of the use or inability to use the Work (including but not limited to damages for loss of goodwill, work stoppage, computer failure or malfunction, or any and all other commercial damages or losses), even if such Contributor has been advised of the possibility of such damages. 9. Accepting Warranty or Additional Liability. While redistributing the Work or Derivative Works thereof, You may choose to offer, and charge a fee for, acceptance of support, warranty, indemnity, or other liability obligations and/or rights consistent with this License. However, in accepting such obligations, You may act only on Your own behalf and on Your sole responsibility, not on behalf of any other Contributor, and only if You agree to indemnify, defend, and hold each Contributor harmless for any liability incurred by, or claims asserted against, such Contributor by reason of your accepting any such warranty or additional liability. END OF TERMS AND CONDITIONS APPENDIX: How to apply the Apache License to your work. To apply the Apache License to your work, attach the following boilerplate notice, with the fields enclosed by brackets "[]" replaced with your own identifying information. (Don't include the brackets!) The text should be enclosed in the appropriate comment syntax for the file format. We also recommend that a file or class name and description of purpose be included on the same "printed page" as the copyright notice for easier identification within third-party archives. Copyright [yyyy] [name of copyright owner] 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. FreeRDP-1.0.2/README000066400000000000000000000021461207112532300136200ustar00rootroot00000000000000FreeRDP: A Remote Desktop Protocol Implementation ================================================= FreeRDP is a free implementation of the Remote Desktop Protocol (RDP), released under the Apache license. Enjoy the freedom of using your software wherever you want, the way you want it, in a world where interoperability can finally liberate your computing experience. Resources --------- Website: http://www.freerdp.com/ Wiki: https://github.com/FreeRDP/FreeRDP/wiki Sources: https://github.com/FreeRDP/FreeRDP/ API doc: http://www.freerdp.com/api/ IRC channel: #freerdp @ irc.freenode.net Mailing list: https://lists.sourceforge.net/lists/listinfo/freerdp-devel Microsoft Open Specifications ----------------------------- Information regarding the Microsoft Open Specifications can be found at: http://www.microsoft.com/openspecifications/ A list of reference documentation is maintained here: https://github.com/FreeRDP/FreeRDP/wiki/Reference-Documentation Compilation ----------- Instructions on how to get started compiling FreeRDP can be found on the wiki: https://github.com/FreeRDP/FreeRDP/wiki/Compilation FreeRDP-1.0.2/channels/000077500000000000000000000000001207112532300145305ustar00rootroot00000000000000FreeRDP-1.0.2/channels/CMakeLists.txt000066400000000000000000000016541207112532300172760ustar00rootroot00000000000000# FreeRDP: A Remote Desktop Protocol Client # FreeRDP cmake build script # # Copyright 2011 O.S. Systems Software Ltda. # Copyright 2011 Otavio Salvador # Copyright 2011 Marc-Andre Moreau # # 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. add_subdirectory(cliprdr) add_subdirectory(drdynvc) add_subdirectory(rdpdbg) add_subdirectory(rdpdr) add_subdirectory(rail) add_subdirectory(rdpsnd) FreeRDP-1.0.2/channels/cliprdr/000077500000000000000000000000001207112532300161675ustar00rootroot00000000000000FreeRDP-1.0.2/channels/cliprdr/CMakeLists.txt000066400000000000000000000021071207112532300207270ustar00rootroot00000000000000# FreeRDP: A Remote Desktop Protocol Client # FreeRDP cmake build script # # Copyright 2011 O.S. Systems Software Ltda. # Copyright 2011 Otavio Salvador # Copyright 2011 Marc-Andre Moreau # # 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(CLIPRDR_SRCS cliprdr_constants.h cliprdr_format.c cliprdr_format.h cliprdr_main.c cliprdr_main.h ) add_library(cliprdr ${CLIPRDR_SRCS}) set_target_properties(cliprdr PROPERTIES PREFIX "") target_link_libraries(cliprdr freerdp-utils) install(TARGETS cliprdr DESTINATION ${FREERDP_PLUGIN_PATH}) FreeRDP-1.0.2/channels/cliprdr/cliprdr_constants.h000066400000000000000000000035021207112532300220730ustar00rootroot00000000000000/** * FreeRDP: A Remote Desktop Protocol client. * Clipboard Virtual Channel * * Copyright 2009-2011 Jay Sorg * Copyright 2010-2011 Vic Lee * * 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. */ #ifndef __CLIPRDR_CONSTANTS #define __CLIPRDR_CONSTANTS /* CLIPRDR_HEADER.msgType */ #define CB_MONITOR_READY 0x0001 #define CB_FORMAT_LIST 0x0002 #define CB_FORMAT_LIST_RESPONSE 0x0003 #define CB_FORMAT_DATA_REQUEST 0x0004 #define CB_FORMAT_DATA_RESPONSE 0x0005 #define CB_TEMP_DIRECTORY 0x0006 #define CB_CLIP_CAPS 0x0007 #define CB_FILECONTENTS_REQUEST 0x0008 #define CB_FILECONTENTS_RESPONSE 0x0009 #define CB_LOCK_CLIPDATA 0x000A #define CB_UNLOCK_CLIPDATA 0x000B /* CLIPRDR_HEADER.msgFlags */ #define CB_RESPONSE_OK 0x0001 #define CB_RESPONSE_FAIL 0x0002 #define CB_ASCII_NAMES 0x0004 /* CLIPRDR_CAPS_SET.capabilitySetType */ #define CB_CAPSTYPE_GENERAL 0x0001 /* CLIPRDR_GENERAL_CAPABILITY.lengthCapability */ #define CB_CAPSTYPE_GENERAL_LEN 12 /* CLIPRDR_GENERAL_CAPABILITY.version */ #define CB_CAPS_VERSION_1 0x00000001 #define CB_CAPS_VERSION_2 0x00000002 /* CLIPRDR_GENERAL_CAPABILITY.generalFlags */ #define CB_USE_LONG_FORMAT_NAMES 0x00000002 #define CB_STREAM_FILECLIP_ENABLED 0x00000004 #define CB_FILECLIP_NO_FILE_PATHS 0x00000008 #define CB_CAN_LOCK_CLIPDATA 0x00000010 #endif /* __CLIPRDR_CONSTANTS */ FreeRDP-1.0.2/channels/cliprdr/cliprdr_format.c000066400000000000000000000220551207112532300213460ustar00rootroot00000000000000/** * FreeRDP: A Remote Desktop Protocol client. * Clipboard Virtual Channel * * Copyright 2009-2011 Jay Sorg * Copyright 2010-2011 Vic Lee * * 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. */ #include #include #include #include #include #include #include #include #include #include #include "cliprdr_constants.h" #include "cliprdr_main.h" #include "cliprdr_format.h" #define CFSTR_HTML "H\0T\0M\0L\0 \0F\0o\0r\0m\0a\0t\0\0" #define CFSTR_PNG "P\0N\0G\0\0" #define CFSTR_JPEG "J\0F\0I\0F\0\0" #define CFSTR_GIF "G\0I\0F\0\0" void cliprdr_process_format_list_event(cliprdrPlugin* cliprdr, RDP_CB_FORMAT_LIST_EVENT* cb_event) { int i; STREAM* s; DEBUG_CLIPRDR("Sending Clipboard Format List"); if (cb_event->raw_format_data) { s = cliprdr_packet_new(CB_FORMAT_LIST, 0, cb_event->raw_format_data_size); stream_write(s, cb_event->raw_format_data, cb_event->raw_format_data_size); } else { STREAM* body = stream_new(0); for (i = 0; i < cb_event->num_formats; i++) { const char* name; int name_length; switch (cb_event->formats[i]) { case CB_FORMAT_HTML: name = CFSTR_HTML; name_length = sizeof(CFSTR_HTML); break; case CB_FORMAT_PNG: name = CFSTR_PNG; name_length = sizeof(CFSTR_PNG); break; case CB_FORMAT_JPEG: name = CFSTR_JPEG; name_length = sizeof(CFSTR_JPEG); break; case CB_FORMAT_GIF: name = CFSTR_GIF; name_length = sizeof(CFSTR_GIF); break; default: name = "\0\0"; name_length = 2; } if (!cliprdr->use_long_format_names) name_length = 32; stream_extend(body, stream_get_size(body) + 4 + name_length); stream_write_uint32(body, cb_event->formats[i]); stream_write(body, name, name_length); } s = cliprdr_packet_new(CB_FORMAT_LIST, 0, stream_get_size(body)); stream_write(s, stream_get_head(body), stream_get_size(body)); stream_free(body); } cliprdr_packet_send(cliprdr, s); } static void cliprdr_send_format_list_response(cliprdrPlugin* cliprdr) { STREAM* s; DEBUG_CLIPRDR("Sending Clipboard Format List Response"); s = cliprdr_packet_new(CB_FORMAT_LIST_RESPONSE, CB_RESPONSE_OK, 0); cliprdr_packet_send(cliprdr, s); } void cliprdr_process_short_format_names(cliprdrPlugin* cliprdr, STREAM* s, uint32 length, uint16 flags) { int i; boolean ascii; int num_formats; CLIPRDR_FORMAT_NAME* format_name; num_formats = length / 36; if (num_formats <= 0) { cliprdr->format_names = NULL; cliprdr->num_format_names = 0; return; } if (num_formats * 36 != length) DEBUG_WARN("dataLen %d not divided by 36!", length); ascii = (flags & CB_ASCII_NAMES) ? true : false; cliprdr->format_names = (CLIPRDR_FORMAT_NAME*) xmalloc(sizeof(CLIPRDR_FORMAT_NAME) * num_formats); cliprdr->num_format_names = num_formats; for (i = 0; i < num_formats; i++) { format_name = &cliprdr->format_names[i]; stream_read_uint32(s, format_name->id); if (ascii) { format_name->name = xstrdup((char*) s->p); format_name->length = strlen(format_name->name); } else { format_name->name = freerdp_uniconv_in(cliprdr->uniconv, s->p, 32); format_name->length = strlen(format_name->name); } stream_seek(s, 32); } } void cliprdr_process_long_format_names(cliprdrPlugin* cliprdr, STREAM* s, uint32 length, uint16 flags) { int allocated_formats = 8; uint8* end_mark; CLIPRDR_FORMAT_NAME* format_name; stream_get_mark(s, end_mark); end_mark += length; cliprdr->format_names = (CLIPRDR_FORMAT_NAME*) xmalloc(sizeof(CLIPRDR_FORMAT_NAME) * allocated_formats); cliprdr->num_format_names = 0; while (stream_get_left(s) >= 6) { uint8* p; int name_len; if (cliprdr->num_format_names >= allocated_formats) { allocated_formats *= 2; cliprdr->format_names = (CLIPRDR_FORMAT_NAME*) xrealloc(cliprdr->format_names, sizeof(CLIPRDR_FORMAT_NAME) * allocated_formats); } format_name = &cliprdr->format_names[cliprdr->num_format_names++]; stream_read_uint32(s, format_name->id); format_name->name = NULL; format_name->length = 0; for (p = stream_get_tail(s), name_len = 0; p + 1 < end_mark; p += 2, name_len += 2) { if (*((unsigned short*) p) == 0) break; } format_name->name = freerdp_uniconv_in(cliprdr->uniconv, stream_get_tail(s), name_len); format_name->length = strlen(format_name->name); stream_seek(s, name_len + 2); } } void cliprdr_process_format_list(cliprdrPlugin* cliprdr, STREAM* s, uint32 dataLen, uint16 msgFlags) { int i; uint32 format; boolean supported; CLIPRDR_FORMAT_NAME* format_name; RDP_CB_FORMAT_LIST_EVENT* cb_event; cb_event = (RDP_CB_FORMAT_LIST_EVENT*) freerdp_event_new(RDP_EVENT_CLASS_CLIPRDR, RDP_EVENT_TYPE_CB_FORMAT_LIST, NULL, NULL); if (dataLen > 0) { cb_event->raw_format_data = (uint8*) xmalloc(dataLen); memcpy(cb_event->raw_format_data, stream_get_tail(s), dataLen); cb_event->raw_format_data_size = dataLen; } if (cliprdr->use_long_format_names) cliprdr_process_long_format_names(cliprdr, s, dataLen, msgFlags); else cliprdr_process_short_format_names(cliprdr, s, dataLen, msgFlags); if (cliprdr->num_format_names > 0) cb_event->formats = (uint32*) xmalloc(sizeof(uint32) * cliprdr->num_format_names); cb_event->num_formats = 0; for (i = 0; i < cliprdr->num_format_names; i++) { supported = true; format_name = &cliprdr->format_names[i]; format = format_name->id; switch (format) { case CB_FORMAT_TEXT: case CB_FORMAT_DIB: case CB_FORMAT_UNICODETEXT: break; default: if (format_name->length > 0) { DEBUG_CLIPRDR("format: %s", format_name->name); if (strcmp(format_name->name, "HTML Format") == 0) { format = CB_FORMAT_HTML; break; } if (strcmp(format_name->name, "PNG") == 0) { format = CB_FORMAT_PNG; break; } if (strcmp(format_name->name, "JFIF") == 0) { format = CB_FORMAT_JPEG; break; } if (strcmp(format_name->name, "GIF") == 0) { format = CB_FORMAT_GIF; break; } } else { supported = false; } break; } if (supported) cb_event->formats[cb_event->num_formats++] = format; if (format_name->length > 0) xfree(format_name->name); } xfree(cliprdr->format_names); cliprdr->format_names = NULL; cliprdr->num_format_names = 0; svc_plugin_send_event((rdpSvcPlugin*) cliprdr, (RDP_EVENT*) cb_event); cliprdr_send_format_list_response(cliprdr); } void cliprdr_process_format_list_response(cliprdrPlugin* cliprdr, STREAM* s, uint32 dataLen, uint16 msgFlags) { /* where is this documented? */ #if 0 RDP_EVENT* event; if ((msgFlags & CB_RESPONSE_FAIL) != 0) { event = freerdp_event_new(RDP_EVENT_CLASS_CLIPRDR, RDP_EVENT_TYPE_CB_MONITOR_READY, NULL, NULL); svc_plugin_send_event((rdpSvcPlugin*) cliprdr, event); } #endif } void cliprdr_process_format_data_request(cliprdrPlugin* cliprdr, STREAM* s, uint32 dataLen, uint16 msgFlags) { RDP_CB_DATA_REQUEST_EVENT* cb_event; cb_event = (RDP_CB_DATA_REQUEST_EVENT*) freerdp_event_new(RDP_EVENT_CLASS_CLIPRDR, RDP_EVENT_TYPE_CB_DATA_REQUEST, NULL, NULL); stream_read_uint32(s, cb_event->format); svc_plugin_send_event((rdpSvcPlugin*) cliprdr, (RDP_EVENT*) cb_event); } void cliprdr_process_format_data_response_event(cliprdrPlugin* cliprdr, RDP_CB_DATA_RESPONSE_EVENT* cb_event) { STREAM* s; DEBUG_CLIPRDR("Sending Format Data Response"); if (cb_event->size > 0) { s = cliprdr_packet_new(CB_FORMAT_DATA_RESPONSE, CB_RESPONSE_OK, cb_event->size); stream_write(s, cb_event->data, cb_event->size); } else { s = cliprdr_packet_new(CB_FORMAT_DATA_RESPONSE, CB_RESPONSE_FAIL, 0); } cliprdr_packet_send(cliprdr, s); } void cliprdr_process_format_data_request_event(cliprdrPlugin* cliprdr, RDP_CB_DATA_REQUEST_EVENT* cb_event) { STREAM* s; DEBUG_CLIPRDR("Sending Format Data Request"); s = cliprdr_packet_new(CB_FORMAT_DATA_REQUEST, 0, 4); stream_write_uint32(s, cb_event->format); cliprdr_packet_send(cliprdr, s); } void cliprdr_process_format_data_response(cliprdrPlugin* cliprdr, STREAM* s, uint32 dataLen, uint16 msgFlags) { RDP_CB_DATA_RESPONSE_EVENT* cb_event; cb_event = (RDP_CB_DATA_RESPONSE_EVENT*) freerdp_event_new(RDP_EVENT_CLASS_CLIPRDR, RDP_EVENT_TYPE_CB_DATA_RESPONSE, NULL, NULL); if (dataLen > 0) { cb_event->size = dataLen; cb_event->data = (uint8*) xmalloc(dataLen); memcpy(cb_event->data, stream_get_tail(s), dataLen); } svc_plugin_send_event((rdpSvcPlugin*) cliprdr, (RDP_EVENT*) cb_event); } FreeRDP-1.0.2/channels/cliprdr/cliprdr_format.h000066400000000000000000000030201207112532300213420ustar00rootroot00000000000000/** * FreeRDP: A Remote Desktop Protocol client. * Clipboard Virtual Channel * * Copyright 2009-2011 Jay Sorg * Copyright 2010-2011 Vic Lee * * 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. */ #ifndef __CLIPRDR_FORMAT_H #define __CLIPRDR_FORMAT_H void cliprdr_process_format_list_event(cliprdrPlugin* cliprdr, RDP_CB_FORMAT_LIST_EVENT* cb_event); void cliprdr_process_format_list(cliprdrPlugin* cliprdr, STREAM* s, uint32 dataLen, uint16 msgFlags); void cliprdr_process_format_list_response(cliprdrPlugin* cliprdr, STREAM* s, uint32 dataLen, uint16 msgFlags); void cliprdr_process_format_data_request(cliprdrPlugin* cliprdr, STREAM* s, uint32 dataLen, uint16 msgFlags); void cliprdr_process_format_data_response_event(cliprdrPlugin* cliprdr, RDP_CB_DATA_RESPONSE_EVENT* cb_event); void cliprdr_process_format_data_request_event(cliprdrPlugin* cliprdr, RDP_CB_DATA_REQUEST_EVENT* cb_event); void cliprdr_process_format_data_response(cliprdrPlugin* cliprdr, STREAM* s, uint32 dataLen, uint16 msgFlags); #endif /* __CLIPRDR_FORMAT_H */ FreeRDP-1.0.2/channels/cliprdr/cliprdr_main.c000066400000000000000000000162071207112532300210040ustar00rootroot00000000000000/** * FreeRDP: A Remote Desktop Protocol client. * Clipboard Virtual Channel * * Copyright 2009-2011 Jay Sorg * Copyright 2010-2011 Vic Lee * * 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. */ #include #include #include #include #include #include #include #include #include #include "cliprdr_constants.h" #include "cliprdr_main.h" #include "cliprdr_format.h" static const char* const CB_MSG_TYPE_STRINGS[] = { "", "CB_MONITOR_READY", "CB_FORMAT_LIST", "CB_FORMAT_LIST_RESPONSE", "CB_FORMAT_DATA_REQUEST", "CB_FORMAT_DATA_RESPONSE", "CB_TEMP_DIRECTORY", "CB_CLIP_CAPS", "CB_FILECONTENTS_REQUEST", "CB_FILECONTENTS_RESPONSE", "CB_LOCK_CLIPDATA" "CB_UNLOCK_CLIPDATA" }; STREAM* cliprdr_packet_new(uint16 msgType, uint16 msgFlags, uint32 dataLen) { STREAM* s; s = stream_new(dataLen + 8); stream_write_uint16(s, msgType); stream_write_uint16(s, msgFlags); /* Write actual length after the entire packet has been constructed. */ stream_seek(s, 4); return s; } void cliprdr_packet_send(cliprdrPlugin* cliprdr, STREAM* s) { int pos; uint32 dataLen; pos = stream_get_pos(s); dataLen = pos - 8; stream_set_pos(s, 4); stream_write_uint32(s, dataLen); stream_set_pos(s, pos); svc_plugin_send((rdpSvcPlugin*) cliprdr, s); } static void cliprdr_process_connect(rdpSvcPlugin* plugin) { DEBUG_CLIPRDR("connecting"); ((cliprdrPlugin*) plugin)->uniconv = freerdp_uniconv_new(); } void cliprdr_print_general_capability_flags(uint32 flags) { printf("generalFlags (0x%08X) {\n", flags); if (flags & CB_USE_LONG_FORMAT_NAMES) printf("\tCB_USE_LONG_FORMAT_NAMES\n"); if (flags & CB_STREAM_FILECLIP_ENABLED) printf("\tCB_STREAM_FILECLIP_ENABLED\n"); if (flags & CB_FILECLIP_NO_FILE_PATHS) printf("\tCB_FILECLIP_NO_FILE_PATHS\n"); if (flags & CB_CAN_LOCK_CLIPDATA) printf("\tCB_CAN_LOCK_CLIPDATA\n"); printf("}\n"); } static void cliprdr_process_general_capability(cliprdrPlugin* cliprdr, STREAM* s) { uint32 version; uint32 generalFlags; stream_read_uint32(s, version); /* version (4 bytes) */ stream_read_uint32(s, generalFlags); /* generalFlags (4 bytes) */ DEBUG_CLIPRDR("Version: %d", version); #ifdef WITH_DEBUG_CLIPRDR cliprdr_print_general_capability_flags(generalFlags); #endif if (generalFlags & CB_USE_LONG_FORMAT_NAMES) cliprdr->use_long_format_names = true; if (generalFlags & CB_STREAM_FILECLIP_ENABLED) cliprdr->stream_fileclip_enabled = true; if (generalFlags & CB_FILECLIP_NO_FILE_PATHS) cliprdr->fileclip_no_file_paths = true; if (generalFlags & CB_CAN_LOCK_CLIPDATA) cliprdr->can_lock_clipdata = true; cliprdr->received_caps = true; } static void cliprdr_process_clip_caps(cliprdrPlugin* cliprdr, STREAM* s, uint16 length, uint16 flags) { int i; uint16 lengthCapability; uint16 cCapabilitiesSets; uint16 capabilitySetType; stream_read_uint16(s, cCapabilitiesSets); /* cCapabilitiesSets (2 bytes) */ stream_seek_uint16(s); /* pad1 (2 bytes) */ DEBUG_CLIPRDR("cCapabilitiesSets %d", cCapabilitiesSets); for (i = 0; i < cCapabilitiesSets; i++) { stream_read_uint16(s, capabilitySetType); /* capabilitySetType (2 bytes) */ stream_read_uint16(s, lengthCapability); /* lengthCapability (2 bytes) */ switch (capabilitySetType) { case CB_CAPSTYPE_GENERAL: cliprdr_process_general_capability(cliprdr, s); break; default: DEBUG_WARN("unknown cliprdr capability set: %d", capabilitySetType); break; } } } static void cliprdr_send_clip_caps(cliprdrPlugin* cliprdr) { STREAM* s; uint32 flags; s = cliprdr_packet_new(CB_CLIP_CAPS, 0, 4 + CB_CAPSTYPE_GENERAL_LEN); DEBUG_CLIPRDR("Sending Capabilities"); flags = CB_USE_LONG_FORMAT_NAMES; stream_write_uint16(s, 1); /* cCapabilitiesSets */ stream_write_uint16(s, 0); /* pad1 */ stream_write_uint16(s, CB_CAPSTYPE_GENERAL); /* capabilitySetType */ stream_write_uint16(s, CB_CAPSTYPE_GENERAL_LEN); /* lengthCapability */ stream_write_uint32(s, CB_CAPS_VERSION_2); /* version */ stream_write_uint32(s, flags); /* generalFlags */ cliprdr_packet_send(cliprdr, s); } static void cliprdr_process_monitor_ready(cliprdrPlugin* cliprdr, STREAM* s, uint16 length, uint16 flags) { RDP_EVENT* event; if (cliprdr->received_caps) cliprdr_send_clip_caps(cliprdr); event = freerdp_event_new(RDP_EVENT_CLASS_CLIPRDR, RDP_EVENT_TYPE_CB_MONITOR_READY, NULL, NULL); svc_plugin_send_event((rdpSvcPlugin*) cliprdr, event); } static void cliprdr_process_receive(rdpSvcPlugin* plugin, STREAM* s) { uint16 msgType; uint16 msgFlags; uint32 dataLen; cliprdrPlugin* cliprdr = (cliprdrPlugin*) plugin; stream_read_uint16(s, msgType); stream_read_uint16(s, msgFlags); stream_read_uint32(s, dataLen); DEBUG_CLIPRDR("msgType: %s (%d), msgFlags: %d dataLen: %d", CB_MSG_TYPE_STRINGS[msgType], msgType, msgFlags, dataLen); switch (msgType) { case CB_CLIP_CAPS: cliprdr_process_clip_caps(cliprdr, s, dataLen, msgFlags); break; case CB_MONITOR_READY: cliprdr_process_monitor_ready(cliprdr, s, dataLen, msgFlags); break; case CB_FORMAT_LIST: cliprdr_process_format_list(cliprdr, s, dataLen, msgFlags); break; case CB_FORMAT_LIST_RESPONSE: cliprdr_process_format_list_response(cliprdr, s, dataLen, msgFlags); break; case CB_FORMAT_DATA_REQUEST: cliprdr_process_format_data_request(cliprdr, s, dataLen, msgFlags); break; case CB_FORMAT_DATA_RESPONSE: cliprdr_process_format_data_response(cliprdr, s, dataLen, msgFlags); break; default: DEBUG_WARN("unknown msgType %d", msgType); break; } stream_free(s); } static void cliprdr_process_event(rdpSvcPlugin* plugin, RDP_EVENT* event) { switch (event->event_type) { case RDP_EVENT_TYPE_CB_FORMAT_LIST: cliprdr_process_format_list_event((cliprdrPlugin*) plugin, (RDP_CB_FORMAT_LIST_EVENT*) event); break; case RDP_EVENT_TYPE_CB_DATA_REQUEST: cliprdr_process_format_data_request_event((cliprdrPlugin*) plugin, (RDP_CB_DATA_REQUEST_EVENT*) event); break; case RDP_EVENT_TYPE_CB_DATA_RESPONSE: cliprdr_process_format_data_response_event((cliprdrPlugin*) plugin, (RDP_CB_DATA_RESPONSE_EVENT*) event); break; default: DEBUG_WARN("unknown event type %d", event->event_type); break; } freerdp_event_free(event); } static void cliprdr_process_terminate(rdpSvcPlugin* plugin) { cliprdrPlugin* cliprdr_plugin = (cliprdrPlugin*) plugin; if (cliprdr_plugin->uniconv != NULL) freerdp_uniconv_free(cliprdr_plugin->uniconv); xfree(plugin); } DEFINE_SVC_PLUGIN(cliprdr, "cliprdr", CHANNEL_OPTION_INITIALIZED | CHANNEL_OPTION_ENCRYPT_RDP | CHANNEL_OPTION_COMPRESS_RDP | CHANNEL_OPTION_SHOW_PROTOCOL) FreeRDP-1.0.2/channels/cliprdr/cliprdr_main.h000066400000000000000000000031421207112532300210030ustar00rootroot00000000000000/** * FreeRDP: A Remote Desktop Protocol client. * Clipboard Virtual Channel * * Copyright 2009-2011 Jay Sorg * Copyright 2010-2011 Vic Lee * * 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. */ #ifndef __CLIPRDR_MAIN_H #define __CLIPRDR_MAIN_H #include #include struct _CLIPRDR_FORMAT_NAME { uint32 id; char* name; int length; }; typedef struct _CLIPRDR_FORMAT_NAME CLIPRDR_FORMAT_NAME; struct cliprdr_plugin { rdpSvcPlugin plugin; UNICONV* uniconv; boolean received_caps; boolean use_long_format_names; boolean stream_fileclip_enabled; boolean fileclip_no_file_paths; boolean can_lock_clipdata; CLIPRDR_FORMAT_NAME* format_names; int num_format_names; }; typedef struct cliprdr_plugin cliprdrPlugin; STREAM* cliprdr_packet_new(uint16 msgType, uint16 msgFlags, uint32 dataLen); void cliprdr_packet_send(cliprdrPlugin* cliprdr, STREAM* data_out); #ifdef WITH_DEBUG_CLIPRDR #define DEBUG_CLIPRDR(fmt, ...) DEBUG_CLASS(CLIPRDR, fmt, ## __VA_ARGS__) #else #define DEBUG_CLIPRDR(fmt, ...) DEBUG_NULL(fmt, ## __VA_ARGS__) #endif #endif /* __CLIPRDR_MAIN_H */ FreeRDP-1.0.2/channels/drdynvc/000077500000000000000000000000001207112532300162015ustar00rootroot00000000000000FreeRDP-1.0.2/channels/drdynvc/CMakeLists.txt000066400000000000000000000021441207112532300207420ustar00rootroot00000000000000# FreeRDP: A Remote Desktop Protocol Client # FreeRDP cmake build script # # Copyright 2011 O.S. Systems Software Ltda. # Copyright 2011 Otavio Salvador # Copyright 2011 Marc-Andre Moreau # # 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(DRDYNVC_SRCS drdynvc_main.c drdynvc_main.h drdynvc_types.h dvcman.c dvcman.h ) add_library(drdynvc ${DRDYNVC_SRCS}) set_target_properties(drdynvc PROPERTIES PREFIX "") target_link_libraries(drdynvc freerdp-utils) install(TARGETS drdynvc DESTINATION ${FREERDP_PLUGIN_PATH}) add_subdirectory(tsmf) add_subdirectory(audin) FreeRDP-1.0.2/channels/drdynvc/audin/000077500000000000000000000000001207112532300173015ustar00rootroot00000000000000FreeRDP-1.0.2/channels/drdynvc/audin/CMakeLists.txt000066400000000000000000000021751207112532300220460ustar00rootroot00000000000000# FreeRDP: A Remote Desktop Protocol Client # FreeRDP cmake build script # # Copyright 2011 O.S. Systems Software Ltda. # Copyright 2011 Otavio Salvador # Copyright 2011 Marc-Andre Moreau # # 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(AUDIN_SRCS audin_main.c audin_main.h ) include_directories(..) add_library(audin ${AUDIN_SRCS}) set_target_properties(audin PROPERTIES PREFIX "") target_link_libraries(audin freerdp-utils) install(TARGETS audin DESTINATION ${FREERDP_PLUGIN_PATH}) if(WITH_ALSA) add_subdirectory(alsa) endif() if(WITH_PULSEAUDIO) add_subdirectory(pulse) endif() FreeRDP-1.0.2/channels/drdynvc/audin/alsa/000077500000000000000000000000001207112532300202215ustar00rootroot00000000000000FreeRDP-1.0.2/channels/drdynvc/audin/alsa/CMakeLists.txt000066400000000000000000000022051207112532300227600ustar00rootroot00000000000000# FreeRDP: A Remote Desktop Protocol Client # FreeRDP cmake build script # # Copyright 2011 O.S. Systems Software Ltda. # Copyright 2011 Otavio Salvador # Copyright 2011 Marc-Andre Moreau # # 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(AUDIN_ALSA_SRCS audin_alsa.c ) include_directories(..) include_directories(${ALSA_INCLUDE_DIRS}) add_library(audin_alsa ${AUDIN_ALSA_SRCS}) set_target_properties(audin_alsa PROPERTIES PREFIX "") target_link_libraries(audin_alsa freerdp-utils) target_link_libraries(audin_alsa ${ALSA_LIBRARIES}) install(TARGETS audin_alsa DESTINATION ${FREERDP_PLUGIN_PATH}) FreeRDP-1.0.2/channels/drdynvc/audin/alsa/audin_alsa.c000066400000000000000000000224471207112532300224760ustar00rootroot00000000000000/** * FreeRDP: A Remote Desktop Protocol client. * Audio Input Redirection Virtual Channel - ALSA implementation * * Copyright 2010-2011 Vic Lee * * 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. */ #include #include #include #include #include #include #include #include "audin_main.h" typedef struct _AudinALSADevice { IAudinDevice iface; char device_name[32]; uint32 frames_per_packet; uint32 target_rate; uint32 actual_rate; snd_pcm_format_t format; uint32 target_channels; uint32 actual_channels; int bytes_per_channel; int wformat; int block_size; ADPCM adpcm; freerdp_thread* thread; uint8* buffer; int buffer_frames; AudinReceive receive; void* user_data; } AudinALSADevice; static boolean audin_alsa_set_params(AudinALSADevice* alsa, snd_pcm_t* capture_handle) { int error; snd_pcm_hw_params_t* hw_params; if ((error = snd_pcm_hw_params_malloc(&hw_params)) < 0) { DEBUG_WARN("snd_pcm_hw_params_malloc (%s)", snd_strerror(error)); return false; } snd_pcm_hw_params_any(capture_handle, hw_params); snd_pcm_hw_params_set_access(capture_handle, hw_params, SND_PCM_ACCESS_RW_INTERLEAVED); snd_pcm_hw_params_set_format(capture_handle, hw_params, alsa->format); snd_pcm_hw_params_set_rate_near(capture_handle, hw_params, &alsa->actual_rate, NULL); snd_pcm_hw_params_set_channels_near(capture_handle, hw_params, &alsa->actual_channels); snd_pcm_hw_params(capture_handle, hw_params); snd_pcm_hw_params_free(hw_params); snd_pcm_prepare(capture_handle); if ((alsa->actual_rate != alsa->target_rate) || (alsa->actual_channels != alsa->target_channels)) { DEBUG_DVC("actual rate %d / channel %d is " "different from target rate %d / channel %d, resampling required.", alsa->actual_rate, alsa->actual_channels, alsa->target_rate, alsa->target_channels); } return true; } static boolean audin_alsa_thread_receive(AudinALSADevice* alsa, uint8* src, int size) { int frames; int cframes; int ret = 0; int encoded_size; uint8* encoded_data; int rbytes_per_frame; int tbytes_per_frame; uint8* resampled_data; rbytes_per_frame = alsa->actual_channels * alsa->bytes_per_channel; tbytes_per_frame = alsa->target_channels * alsa->bytes_per_channel; if ((alsa->target_rate == alsa->actual_rate) && (alsa->target_channels == alsa->actual_channels)) { resampled_data = NULL; frames = size / rbytes_per_frame; } else { resampled_data = dsp_resample(src, alsa->bytes_per_channel, alsa->actual_channels, alsa->actual_rate, size / rbytes_per_frame, alsa->target_channels, alsa->target_rate, &frames); DEBUG_DVC("resampled %d frames at %d to %d frames at %d", size / rbytes_per_frame, alsa->actual_rate, frames, alsa->target_rate); size = frames * tbytes_per_frame; src = resampled_data; } while (frames > 0) { if (freerdp_thread_is_stopped(alsa->thread)) break; cframes = alsa->frames_per_packet - alsa->buffer_frames; if (cframes > frames) cframes = frames; memcpy(alsa->buffer + alsa->buffer_frames * tbytes_per_frame, src, cframes * tbytes_per_frame); alsa->buffer_frames += cframes; if (alsa->buffer_frames >= alsa->frames_per_packet) { if (alsa->wformat == 0x11) { encoded_data = dsp_encode_ima_adpcm(&alsa->adpcm, alsa->buffer, alsa->buffer_frames * tbytes_per_frame, alsa->target_channels, alsa->block_size, &encoded_size); DEBUG_DVC("encoded %d to %d", alsa->buffer_frames * tbytes_per_frame, encoded_size); } else { encoded_data = alsa->buffer; encoded_size = alsa->buffer_frames * tbytes_per_frame; } if (freerdp_thread_is_stopped(alsa->thread)) { ret = 0; frames = 0; } else ret = alsa->receive(encoded_data, encoded_size, alsa->user_data); alsa->buffer_frames = 0; if (encoded_data != alsa->buffer) xfree(encoded_data); if (!ret) break; } src += cframes * tbytes_per_frame; frames -= cframes; } if (resampled_data) xfree(resampled_data); return ret; } static void* audin_alsa_thread_func(void* arg) { int error; uint8* buffer; int rbytes_per_frame; int tbytes_per_frame; snd_pcm_t* capture_handle = NULL; AudinALSADevice* alsa = (AudinALSADevice*) arg; DEBUG_DVC("in"); rbytes_per_frame = alsa->actual_channels * alsa->bytes_per_channel; tbytes_per_frame = alsa->target_channels * alsa->bytes_per_channel; alsa->buffer = (uint8*) xzalloc(tbytes_per_frame * alsa->frames_per_packet); alsa->buffer_frames = 0; buffer = (uint8*) xzalloc(rbytes_per_frame * alsa->frames_per_packet); memset(&alsa->adpcm, 0, sizeof(ADPCM)); do { if ((error = snd_pcm_open(&capture_handle, alsa->device_name, SND_PCM_STREAM_CAPTURE, 0)) < 0) { DEBUG_WARN("snd_pcm_open (%s)", snd_strerror(error)); break; } if (!audin_alsa_set_params(alsa, capture_handle)) { break; } while (!freerdp_thread_is_stopped(alsa->thread)) { error = snd_pcm_readi(capture_handle, buffer, alsa->frames_per_packet); if (error == -EPIPE) { snd_pcm_recover(capture_handle, error, 0); continue; } else if (error < 0) { DEBUG_WARN("snd_pcm_readi (%s)", snd_strerror(error)); break; } if (!audin_alsa_thread_receive(alsa, buffer, error * rbytes_per_frame)) break; } } while (0); xfree(buffer); xfree(alsa->buffer); alsa->buffer = NULL; if (capture_handle) snd_pcm_close(capture_handle); freerdp_thread_quit(alsa->thread); DEBUG_DVC("out"); return NULL; } static void audin_alsa_free(IAudinDevice* device) { AudinALSADevice* alsa = (AudinALSADevice*) device; freerdp_thread_free(alsa->thread); xfree(alsa); } static boolean audin_alsa_format_supported(IAudinDevice* device, audinFormat* format) { switch (format->wFormatTag) { case 1: /* PCM */ if (format->cbSize == 0 && (format->nSamplesPerSec <= 48000) && (format->wBitsPerSample == 8 || format->wBitsPerSample == 16) && (format->nChannels == 1 || format->nChannels == 2)) { return true; } break; case 0x11: /* IMA ADPCM */ if ((format->nSamplesPerSec <= 48000) && (format->wBitsPerSample == 4) && (format->nChannels == 1 || format->nChannels == 2)) { return true; } break; } return false; } static void audin_alsa_set_format(IAudinDevice* device, audinFormat* format, uint32 FramesPerPacket) { int bs; AudinALSADevice* alsa = (AudinALSADevice*) device; alsa->target_rate = format->nSamplesPerSec; alsa->actual_rate = format->nSamplesPerSec; alsa->target_channels = format->nChannels; alsa->actual_channels = format->nChannels; switch (format->wFormatTag) { case 1: /* PCM */ switch (format->wBitsPerSample) { case 8: alsa->format = SND_PCM_FORMAT_S8; alsa->bytes_per_channel = 1; break; case 16: alsa->format = SND_PCM_FORMAT_S16_LE; alsa->bytes_per_channel = 2; break; } break; case 0x11: /* IMA ADPCM */ alsa->format = SND_PCM_FORMAT_S16_LE; alsa->bytes_per_channel = 2; bs = (format->nBlockAlign - 4 * format->nChannels) * 4; alsa->frames_per_packet = (alsa->frames_per_packet * format->nChannels * 2 / bs + 1) * bs / (format->nChannels * 2); DEBUG_DVC("aligned FramesPerPacket=%d", alsa->frames_per_packet); break; } alsa->wformat = format->wFormatTag; alsa->block_size = format->nBlockAlign; } static void audin_alsa_open(IAudinDevice* device, AudinReceive receive, void* user_data) { AudinALSADevice* alsa = (AudinALSADevice*) device; DEBUG_DVC(""); alsa->receive = receive; alsa->user_data = user_data; freerdp_thread_start(alsa->thread, audin_alsa_thread_func, alsa); } static void audin_alsa_close(IAudinDevice* device) { AudinALSADevice* alsa = (AudinALSADevice*) device; DEBUG_DVC(""); freerdp_thread_stop(alsa->thread); alsa->receive = NULL; alsa->user_data = NULL; } int FreeRDPAudinDeviceEntry(PFREERDP_AUDIN_DEVICE_ENTRY_POINTS pEntryPoints) { AudinALSADevice* alsa; RDP_PLUGIN_DATA* data; alsa = xnew(AudinALSADevice); alsa->iface.Open = audin_alsa_open; alsa->iface.FormatSupported = audin_alsa_format_supported; alsa->iface.SetFormat = audin_alsa_set_format; alsa->iface.Close = audin_alsa_close; alsa->iface.Free = audin_alsa_free; data = pEntryPoints->plugin_data; if (data && data->data[0] && strcmp(data->data[0], "audin") == 0 && data->data[1] && strcmp(data->data[1], "alsa") == 0) { if (data[2].size) strncpy(alsa->device_name, (char*)data->data[2], sizeof(alsa->device_name)); } if (alsa->device_name[0] == '\0') { strcpy(alsa->device_name, "default"); } alsa->frames_per_packet = 128; alsa->target_rate = 22050; alsa->actual_rate = 22050; alsa->format = SND_PCM_FORMAT_S16_LE; alsa->target_channels = 2; alsa->actual_channels = 2; alsa->bytes_per_channel = 2; alsa->thread = freerdp_thread_new(); pEntryPoints->pRegisterAudinDevice(pEntryPoints->plugin, (IAudinDevice*) alsa); return 0; } FreeRDP-1.0.2/channels/drdynvc/audin/audin_main.c000066400000000000000000000344741207112532300215650ustar00rootroot00000000000000/** * FreeRDP: A Remote Desktop Protocol client. * Audio Input Redirection Virtual Channel * * Copyright 2010-2011 Vic Lee * * 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. */ #include #include #include #include #include #include #include "audin_main.h" #define MSG_SNDIN_VERSION 0x01 #define MSG_SNDIN_FORMATS 0x02 #define MSG_SNDIN_OPEN 0x03 #define MSG_SNDIN_OPEN_REPLY 0x04 #define MSG_SNDIN_DATA_INCOMING 0x05 #define MSG_SNDIN_DATA 0x06 #define MSG_SNDIN_FORMATCHANGE 0x07 typedef struct _AUDIN_LISTENER_CALLBACK AUDIN_LISTENER_CALLBACK; struct _AUDIN_LISTENER_CALLBACK { IWTSListenerCallback iface; IWTSPlugin* plugin; IWTSVirtualChannelManager* channel_mgr; }; typedef struct _AUDIN_CHANNEL_CALLBACK AUDIN_CHANNEL_CALLBACK; struct _AUDIN_CHANNEL_CALLBACK { IWTSVirtualChannelCallback iface; IWTSPlugin* plugin; IWTSVirtualChannelManager* channel_mgr; IWTSVirtualChannel* channel; /** * The supported format list sent back to the server, which needs to * be stored as reference when the server sends the format index in * Open PDU and Format Change PDU */ audinFormat* formats; int formats_count; }; typedef struct _AUDIN_PLUGIN AUDIN_PLUGIN; struct _AUDIN_PLUGIN { IWTSPlugin iface; AUDIN_LISTENER_CALLBACK* listener_callback; /* Parsed plugin data */ uint16 fixed_format; uint16 fixed_channel; uint32 fixed_rate; /* Device interface */ IAudinDevice* device; }; static int audin_process_version(IWTSVirtualChannelCallback* pChannelCallback, STREAM* s) { int error; STREAM* out; uint32 Version; AUDIN_CHANNEL_CALLBACK* callback = (AUDIN_CHANNEL_CALLBACK*) pChannelCallback; stream_read_uint32(s, Version); DEBUG_DVC("Version=%d", Version); out = stream_new(5); stream_write_uint8(out, MSG_SNDIN_VERSION); stream_write_uint32(out, Version); error = callback->channel->Write(callback->channel, stream_get_length(s), stream_get_head(s), NULL); stream_free(out); return error; } static int audin_send_incoming_data_pdu(IWTSVirtualChannelCallback* pChannelCallback) { uint8 out_data[1]; AUDIN_CHANNEL_CALLBACK* callback = (AUDIN_CHANNEL_CALLBACK*) pChannelCallback; out_data[0] = MSG_SNDIN_DATA_INCOMING; return callback->channel->Write(callback->channel, 1, out_data, NULL); } static int audin_process_formats(IWTSVirtualChannelCallback* pChannelCallback, STREAM* s) { AUDIN_CHANNEL_CALLBACK* callback = (AUDIN_CHANNEL_CALLBACK*) pChannelCallback; AUDIN_PLUGIN* audin = (AUDIN_PLUGIN*) callback->plugin; uint32 i; uint8* fm; int error; STREAM* out; uint32 NumFormats; audinFormat format; uint32 cbSizeFormatsPacket; stream_read_uint32(s, NumFormats); DEBUG_DVC("NumFormats %d", NumFormats); if ((NumFormats < 1) || (NumFormats > 1000)) { DEBUG_WARN("bad NumFormats %d", NumFormats); return 1; } stream_seek_uint32(s); /* cbSizeFormatsPacket */ callback->formats = (audinFormat*) xzalloc(NumFormats * sizeof(audinFormat)); out = stream_new(9); stream_seek(out, 9); /* SoundFormats (variable) */ for (i = 0; i < NumFormats; i++) { stream_get_mark(s, fm); stream_read_uint16(s, format.wFormatTag); stream_read_uint16(s, format.nChannels); stream_read_uint32(s, format.nSamplesPerSec); stream_seek_uint32(s); /* nAvgBytesPerSec */ stream_read_uint16(s, format.nBlockAlign); stream_read_uint16(s, format.wBitsPerSample); stream_read_uint16(s, format.cbSize); format.data = stream_get_tail(s); stream_seek(s, format.cbSize); DEBUG_DVC("wFormatTag=%d nChannels=%d nSamplesPerSec=%d " "nBlockAlign=%d wBitsPerSample=%d cbSize=%d", format.wFormatTag, format.nChannels, format.nSamplesPerSec, format.nBlockAlign, format.wBitsPerSample, format.cbSize); if (audin->fixed_format > 0 && audin->fixed_format != format.wFormatTag) continue; if (audin->fixed_channel > 0 && audin->fixed_channel != format.nChannels) continue; if (audin->fixed_rate > 0 && audin->fixed_rate != format.nSamplesPerSec) continue; if (audin->device && audin->device->FormatSupported(audin->device, &format)) { DEBUG_DVC("format ok"); /* Store the agreed format in the corresponding index */ callback->formats[callback->formats_count++] = format; /* Put the format to output buffer */ stream_check_size(out, 18 + format.cbSize); stream_write(out, fm, 18 + format.cbSize); } } audin_send_incoming_data_pdu(pChannelCallback); cbSizeFormatsPacket = stream_get_pos(out); stream_set_pos(out, 0); stream_write_uint8(out, MSG_SNDIN_FORMATS); /* Header (1 byte) */ stream_write_uint32(out, callback->formats_count); /* NumFormats (4 bytes) */ stream_write_uint32(out, cbSizeFormatsPacket); /* cbSizeFormatsPacket (4 bytes) */ error = callback->channel->Write(callback->channel, cbSizeFormatsPacket, stream_get_head(out), NULL); stream_free(out); return error; } static int audin_send_format_change_pdu(IWTSVirtualChannelCallback* pChannelCallback, uint32 NewFormat) { int error; STREAM* out; AUDIN_CHANNEL_CALLBACK* callback = (AUDIN_CHANNEL_CALLBACK*) pChannelCallback; out = stream_new(5); stream_write_uint8(out, MSG_SNDIN_FORMATCHANGE); stream_write_uint32(out, NewFormat); error = callback->channel->Write(callback->channel, 5, stream_get_head(out), NULL); stream_free(out); return error; } static int audin_send_open_reply_pdu(IWTSVirtualChannelCallback* pChannelCallback, uint32 Result) { int error; STREAM* out; AUDIN_CHANNEL_CALLBACK* callback = (AUDIN_CHANNEL_CALLBACK*) pChannelCallback; out = stream_new(5); stream_write_uint8(out, MSG_SNDIN_OPEN_REPLY); stream_write_uint32(out, Result); error = callback->channel->Write(callback->channel, 5, stream_get_head(out), NULL); stream_free(out); return error; } static boolean audin_receive_wave_data(uint8* data, int size, void* user_data) { int error; STREAM* out; AUDIN_CHANNEL_CALLBACK* callback = (AUDIN_CHANNEL_CALLBACK*) user_data; error = audin_send_incoming_data_pdu((IWTSVirtualChannelCallback*) callback); if (error != 0) return false; out = stream_new(size + 1); stream_write_uint8(out, MSG_SNDIN_DATA); stream_write(out, data, size); error = callback->channel->Write(callback->channel, stream_get_length(out), stream_get_head(out), NULL); stream_free(out); return (error == 0 ? true : false); } static int audin_process_open(IWTSVirtualChannelCallback* pChannelCallback, STREAM* s) { AUDIN_CHANNEL_CALLBACK* callback = (AUDIN_CHANNEL_CALLBACK*) pChannelCallback; AUDIN_PLUGIN* audin = (AUDIN_PLUGIN*) callback->plugin; audinFormat* format; uint32 initialFormat; uint32 FramesPerPacket; stream_read_uint32(s, FramesPerPacket); stream_read_uint32(s, initialFormat); DEBUG_DVC("FramesPerPacket=%d initialFormat=%d", FramesPerPacket, initialFormat); if (initialFormat >= callback->formats_count) { DEBUG_WARN("invalid format index %d (total %d)", initialFormat, callback->formats_count); return 1; } format = &callback->formats[initialFormat]; if (audin->device) { IFCALL(audin->device->SetFormat, audin->device, format, FramesPerPacket); IFCALL(audin->device->Open, audin->device, audin_receive_wave_data, callback); } audin_send_format_change_pdu(pChannelCallback, initialFormat); audin_send_open_reply_pdu(pChannelCallback, 0); return 0; } static int audin_process_format_change(IWTSVirtualChannelCallback* pChannelCallback, STREAM* s) { AUDIN_CHANNEL_CALLBACK* callback = (AUDIN_CHANNEL_CALLBACK*) pChannelCallback; AUDIN_PLUGIN * audin = (AUDIN_PLUGIN*) callback->plugin; uint32 NewFormat; audinFormat* format; stream_read_uint32(s, NewFormat); DEBUG_DVC("NewFormat=%d", NewFormat); if (NewFormat >= callback->formats_count) { DEBUG_WARN("invalid format index %d (total %d)", NewFormat, callback->formats_count); return 1; } format = &callback->formats[NewFormat]; if (audin->device) { IFCALL(audin->device->Close, audin->device); IFCALL(audin->device->SetFormat, audin->device, format, 0); IFCALL(audin->device->Open, audin->device, audin_receive_wave_data, callback); } audin_send_format_change_pdu(pChannelCallback, NewFormat); return 0; } static int audin_on_data_received(IWTSVirtualChannelCallback* pChannelCallback, uint32 cbSize, uint8* pBuffer) { int error; STREAM* s; uint8 MessageId; s = stream_new(0); stream_attach(s, pBuffer, cbSize); stream_read_uint8(s, MessageId); DEBUG_DVC("MessageId=0x%x", MessageId); switch (MessageId) { case MSG_SNDIN_VERSION: error = audin_process_version(pChannelCallback, s); break; case MSG_SNDIN_FORMATS: error = audin_process_formats(pChannelCallback, s); break; case MSG_SNDIN_OPEN: error = audin_process_open(pChannelCallback, s); break; case MSG_SNDIN_FORMATCHANGE: error = audin_process_format_change(pChannelCallback, s); break; default: DEBUG_WARN("unknown MessageId=0x%x", MessageId); error = 1; break; } stream_detach(s); stream_free(s); return error; } static int audin_on_close(IWTSVirtualChannelCallback* pChannelCallback) { AUDIN_CHANNEL_CALLBACK* callback = (AUDIN_CHANNEL_CALLBACK*) pChannelCallback; AUDIN_PLUGIN* audin = (AUDIN_PLUGIN*) callback->plugin; DEBUG_DVC(""); if (audin->device) IFCALL(audin->device->Close, audin->device); xfree(callback->formats); xfree(callback); return 0; } static int audin_on_new_channel_connection(IWTSListenerCallback* pListenerCallback, IWTSVirtualChannel* pChannel, uint8* Data, int* pbAccept, IWTSVirtualChannelCallback** ppCallback) { AUDIN_CHANNEL_CALLBACK* callback; AUDIN_LISTENER_CALLBACK* listener_callback = (AUDIN_LISTENER_CALLBACK*) pListenerCallback; DEBUG_DVC(""); callback = xnew(AUDIN_CHANNEL_CALLBACK); callback->iface.OnDataReceived = audin_on_data_received; callback->iface.OnClose = audin_on_close; callback->plugin = listener_callback->plugin; callback->channel_mgr = listener_callback->channel_mgr; callback->channel = pChannel; *ppCallback = (IWTSVirtualChannelCallback*) callback; return 0; } static int audin_plugin_initialize(IWTSPlugin* pPlugin, IWTSVirtualChannelManager* pChannelMgr) { AUDIN_PLUGIN* audin = (AUDIN_PLUGIN*) pPlugin; DEBUG_DVC(""); audin->listener_callback = xnew(AUDIN_LISTENER_CALLBACK); audin->listener_callback->iface.OnNewChannelConnection = audin_on_new_channel_connection; audin->listener_callback->plugin = pPlugin; audin->listener_callback->channel_mgr = pChannelMgr; return pChannelMgr->CreateListener(pChannelMgr, "AUDIO_INPUT", 0, (IWTSListenerCallback*) audin->listener_callback, NULL); } static int audin_plugin_terminated(IWTSPlugin* pPlugin) { AUDIN_PLUGIN* audin = (AUDIN_PLUGIN*) pPlugin; DEBUG_DVC(""); if (audin->device) { IFCALL(audin->device->Close, audin->device); IFCALL(audin->device->Free, audin->device); audin->device = NULL; } xfree(audin->listener_callback); xfree(audin); return 0; } static void audin_register_device_plugin(IWTSPlugin* pPlugin, IAudinDevice* device) { AUDIN_PLUGIN* audin = (AUDIN_PLUGIN*) pPlugin; if (audin->device) { DEBUG_WARN("existing device, abort."); return; } DEBUG_DVC("device registered."); audin->device = device; } static boolean audin_load_device_plugin(IWTSPlugin* pPlugin, const char* name, RDP_PLUGIN_DATA* data) { char* fullname; PFREERDP_AUDIN_DEVICE_ENTRY entry; FREERDP_AUDIN_DEVICE_ENTRY_POINTS entryPoints; if (strrchr(name, '.') != NULL) { entry = (PFREERDP_AUDIN_DEVICE_ENTRY) freerdp_load_plugin(name, AUDIN_DEVICE_EXPORT_FUNC_NAME); } else { fullname = xzalloc(strlen(name) + 8); strcpy(fullname, "audin_"); strcat(fullname, name); entry = (PFREERDP_AUDIN_DEVICE_ENTRY) freerdp_load_plugin(fullname, AUDIN_DEVICE_EXPORT_FUNC_NAME); xfree(fullname); } if (entry == NULL) return false; entryPoints.plugin = pPlugin; entryPoints.pRegisterAudinDevice = audin_register_device_plugin; entryPoints.plugin_data = data; if (entry(&entryPoints) != 0) { DEBUG_WARN("%s entry returns error.", name); return false; } return true; } static boolean audin_process_plugin_data(IWTSPlugin* pPlugin, RDP_PLUGIN_DATA* data) { boolean ret; AUDIN_PLUGIN* audin = (AUDIN_PLUGIN*) pPlugin; RDP_PLUGIN_DATA default_data[2] = { { 0 }, { 0 } }; if (data->data[0] && (strcmp((char*)data->data[0], "audin") == 0 || strstr((char*) data->data[0], "/audin.") != NULL)) { if (data->data[1] && strcmp((char*)data->data[1], "format") == 0) { audin->fixed_format = atoi(data->data[2]); return true; } else if (data->data[1] && strcmp((char*)data->data[1], "rate") == 0) { audin->fixed_rate = atoi(data->data[2]); return true; } else if (data->data[1] && strcmp((char*)data->data[1], "channel") == 0) { audin->fixed_channel = atoi(data->data[2]); return true; } else if (data->data[1] && ((char*)data->data[1])[0]) { return audin_load_device_plugin(pPlugin, (char*) data->data[1], data); } else { default_data[0].size = sizeof(RDP_PLUGIN_DATA); default_data[0].data[0] = "audin"; default_data[0].data[1] = "pulse"; default_data[0].data[2] = ""; ret = audin_load_device_plugin(pPlugin, "pulse", default_data); if (!ret) { default_data[0].size = sizeof(RDP_PLUGIN_DATA); default_data[0].data[0] = "audin"; default_data[0].data[1] = "alsa"; default_data[0].data[2] = "default"; ret = audin_load_device_plugin(pPlugin, "alsa", default_data); } return ret; } } return true; } int DVCPluginEntry(IDRDYNVC_ENTRY_POINTS* pEntryPoints) { int error = 0; AUDIN_PLUGIN* audin; audin = (AUDIN_PLUGIN*) pEntryPoints->GetPlugin(pEntryPoints, "audin"); if (audin == NULL) { audin = xnew(AUDIN_PLUGIN); audin->iface.Initialize = audin_plugin_initialize; audin->iface.Connected = NULL; audin->iface.Disconnected = NULL; audin->iface.Terminated = audin_plugin_terminated; error = pEntryPoints->RegisterPlugin(pEntryPoints, "audin", (IWTSPlugin*) audin); } if (error == 0) audin_process_plugin_data((IWTSPlugin*) audin, pEntryPoints->GetPluginData(pEntryPoints)); return error; } FreeRDP-1.0.2/channels/drdynvc/audin/audin_main.h000066400000000000000000000037461207112532300215700ustar00rootroot00000000000000/** * FreeRDP: A Remote Desktop Protocol client. * Audio Input Redirection Virtual Channel * * Copyright 2010-2011 Vic Lee * * 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. */ #ifndef __AUDIN_MAIN_H #define __AUDIN_MAIN_H #include "drdynvc_types.h" typedef boolean (*AudinReceive) (uint8* data, int size, void* user_data); typedef struct audin_format audinFormat; struct audin_format { uint16 wFormatTag; uint16 nChannels; uint32 nSamplesPerSec; uint16 nBlockAlign; uint16 wBitsPerSample; uint16 cbSize; uint8* data; }; typedef struct _IAudinDevice IAudinDevice; struct _IAudinDevice { void (*Open) (IAudinDevice* devplugin, AudinReceive receive, void* user_data); boolean (*FormatSupported) (IAudinDevice* devplugin, audinFormat* format); void (*SetFormat) (IAudinDevice* devplugin, audinFormat* format, uint32 FramesPerPacket); void (*Close) (IAudinDevice* devplugin); void (*Free) (IAudinDevice* devplugin); }; #define AUDIN_DEVICE_EXPORT_FUNC_NAME "FreeRDPAudinDeviceEntry" typedef void (*PREGISTERAUDINDEVICE)(IWTSPlugin* plugin, IAudinDevice* device); struct _FREERDP_AUDIN_DEVICE_ENTRY_POINTS { IWTSPlugin* plugin; PREGISTERAUDINDEVICE pRegisterAudinDevice; RDP_PLUGIN_DATA* plugin_data; }; typedef struct _FREERDP_AUDIN_DEVICE_ENTRY_POINTS FREERDP_AUDIN_DEVICE_ENTRY_POINTS; typedef FREERDP_AUDIN_DEVICE_ENTRY_POINTS* PFREERDP_AUDIN_DEVICE_ENTRY_POINTS; typedef int (*PFREERDP_AUDIN_DEVICE_ENTRY)(PFREERDP_AUDIN_DEVICE_ENTRY_POINTS pEntryPoints); #endif /* __AUDIN_MAIN_H */ FreeRDP-1.0.2/channels/drdynvc/audin/pulse/000077500000000000000000000000001207112532300204315ustar00rootroot00000000000000FreeRDP-1.0.2/channels/drdynvc/audin/pulse/CMakeLists.txt000066400000000000000000000022231207112532300231700ustar00rootroot00000000000000# FreeRDP: A Remote Desktop Protocol Client # FreeRDP cmake build script # # Copyright 2011 O.S. Systems Software Ltda. # Copyright 2011 Otavio Salvador # Copyright 2011 Marc-Andre Moreau # # 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(AUDIN_PULSE_SRCS audin_pulse.c ) include_directories(..) include_directories(${PULSE_INCLUDE_DIRS}) add_library(audin_pulse ${AUDIN_PULSE_SRCS}) set_target_properties(audin_pulse PROPERTIES PREFIX "") target_link_libraries(audin_pulse freerdp-utils) target_link_libraries(audin_pulse ${PULSEAUDIO_LIBRARY}) install(TARGETS audin_pulse DESTINATION ${FREERDP_PLUGIN_PATH}) FreeRDP-1.0.2/channels/drdynvc/audin/pulse/audin_pulse.c000066400000000000000000000266301207112532300231140ustar00rootroot00000000000000/** * FreeRDP: A Remote Desktop Protocol client. * Audio Input Redirection Virtual Channel - PulseAudio implementation * * Copyright 2010-2011 Vic Lee * * 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. */ #include #include #include #include #include #include #include #include "audin_main.h" typedef struct _AudinPulseDevice { IAudinDevice iface; char device_name[32]; uint32 frames_per_packet; pa_threaded_mainloop* mainloop; pa_context* context; pa_sample_spec sample_spec; pa_stream* stream; int format; int block_size; ADPCM adpcm; int bytes_per_frame; uint8* buffer; int buffer_frames; AudinReceive receive; void* user_data; } AudinPulseDevice; static void audin_pulse_context_state_callback(pa_context* context, void* userdata) { pa_context_state_t state; AudinPulseDevice* pulse = (AudinPulseDevice*) userdata; state = pa_context_get_state(context); switch (state) { case PA_CONTEXT_READY: DEBUG_DVC("PA_CONTEXT_READY"); pa_threaded_mainloop_signal (pulse->mainloop, 0); break; case PA_CONTEXT_FAILED: case PA_CONTEXT_TERMINATED: DEBUG_DVC("state %d", (int)state); pa_threaded_mainloop_signal (pulse->mainloop, 0); break; default: DEBUG_DVC("state %d", (int)state); break; } } static boolean audin_pulse_connect(IAudinDevice* device) { pa_context_state_t state; AudinPulseDevice* pulse = (AudinPulseDevice*) device; if (!pulse->context) return false; if (pa_context_connect(pulse->context, NULL, 0, NULL)) { DEBUG_WARN("pa_context_connect failed (%d)", pa_context_errno(pulse->context)); return false; } pa_threaded_mainloop_lock(pulse->mainloop); if (pa_threaded_mainloop_start(pulse->mainloop) < 0) { pa_threaded_mainloop_unlock(pulse->mainloop); DEBUG_WARN("pa_threaded_mainloop_start failed (%d)", pa_context_errno(pulse->context)); return false; } for (;;) { state = pa_context_get_state(pulse->context); if (state == PA_CONTEXT_READY) break; if (!PA_CONTEXT_IS_GOOD(state)) { DEBUG_WARN("bad context state (%d)", pa_context_errno(pulse->context)); break; } pa_threaded_mainloop_wait(pulse->mainloop); } pa_threaded_mainloop_unlock(pulse->mainloop); if (state == PA_CONTEXT_READY) { DEBUG_DVC("connected"); return true; } else { pa_context_disconnect(pulse->context); return false; } } static void audin_pulse_free(IAudinDevice* device) { AudinPulseDevice* pulse = (AudinPulseDevice*) device; DEBUG_DVC(""); if (!pulse) return; if (pulse->mainloop) { pa_threaded_mainloop_stop(pulse->mainloop); } if (pulse->context) { pa_context_disconnect(pulse->context); pa_context_unref(pulse->context); pulse->context = NULL; } if (pulse->mainloop) { pa_threaded_mainloop_free(pulse->mainloop); pulse->mainloop = NULL; } xfree(pulse); } static boolean audin_pulse_format_supported(IAudinDevice* device, audinFormat* format) { AudinPulseDevice* pulse = (AudinPulseDevice*) device; if (!pulse->context) return 0; switch (format->wFormatTag) { case 1: /* PCM */ if (format->cbSize == 0 && (format->nSamplesPerSec <= PA_RATE_MAX) && (format->wBitsPerSample == 8 || format->wBitsPerSample == 16) && (format->nChannels >= 1 && format->nChannels <= PA_CHANNELS_MAX)) { return true; } break; case 6: /* A-LAW */ case 7: /* U-LAW */ if (format->cbSize == 0 && (format->nSamplesPerSec <= PA_RATE_MAX) && (format->wBitsPerSample == 8) && (format->nChannels >= 1 && format->nChannels <= PA_CHANNELS_MAX)) { return true; } break; case 0x11: /* IMA ADPCM */ if ((format->nSamplesPerSec <= PA_RATE_MAX) && (format->wBitsPerSample == 4) && (format->nChannels == 1 || format->nChannels == 2)) { return true; } break; } return false; } static void audin_pulse_set_format(IAudinDevice* device, audinFormat* format, uint32 FramesPerPacket) { int bs; pa_sample_spec sample_spec = { 0 }; AudinPulseDevice* pulse = (AudinPulseDevice*) device; if (!pulse->context) return; if (FramesPerPacket > 0) { pulse->frames_per_packet = FramesPerPacket; } sample_spec.rate = format->nSamplesPerSec; sample_spec.channels = format->nChannels; switch (format->wFormatTag) { case 1: /* PCM */ switch (format->wBitsPerSample) { case 8: sample_spec.format = PA_SAMPLE_U8; break; case 16: sample_spec.format = PA_SAMPLE_S16LE; break; } break; case 6: /* A-LAW */ sample_spec.format = PA_SAMPLE_ALAW; break; case 7: /* U-LAW */ sample_spec.format = PA_SAMPLE_ULAW; break; case 0x11: /* IMA ADPCM */ sample_spec.format = PA_SAMPLE_S16LE; bs = (format->nBlockAlign - 4 * format->nChannels) * 4; pulse->frames_per_packet = (pulse->frames_per_packet * format->nChannels * 2 / bs + 1) * bs / (format->nChannels * 2); DEBUG_DVC("aligned FramesPerPacket=%d", pulse->frames_per_packet); break; } pulse->sample_spec = sample_spec; pulse->format = format->wFormatTag; pulse->block_size = format->nBlockAlign; } static void audin_pulse_stream_state_callback(pa_stream* stream, void* userdata) { pa_stream_state_t state; AudinPulseDevice* pulse = (AudinPulseDevice*) userdata; state = pa_stream_get_state(stream); switch (state) { case PA_STREAM_READY: DEBUG_DVC("PA_STREAM_READY"); pa_threaded_mainloop_signal(pulse->mainloop, 0); break; case PA_STREAM_FAILED: case PA_STREAM_TERMINATED: DEBUG_DVC("state %d", (int)state); pa_threaded_mainloop_signal(pulse->mainloop, 0); break; default: DEBUG_DVC("state %d", (int)state); break; } } static void audin_pulse_stream_request_callback(pa_stream* stream, size_t length, void* userdata) { int frames; int cframes; boolean ret; const void* data; const uint8* src; int encoded_size; uint8* encoded_data; AudinPulseDevice* pulse = (AudinPulseDevice*) userdata; pa_stream_peek(stream, &data, &length); frames = length / pulse->bytes_per_frame; DEBUG_DVC("length %d frames %d", (int) length, frames); src = (const uint8*) data; while (frames > 0) { cframes = pulse->frames_per_packet - pulse->buffer_frames; if (cframes > frames) cframes = frames; memcpy(pulse->buffer + pulse->buffer_frames * pulse->bytes_per_frame, src, cframes * pulse->bytes_per_frame); pulse->buffer_frames += cframes; if (pulse->buffer_frames >= pulse->frames_per_packet) { if (pulse->format == 0x11) { encoded_data = dsp_encode_ima_adpcm(&pulse->adpcm, pulse->buffer, pulse->buffer_frames * pulse->bytes_per_frame, pulse->sample_spec.channels, pulse->block_size, &encoded_size); DEBUG_DVC("encoded %d to %d", pulse->buffer_frames * pulse->bytes_per_frame, encoded_size); } else { encoded_data = pulse->buffer; encoded_size = pulse->buffer_frames * pulse->bytes_per_frame; } ret = pulse->receive(encoded_data, encoded_size, pulse->user_data); pulse->buffer_frames = 0; if (encoded_data != pulse->buffer) xfree(encoded_data); if (!ret) break; } src += cframes * pulse->bytes_per_frame; frames -= cframes; } pa_stream_drop(stream); } static void audin_pulse_close(IAudinDevice* device) { AudinPulseDevice* pulse = (AudinPulseDevice*) device; if (!pulse->context || !pulse->stream) return; DEBUG_DVC(""); pa_threaded_mainloop_lock(pulse->mainloop); pa_stream_disconnect(pulse->stream); pa_stream_unref(pulse->stream); pulse->stream = NULL; pa_threaded_mainloop_unlock(pulse->mainloop); pulse->receive = NULL; pulse->user_data = NULL; if (pulse->buffer) { xfree(pulse->buffer); pulse->buffer = NULL; pulse->buffer_frames = 0; } } static void audin_pulse_open(IAudinDevice* device, AudinReceive receive, void* user_data) { pa_stream_state_t state; pa_buffer_attr buffer_attr = { 0 }; AudinPulseDevice* pulse = (AudinPulseDevice*) device; if (!pulse->context) return; if (!pulse->sample_spec.rate || pulse->stream) return; DEBUG_DVC(""); pulse->receive = receive; pulse->user_data = user_data; pa_threaded_mainloop_lock(pulse->mainloop); pulse->stream = pa_stream_new(pulse->context, "freerdp_audin", &pulse->sample_spec, NULL); if (!pulse->stream) { pa_threaded_mainloop_unlock(pulse->mainloop); DEBUG_DVC("pa_stream_new failed (%d)", pa_context_errno(pulse->context)); return; } pulse->bytes_per_frame = pa_frame_size(&pulse->sample_spec); pa_stream_set_state_callback(pulse->stream, audin_pulse_stream_state_callback, pulse); pa_stream_set_read_callback(pulse->stream, audin_pulse_stream_request_callback, pulse); buffer_attr.maxlength = (uint32_t) -1; buffer_attr.tlength = (uint32_t) -1; buffer_attr.prebuf = (uint32_t) -1; buffer_attr.minreq = (uint32_t) -1; /* 500ms latency */ buffer_attr.fragsize = pa_usec_to_bytes(500000, &pulse->sample_spec); if (pa_stream_connect_record(pulse->stream, pulse->device_name[0] ? pulse->device_name : NULL, &buffer_attr, PA_STREAM_ADJUST_LATENCY) < 0) { pa_threaded_mainloop_unlock(pulse->mainloop); DEBUG_WARN("pa_stream_connect_playback failed (%d)", pa_context_errno(pulse->context)); return; } for (;;) { state = pa_stream_get_state(pulse->stream); if (state == PA_STREAM_READY) break; if (!PA_STREAM_IS_GOOD(state)) { DEBUG_WARN("bad stream state (%d)", pa_context_errno(pulse->context)); break; } pa_threaded_mainloop_wait(pulse->mainloop); } pa_threaded_mainloop_unlock(pulse->mainloop); if (state == PA_STREAM_READY) { memset(&pulse->adpcm, 0, sizeof(ADPCM)); pulse->buffer = xzalloc(pulse->bytes_per_frame * pulse->frames_per_packet); pulse->buffer_frames = 0; DEBUG_DVC("connected"); } else { audin_pulse_close(device); } } int FreeRDPAudinDeviceEntry(PFREERDP_AUDIN_DEVICE_ENTRY_POINTS pEntryPoints) { AudinPulseDevice* pulse; RDP_PLUGIN_DATA * data; pulse = xnew(AudinPulseDevice); pulse->iface.Open = audin_pulse_open; pulse->iface.FormatSupported = audin_pulse_format_supported; pulse->iface.SetFormat = audin_pulse_set_format; pulse->iface.Close = audin_pulse_close; pulse->iface.Free = audin_pulse_free; data = pEntryPoints->plugin_data; if (data && data->data[0] && strcmp(data->data[0], "audin") == 0 && data->data[1] && strcmp(data->data[1], "pulse") == 0) { strncpy(pulse->device_name, (char*)data->data[2], sizeof(pulse->device_name)); } pulse->mainloop = pa_threaded_mainloop_new(); if (!pulse->mainloop) { DEBUG_WARN("pa_threaded_mainloop_new failed"); audin_pulse_free((IAudinDevice*) pulse); return 1; } pulse->context = pa_context_new(pa_threaded_mainloop_get_api(pulse->mainloop), "freerdp"); if (!pulse->context) { DEBUG_WARN("pa_context_new failed"); audin_pulse_free((IAudinDevice*) pulse); return 1; } pa_context_set_state_callback(pulse->context, audin_pulse_context_state_callback, pulse); if (!audin_pulse_connect((IAudinDevice*) pulse)) { audin_pulse_free((IAudinDevice*) pulse); return 1; } pEntryPoints->pRegisterAudinDevice(pEntryPoints->plugin, (IAudinDevice*) pulse); return 0; } FreeRDP-1.0.2/channels/drdynvc/drdynvc_main.c000066400000000000000000000206131207112532300210240ustar00rootroot00000000000000/** * FreeRDP: A Remote Desktop Protocol client. * Dynamic Virtual Channel * * Copyright 2010-2011 Vic Lee * * 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. */ #include #include #include #include #include #include #include #include #include "dvcman.h" #include "drdynvc_types.h" #include "drdynvc_main.h" #define CREATE_REQUEST_PDU 0x01 #define DATA_FIRST_PDU 0x02 #define DATA_PDU 0x03 #define CLOSE_REQUEST_PDU 0x04 #define CAPABILITY_REQUEST_PDU 0x05 struct drdynvc_plugin { rdpSvcPlugin plugin; int version; int PriorityCharge0; int PriorityCharge1; int PriorityCharge2; int PriorityCharge3; IWTSVirtualChannelManager* channel_mgr; }; static int drdynvc_write_variable_uint(STREAM* stream, uint32 val) { int cb; if (val <= 0xFF) { cb = 0; stream_write_uint8(stream, val); } else if (val <= 0xFFFF) { cb = 1; stream_write_uint16(stream, val); } else { cb = 3; stream_write_uint32(stream, val); } return cb; } int drdynvc_write_data(drdynvcPlugin* drdynvc, uint32 ChannelId, uint8* data, uint32 data_size) { STREAM* data_out; uint32 pos = 0; uint32 cbChId; uint32 cbLen; uint32 chunk_len; int error; DEBUG_DVC("ChannelId=%d size=%d", ChannelId, data_size); data_out = stream_new(CHANNEL_CHUNK_LENGTH); stream_set_pos(data_out, 1); cbChId = drdynvc_write_variable_uint(data_out, ChannelId); if (data_size <= CHANNEL_CHUNK_LENGTH - pos) { pos = stream_get_pos(data_out); stream_set_pos(data_out, 0); stream_write_uint8(data_out, 0x30 | cbChId); stream_set_pos(data_out, pos); stream_write(data_out, data, data_size); error = svc_plugin_send((rdpSvcPlugin*)drdynvc, data_out); } else { /* Fragment the data */ cbLen = drdynvc_write_variable_uint(data_out, data_size); pos = stream_get_pos(data_out); stream_set_pos(data_out, 0); stream_write_uint8(data_out, 0x20 | cbChId | (cbLen << 2)); stream_set_pos(data_out, pos); chunk_len = CHANNEL_CHUNK_LENGTH - pos; stream_write(data_out, data, chunk_len); data += chunk_len; data_size -= chunk_len; error = svc_plugin_send((rdpSvcPlugin*)drdynvc, data_out); while (error == CHANNEL_RC_OK && data_size > 0) { data_out = stream_new(CHANNEL_CHUNK_LENGTH); stream_set_pos(data_out, 1); cbChId = drdynvc_write_variable_uint(data_out, ChannelId); pos = stream_get_pos(data_out); stream_set_pos(data_out, 0); stream_write_uint8(data_out, 0x30 | cbChId); stream_set_pos(data_out, pos); chunk_len = data_size; if (chunk_len > CHANNEL_CHUNK_LENGTH - pos) chunk_len = CHANNEL_CHUNK_LENGTH - pos; stream_write(data_out, data, chunk_len); data += chunk_len; data_size -= chunk_len; error = svc_plugin_send((rdpSvcPlugin*)drdynvc, data_out); } } if (error != CHANNEL_RC_OK) { DEBUG_WARN("VirtualChannelWrite failed %d", error); return 1; } return 0; } int drdynvc_push_event(drdynvcPlugin* drdynvc, RDP_EVENT* event) { int error; error = svc_plugin_send_event((rdpSvcPlugin*)drdynvc, event); if (error != CHANNEL_RC_OK) { DEBUG_WARN("pVirtualChannelEventPush failed %d", error); return 1; } return 0; } static int drdynvc_process_capability_request(drdynvcPlugin* drdynvc, int Sp, int cbChId, STREAM* s) { STREAM* data_out; int error; DEBUG_DVC("Sp=%d cbChId=%d", Sp, cbChId); stream_seek(s, 1); /* pad */ stream_read_uint16(s, drdynvc->version); if (drdynvc->version == 2) { stream_read_uint16(s, drdynvc->PriorityCharge0); stream_read_uint16(s, drdynvc->PriorityCharge1); stream_read_uint16(s, drdynvc->PriorityCharge2); stream_read_uint16(s, drdynvc->PriorityCharge3); } data_out = stream_new(4); stream_write_uint16(data_out, 0x0050); /* Cmd+Sp+cbChId+Pad. Note: MSTSC sends 0x005c */ stream_write_uint16(data_out, drdynvc->version); error = svc_plugin_send((rdpSvcPlugin*)drdynvc, data_out); if (error != CHANNEL_RC_OK) { DEBUG_WARN("VirtualChannelWrite failed %d", error); return 1; } return 0; } static uint32 drdynvc_read_variable_uint(STREAM* stream, int cbLen) { uint32 val; switch (cbLen) { case 0: stream_read_uint8(stream, val); break; case 1: stream_read_uint16(stream, val); break; default: stream_read_uint32(stream, val); break; } return val; } static int drdynvc_process_create_request(drdynvcPlugin* drdynvc, int Sp, int cbChId, STREAM* s) { STREAM* data_out; int pos; int error; uint32 ChannelId; ChannelId = drdynvc_read_variable_uint(s, cbChId); pos = stream_get_pos(s); DEBUG_DVC("ChannelId=%d ChannelName=%s", ChannelId, stream_get_tail(s)); error = dvcman_create_channel(drdynvc->channel_mgr, ChannelId, (char*)stream_get_tail(s)); data_out = stream_new(pos + 4); stream_write_uint8(data_out, 0x10 | cbChId); stream_set_pos(s, 1); stream_copy(data_out, s, pos - 1); if (error == 0) { DEBUG_DVC("channel created"); stream_write_uint32(data_out, 0); } else { DEBUG_DVC("no listener"); stream_write_uint32(data_out, (uint32)(-1)); } error = svc_plugin_send((rdpSvcPlugin*)drdynvc, data_out); if (error != CHANNEL_RC_OK) { DEBUG_WARN("VirtualChannelWrite failed %d", error); return 1; } return 0; } static int drdynvc_process_data_first(drdynvcPlugin* drdynvc, int Sp, int cbChId, STREAM* s) { uint32 ChannelId; uint32 Length; int error; ChannelId = drdynvc_read_variable_uint(s, cbChId); Length = drdynvc_read_variable_uint(s, Sp); DEBUG_DVC("ChannelId=%d Length=%d", ChannelId, Length); error = dvcman_receive_channel_data_first(drdynvc->channel_mgr, ChannelId, Length); if (error) return error; return dvcman_receive_channel_data(drdynvc->channel_mgr, ChannelId, stream_get_tail(s), stream_get_left(s)); } static int drdynvc_process_data(drdynvcPlugin* drdynvc, int Sp, int cbChId, STREAM* s) { uint32 ChannelId; ChannelId = drdynvc_read_variable_uint(s, cbChId); DEBUG_DVC("ChannelId=%d", ChannelId); return dvcman_receive_channel_data(drdynvc->channel_mgr, ChannelId, stream_get_tail(s), stream_get_left(s)); } static int drdynvc_process_close_request(drdynvcPlugin* drdynvc, int Sp, int cbChId, STREAM* s) { uint32 ChannelId; ChannelId = drdynvc_read_variable_uint(s, cbChId); DEBUG_DVC("ChannelId=%d", ChannelId); dvcman_close_channel(drdynvc->channel_mgr, ChannelId); return 0; } static void drdynvc_process_receive(rdpSvcPlugin* plugin, STREAM* s) { drdynvcPlugin* drdynvc = (drdynvcPlugin*)plugin; int value; int Cmd; int Sp; int cbChId; stream_read_uint8(s, value); Cmd = (value & 0xf0) >> 4; Sp = (value & 0x0c) >> 2; cbChId = (value & 0x03) >> 0; DEBUG_DVC("Cmd=0x%x", Cmd); switch (Cmd) { case CAPABILITY_REQUEST_PDU: drdynvc_process_capability_request(drdynvc, Sp, cbChId, s); break; case CREATE_REQUEST_PDU: drdynvc_process_create_request(drdynvc, Sp, cbChId, s); break; case DATA_FIRST_PDU: drdynvc_process_data_first(drdynvc, Sp, cbChId, s); break; case DATA_PDU: drdynvc_process_data(drdynvc, Sp, cbChId, s); break; case CLOSE_REQUEST_PDU: drdynvc_process_close_request(drdynvc, Sp, cbChId, s); break; default: DEBUG_WARN("unknown drdynvc cmd 0x%x", Cmd); break; } stream_free(s); } static void drdynvc_process_connect(rdpSvcPlugin* plugin) { drdynvcPlugin* drdynvc = (drdynvcPlugin*)plugin; DEBUG_DVC("connecting"); drdynvc->channel_mgr = dvcman_new(drdynvc); dvcman_load_plugin(drdynvc->channel_mgr, svc_plugin_get_data(plugin)); dvcman_init(drdynvc->channel_mgr); } static void drdynvc_process_event(rdpSvcPlugin* plugin, RDP_EVENT* event) { freerdp_event_free(event); } static void drdynvc_process_terminate(rdpSvcPlugin* plugin) { drdynvcPlugin* drdynvc = (drdynvcPlugin*)plugin; DEBUG_DVC("terminating"); if (drdynvc->channel_mgr != NULL) dvcman_free(drdynvc->channel_mgr); xfree(drdynvc); } DEFINE_SVC_PLUGIN(drdynvc, "drdynvc", CHANNEL_OPTION_INITIALIZED | CHANNEL_OPTION_ENCRYPT_RDP | CHANNEL_OPTION_COMPRESS_RDP) FreeRDP-1.0.2/channels/drdynvc/drdynvc_main.h000066400000000000000000000017101207112532300210260ustar00rootroot00000000000000/** * FreeRDP: A Remote Desktop Protocol client. * Dynamic Virtual Channel * * Copyright 2010-2011 Vic Lee * * 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. */ #ifndef __DRDYNVC_MAIN_H #define __DRDYNVC_MAIN_H #include typedef struct drdynvc_plugin drdynvcPlugin; int drdynvc_write_data(drdynvcPlugin* plugin, uint32 ChannelId, uint8* data, uint32 data_size); int drdynvc_push_event(drdynvcPlugin* plugin, RDP_EVENT* event); #endif FreeRDP-1.0.2/channels/drdynvc/drdynvc_types.h000066400000000000000000000017521207112532300212540ustar00rootroot00000000000000/** * FreeRDP: A Remote Desktop Protocol client. * Dynamic Virtual Channel * * Copyright 2010-2011 Vic Lee * * 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. */ #ifndef __DRDYNVC_TYPES_H #define __DRDYNVC_TYPES_H #include "config.h" #include #include #include #ifdef WITH_DEBUG_DVC #define DEBUG_DVC(fmt, ...) DEBUG_CLASS(DVC, fmt, ## __VA_ARGS__) #else #define DEBUG_DVC(fmt, ...) DEBUG_NULL(fmt, ## __VA_ARGS__) #endif #endif FreeRDP-1.0.2/channels/drdynvc/dvcman.c000066400000000000000000000244311207112532300176210ustar00rootroot00000000000000/** * FreeRDP: A Remote Desktop Protocol client. * Dynamic Virtual Channel Manager * * Copyright 2010-2011 Vic Lee * * 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. */ #include #include #include #include #include #include #include #include "drdynvc_types.h" #include "dvcman.h" #define MAX_PLUGINS 10 typedef struct _DVCMAN DVCMAN; struct _DVCMAN { IWTSVirtualChannelManager iface; drdynvcPlugin* drdynvc; const char* plugin_names[MAX_PLUGINS]; IWTSPlugin* plugins[MAX_PLUGINS]; int num_plugins; IWTSListener* listeners[MAX_PLUGINS]; int num_listeners; LIST* channels; }; typedef struct _DVCMAN_LISTENER DVCMAN_LISTENER; struct _DVCMAN_LISTENER { IWTSListener iface; DVCMAN* dvcman; char* channel_name; uint32 flags; IWTSListenerCallback* listener_callback; }; typedef struct _DVCMAN_ENTRY_POINTS DVCMAN_ENTRY_POINTS; struct _DVCMAN_ENTRY_POINTS { IDRDYNVC_ENTRY_POINTS iface; DVCMAN* dvcman; RDP_PLUGIN_DATA* plugin_data; }; typedef struct _DVCMAN_CHANNEL DVCMAN_CHANNEL; struct _DVCMAN_CHANNEL { IWTSVirtualChannel iface; DVCMAN* dvcman; DVCMAN_CHANNEL* next; uint32 channel_id; IWTSVirtualChannelCallback* channel_callback; STREAM* dvc_data; }; static int dvcman_get_configuration(IWTSListener* pListener, void** ppPropertyBag) { *ppPropertyBag = NULL; return 1; } static int dvcman_create_listener(IWTSVirtualChannelManager* pChannelMgr, const char* pszChannelName, uint32 ulFlags, IWTSListenerCallback* pListenerCallback, IWTSListener** ppListener) { DVCMAN* dvcman = (DVCMAN*)pChannelMgr; DVCMAN_LISTENER* listener; if (dvcman->num_listeners < MAX_PLUGINS) { DEBUG_DVC("%d.%s.", dvcman->num_listeners, pszChannelName); listener = xnew(DVCMAN_LISTENER); listener->iface.GetConfiguration = dvcman_get_configuration; listener->dvcman = dvcman; listener->channel_name = xstrdup(pszChannelName); listener->flags = ulFlags; listener->listener_callback = pListenerCallback; if (ppListener) *ppListener = (IWTSListener*)listener; dvcman->listeners[dvcman->num_listeners++] = (IWTSListener*)listener; return 0; } else { DEBUG_WARN("Maximum DVC listener number reached."); return 1; } } static int dvcman_push_event(IWTSVirtualChannelManager* pChannelMgr, RDP_EVENT* pEvent) { int error; DVCMAN* dvcman = (DVCMAN*) pChannelMgr; error = drdynvc_push_event(dvcman->drdynvc, pEvent); if (error == 0) { DEBUG_DVC("event_type %d pushed.", pEvent->event_type); } else { DEBUG_WARN("event_type %d push failed.", pEvent->event_type); } return error; } static int dvcman_register_plugin(IDRDYNVC_ENTRY_POINTS* pEntryPoints, const char* name, IWTSPlugin* pPlugin) { DVCMAN* dvcman = ((DVCMAN_ENTRY_POINTS*) pEntryPoints)->dvcman; if (dvcman->num_plugins < MAX_PLUGINS) { DEBUG_DVC("num_plugins %d", dvcman->num_plugins); dvcman->plugin_names[dvcman->num_plugins] = name; dvcman->plugins[dvcman->num_plugins++] = pPlugin; return 0; } else { DEBUG_WARN("Maximum DVC plugin number reached."); return 1; } } IWTSPlugin* dvcman_get_plugin(IDRDYNVC_ENTRY_POINTS* pEntryPoints, const char* name) { int i; DVCMAN* dvcman = ((DVCMAN_ENTRY_POINTS*) pEntryPoints)->dvcman; for (i = 0; i < dvcman->num_plugins; i++) { if (dvcman->plugin_names[i] == name || strcmp(dvcman->plugin_names[i], name) == 0) { return dvcman->plugins[i]; } } return NULL; } RDP_PLUGIN_DATA* dvcman_get_plugin_data(IDRDYNVC_ENTRY_POINTS* pEntryPoints) { return ((DVCMAN_ENTRY_POINTS*) pEntryPoints)->plugin_data; } IWTSVirtualChannelManager* dvcman_new(drdynvcPlugin* plugin) { DVCMAN* dvcman; dvcman = xnew(DVCMAN); dvcman->iface.CreateListener = dvcman_create_listener; dvcman->iface.PushEvent = dvcman_push_event; dvcman->drdynvc = plugin; dvcman->channels = list_new(); return (IWTSVirtualChannelManager*) dvcman; } int dvcman_load_plugin(IWTSVirtualChannelManager* pChannelMgr, RDP_PLUGIN_DATA* data) { DVCMAN_ENTRY_POINTS entryPoints; PDVC_PLUGIN_ENTRY pDVCPluginEntry = NULL; while (data && data->size > 0) { pDVCPluginEntry = freerdp_load_plugin((char*) data->data[0], "DVCPluginEntry"); if (pDVCPluginEntry != NULL) { entryPoints.iface.RegisterPlugin = dvcman_register_plugin; entryPoints.iface.GetPlugin = dvcman_get_plugin; entryPoints.iface.GetPluginData = dvcman_get_plugin_data; entryPoints.dvcman = (DVCMAN*) pChannelMgr; entryPoints.plugin_data = data; pDVCPluginEntry((IDRDYNVC_ENTRY_POINTS*) &entryPoints); } data = (RDP_PLUGIN_DATA*)(((void*) data) + data->size); } return 0; } static void dvcman_channel_free(DVCMAN_CHANNEL* channel) { if (channel->channel_callback) channel->channel_callback->OnClose(channel->channel_callback); xfree(channel); } void dvcman_free(IWTSVirtualChannelManager* pChannelMgr) { int i; IWTSPlugin* pPlugin; DVCMAN_LISTENER* listener; DVCMAN_CHANNEL* channel; DVCMAN* dvcman = (DVCMAN*) pChannelMgr; while ((channel = (DVCMAN_CHANNEL*) list_dequeue(dvcman->channels)) != NULL) dvcman_channel_free(channel); list_free(dvcman->channels); for (i = 0; i < dvcman->num_listeners; i++) { listener = (DVCMAN_LISTENER*) dvcman->listeners[i]; xfree(listener->channel_name); xfree(listener); } for (i = 0; i < dvcman->num_plugins; i++) { pPlugin = dvcman->plugins[i]; if (pPlugin->Terminated) pPlugin->Terminated(pPlugin); } xfree(dvcman); } int dvcman_init(IWTSVirtualChannelManager* pChannelMgr) { int i; IWTSPlugin* pPlugin; DVCMAN* dvcman = (DVCMAN*) pChannelMgr; for (i = 0; i < dvcman->num_plugins; i++) { pPlugin = dvcman->plugins[i]; if (pPlugin->Initialize) pPlugin->Initialize(pPlugin, pChannelMgr); } return 0; } static int dvcman_write_channel(IWTSVirtualChannel* pChannel, uint32 cbSize, uint8* pBuffer, void* pReserved) { DVCMAN_CHANNEL* channel = (DVCMAN_CHANNEL*) pChannel; return drdynvc_write_data(channel->dvcman->drdynvc, channel->channel_id, pBuffer, cbSize); } static int dvcman_close_channel_iface(IWTSVirtualChannel* pChannel) { DVCMAN_CHANNEL* channel = (DVCMAN_CHANNEL*) pChannel; DVCMAN* dvcman = channel->dvcman; DEBUG_DVC("id=%d", channel->channel_id); if (list_remove(dvcman->channels, channel) == NULL) DEBUG_WARN("channel not found"); dvcman_channel_free(channel); return 1; } int dvcman_create_channel(IWTSVirtualChannelManager* pChannelMgr, uint32 ChannelId, const char* ChannelName) { int i; int bAccept; DVCMAN_LISTENER* listener; DVCMAN_CHANNEL* channel; IWTSVirtualChannelCallback* pCallback; DVCMAN* dvcman = (DVCMAN*) pChannelMgr; for (i = 0; i < dvcman->num_listeners; i++) { listener = (DVCMAN_LISTENER*)dvcman->listeners[i]; if (strcmp(listener->channel_name, ChannelName) == 0) { channel = xnew(DVCMAN_CHANNEL); channel->iface.Write = dvcman_write_channel; channel->iface.Close = dvcman_close_channel_iface; channel->dvcman = dvcman; channel->channel_id = ChannelId; bAccept = 1; pCallback = NULL; if (listener->listener_callback->OnNewChannelConnection(listener->listener_callback, (IWTSVirtualChannel*) channel, NULL, &bAccept, &pCallback) == 0 && bAccept == 1) { DEBUG_DVC("listener %s created new channel %d", listener->channel_name, channel->channel_id); channel->channel_callback = pCallback; list_add(dvcman->channels, channel); return 0; } else { DEBUG_WARN("channel rejected by plugin"); dvcman_channel_free(channel); return 1; } } } return 1; } static DVCMAN_CHANNEL* dvcman_find_channel_by_id(IWTSVirtualChannelManager* pChannelMgr, uint32 ChannelId) { LIST_ITEM* curr; DVCMAN* dvcman = (DVCMAN*) pChannelMgr; for (curr = dvcman->channels->head; curr; curr = curr->next) { if (((DVCMAN_CHANNEL*) curr->data)->channel_id == ChannelId) { return (DVCMAN_CHANNEL*)curr->data; } } return NULL; } int dvcman_close_channel(IWTSVirtualChannelManager* pChannelMgr, uint32 ChannelId) { DVCMAN_CHANNEL* channel; IWTSVirtualChannel* ichannel; channel = dvcman_find_channel_by_id(pChannelMgr, ChannelId); if (channel == NULL) { DEBUG_WARN("ChannelId %d not found!", ChannelId); return 1; } if (channel->dvc_data) { stream_free(channel->dvc_data); channel->dvc_data = NULL; } DEBUG_DVC("dvcman_close_channel: channel %d closed", ChannelId); ichannel = (IWTSVirtualChannel*)channel; ichannel->Close(ichannel); return 0; } int dvcman_receive_channel_data_first(IWTSVirtualChannelManager* pChannelMgr, uint32 ChannelId, uint32 length) { DVCMAN_CHANNEL* channel; channel = dvcman_find_channel_by_id(pChannelMgr, ChannelId); if (channel == NULL) { DEBUG_WARN("ChannelId %d not found!", ChannelId); return 1; } if (channel->dvc_data) stream_free(channel->dvc_data); channel->dvc_data = stream_new(length); return 0; } int dvcman_receive_channel_data(IWTSVirtualChannelManager* pChannelMgr, uint32 ChannelId, uint8* data, uint32 data_size) { int error = 0; DVCMAN_CHANNEL* channel; channel = dvcman_find_channel_by_id(pChannelMgr, ChannelId); if (channel == NULL) { DEBUG_WARN("ChannelId %d not found!", ChannelId); return 1; } if (channel->dvc_data) { /* Fragmented data */ if (stream_get_length(channel->dvc_data) + data_size > stream_get_size(channel->dvc_data)) { DEBUG_WARN("data exceeding declared length!"); stream_free(channel->dvc_data); channel->dvc_data = NULL; return 1; } stream_write(channel->dvc_data, data, data_size); if (stream_get_length(channel->dvc_data) >= stream_get_size(channel->dvc_data)) { error = channel->channel_callback->OnDataReceived(channel->channel_callback, stream_get_size(channel->dvc_data), stream_get_data(channel->dvc_data)); stream_free(channel->dvc_data); channel->dvc_data = NULL; } } else { error = channel->channel_callback->OnDataReceived(channel->channel_callback, data_size, data); } return error; } FreeRDP-1.0.2/channels/drdynvc/dvcman.h000066400000000000000000000027011207112532300176220ustar00rootroot00000000000000/** * FreeRDP: A Remote Desktop Protocol client. * Dynamic Virtual Channel Manager * * Copyright 2010-2011 Vic Lee * * 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. */ #ifndef __DVCMAN_H #define __DVCMAN_H #include #include "drdynvc_main.h" IWTSVirtualChannelManager* dvcman_new(drdynvcPlugin* plugin); int dvcman_load_plugin(IWTSVirtualChannelManager* pChannelMgr, RDP_PLUGIN_DATA* data); void dvcman_free(IWTSVirtualChannelManager* pChannelMgr); int dvcman_init(IWTSVirtualChannelManager* pChannelMgr); int dvcman_create_channel(IWTSVirtualChannelManager* pChannelMgr, uint32 ChannelId, const char* ChannelName); int dvcman_close_channel(IWTSVirtualChannelManager* pChannelMgr, uint32 ChannelId); int dvcman_receive_channel_data_first(IWTSVirtualChannelManager* pChannelMgr, uint32 ChannelId, uint32 length); int dvcman_receive_channel_data(IWTSVirtualChannelManager* pChannelMgr, uint32 ChannelId, uint8* data, uint32 data_size); #endif FreeRDP-1.0.2/channels/drdynvc/tsmf/000077500000000000000000000000001207112532300171525ustar00rootroot00000000000000FreeRDP-1.0.2/channels/drdynvc/tsmf/CMakeLists.txt000066400000000000000000000025301207112532300217120ustar00rootroot00000000000000# FreeRDP: A Remote Desktop Protocol Client # FreeRDP cmake build script # # Copyright 2011 O.S. Systems Software Ltda. # Copyright 2011 Otavio Salvador # Copyright 2011 Marc-Andre Moreau # # 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(TSMF_SRCS tsmf_audio.c tsmf_audio.h tsmf_codec.c tsmf_codec.h tsmf_constants.h tsmf_decoder.c tsmf_decoder.h tsmf_ifman.c tsmf_ifman.h tsmf_main.c tsmf_main.h tsmf_media.c tsmf_media.h tsmf_types.h ) include_directories(..) add_library(tsmf ${TSMF_SRCS}) set_target_properties(tsmf PROPERTIES PREFIX "") target_link_libraries(tsmf freerdp-utils) install(TARGETS tsmf DESTINATION ${FREERDP_PLUGIN_PATH}) if(WITH_FFMPEG) add_subdirectory(ffmpeg) endif() if(WITH_ALSA) add_subdirectory(alsa) endif() if(WITH_PULSEAUDIO) add_subdirectory(pulse) endif() FreeRDP-1.0.2/channels/drdynvc/tsmf/alsa/000077500000000000000000000000001207112532300200725ustar00rootroot00000000000000FreeRDP-1.0.2/channels/drdynvc/tsmf/alsa/CMakeLists.txt000066400000000000000000000021761207112532300226400ustar00rootroot00000000000000# FreeRDP: A Remote Desktop Protocol Client # FreeRDP cmake build script # # Copyright 2011 O.S. Systems Software Ltda. # Copyright 2011 Otavio Salvador # Copyright 2011 Marc-Andre Moreau # # 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(TSMF_ALSA_SRCS tsmf_alsa.c ) include_directories(..) include_directories(${ALSA_INCLUDE_DIRS}) add_library(tsmf_alsa ${TSMF_ALSA_SRCS}) set_target_properties(tsmf_alsa PROPERTIES PREFIX "") target_link_libraries(tsmf_alsa freerdp-utils) target_link_libraries(tsmf_alsa ${ALSA_LIBRARIES}) install(TARGETS tsmf_alsa DESTINATION ${FREERDP_PLUGIN_PATH}) FreeRDP-1.0.2/channels/drdynvc/tsmf/alsa/tsmf_alsa.c000066400000000000000000000152011207112532300222060ustar00rootroot00000000000000/** * FreeRDP: A Remote Desktop Protocol client. * Video Redirection Virtual Channel - ALSA Audio Device * * Copyright 2010-2011 Vic Lee * * 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. */ #include #include #include #include #include #include #include #include #include #include "tsmf_audio.h" typedef struct _TSMFALSAAudioDevice { ITSMFAudioDevice iface; char device[32]; snd_pcm_t* out_handle; uint32 source_rate; uint32 actual_rate; uint32 source_channels; uint32 actual_channels; uint32 bytes_per_sample; } TSMFALSAAudioDevice; static boolean tsmf_alsa_open_device(TSMFALSAAudioDevice* alsa) { int error; error = snd_pcm_open(&alsa->out_handle, alsa->device, SND_PCM_STREAM_PLAYBACK, 0); if (error < 0) { DEBUG_WARN("failed to open device %s", alsa->device); return false; } DEBUG_DVC("open device %s", alsa->device); return true; } static boolean tsmf_alsa_open(ITSMFAudioDevice* audio, const char* device) { TSMFALSAAudioDevice* alsa = (TSMFALSAAudioDevice*) audio; if (!device) { if (!alsa->device[0]) strcpy(alsa->device, "default"); } else { strcpy(alsa->device, device); } return tsmf_alsa_open_device(alsa); } static boolean tsmf_alsa_set_format(ITSMFAudioDevice* audio, uint32 sample_rate, uint32 channels, uint32 bits_per_sample) { int error; snd_pcm_uframes_t frames; snd_pcm_hw_params_t* hw_params; snd_pcm_sw_params_t* sw_params; TSMFALSAAudioDevice* alsa = (TSMFALSAAudioDevice*) audio; if (!alsa->out_handle) return false; snd_pcm_drop(alsa->out_handle); alsa->actual_rate = alsa->source_rate = sample_rate; alsa->actual_channels = alsa->source_channels = channels; alsa->bytes_per_sample = bits_per_sample / 8; error = snd_pcm_hw_params_malloc(&hw_params); if (error < 0) { DEBUG_WARN("snd_pcm_hw_params_malloc failed"); return false; } snd_pcm_hw_params_any(alsa->out_handle, hw_params); snd_pcm_hw_params_set_access(alsa->out_handle, hw_params, SND_PCM_ACCESS_RW_INTERLEAVED); snd_pcm_hw_params_set_format(alsa->out_handle, hw_params, SND_PCM_FORMAT_S16_LE); snd_pcm_hw_params_set_rate_near(alsa->out_handle, hw_params, &alsa->actual_rate, NULL); snd_pcm_hw_params_set_channels_near(alsa->out_handle, hw_params, &alsa->actual_channels); frames = sample_rate; snd_pcm_hw_params_set_buffer_size_near(alsa->out_handle, hw_params, &frames); snd_pcm_hw_params(alsa->out_handle, hw_params); snd_pcm_hw_params_free(hw_params); error = snd_pcm_sw_params_malloc(&sw_params); if (error < 0) { DEBUG_WARN("snd_pcm_sw_params_malloc"); return false; } snd_pcm_sw_params_current(alsa->out_handle, sw_params); snd_pcm_sw_params_set_start_threshold(alsa->out_handle, sw_params, frames / 2); snd_pcm_sw_params(alsa->out_handle, sw_params); snd_pcm_sw_params_free(sw_params); snd_pcm_prepare(alsa->out_handle); DEBUG_DVC("sample_rate %d channels %d bits_per_sample %d", sample_rate, channels, bits_per_sample); DEBUG_DVC("hardware buffer %d frames", (int)frames); if ((alsa->actual_rate != alsa->source_rate) || (alsa->actual_channels != alsa->source_channels)) { DEBUG_DVC("actual rate %d / channel %d is different " "from source rate %d / channel %d, resampling required.", alsa->actual_rate, alsa->actual_channels, alsa->source_rate, alsa->source_channels); } return true; } static boolean tsmf_alsa_play(ITSMFAudioDevice* audio, uint8* data, uint32 data_size) { int len; int error; int frames; uint8* end; uint8* src; uint8* pindex; int rbytes_per_frame; int sbytes_per_frame; uint8* resampled_data; TSMFALSAAudioDevice* alsa = (TSMFALSAAudioDevice*) audio; DEBUG_DVC("data_size %d", data_size); if (alsa->out_handle) { sbytes_per_frame = alsa->source_channels * alsa->bytes_per_sample; rbytes_per_frame = alsa->actual_channels * alsa->bytes_per_sample; if ((alsa->source_rate == alsa->actual_rate) && (alsa->source_channels == alsa->actual_channels)) { resampled_data = NULL; src = data; } else { resampled_data = dsp_resample(data, alsa->bytes_per_sample, alsa->source_channels, alsa->source_rate, data_size / sbytes_per_frame, alsa->actual_channels, alsa->actual_rate, &frames); DEBUG_DVC("resampled %d frames at %d to %d frames at %d", data_size / sbytes_per_frame, alsa->source_rate, frames, alsa->actual_rate); data_size = frames * rbytes_per_frame; src = resampled_data; } pindex = src; end = pindex + data_size; while (pindex < end) { len = end - pindex; frames = len / rbytes_per_frame; error = snd_pcm_writei(alsa->out_handle, pindex, frames); if (error == -EPIPE) { snd_pcm_recover(alsa->out_handle, error, 0); error = 0; } else if (error < 0) { DEBUG_DVC("error len %d", error); snd_pcm_close(alsa->out_handle); alsa->out_handle = 0; tsmf_alsa_open_device(alsa); break; } DEBUG_DVC("%d frames played.", error); if (error == 0) break; pindex += error * rbytes_per_frame; } if (resampled_data) xfree(resampled_data); } xfree(data); return true; } static uint64 tsmf_alsa_get_latency(ITSMFAudioDevice* audio) { uint64 latency = 0; snd_pcm_sframes_t frames = 0; TSMFALSAAudioDevice* alsa = (TSMFALSAAudioDevice*) audio; if (alsa->out_handle && alsa->actual_rate > 0 && snd_pcm_delay(alsa->out_handle, &frames) == 0 && frames > 0) { latency = ((uint64)frames) * 10000000LL / (uint64)alsa->actual_rate; } return latency; } static void tsmf_alsa_flush(ITSMFAudioDevice* audio) { } static void tsmf_alsa_free(ITSMFAudioDevice* audio) { TSMFALSAAudioDevice* alsa = (TSMFALSAAudioDevice*) audio; DEBUG_DVC(""); if (alsa->out_handle) { snd_pcm_drain(alsa->out_handle); snd_pcm_close(alsa->out_handle); } xfree(alsa); } ITSMFAudioDevice* TSMFAudioDeviceEntry(void) { TSMFALSAAudioDevice* alsa; alsa = xnew(TSMFALSAAudioDevice); alsa->iface.Open = tsmf_alsa_open; alsa->iface.SetFormat = tsmf_alsa_set_format; alsa->iface.Play = tsmf_alsa_play; alsa->iface.GetLatency = tsmf_alsa_get_latency; alsa->iface.Flush = tsmf_alsa_flush; alsa->iface.Free = tsmf_alsa_free; return (ITSMFAudioDevice*) alsa; } FreeRDP-1.0.2/channels/drdynvc/tsmf/ffmpeg/000077500000000000000000000000001207112532300204165ustar00rootroot00000000000000FreeRDP-1.0.2/channels/drdynvc/tsmf/ffmpeg/CMakeLists.txt000066400000000000000000000022221207112532300231540ustar00rootroot00000000000000# FreeRDP: A Remote Desktop Protocol Client # FreeRDP cmake build script # # Copyright 2011 O.S. Systems Software Ltda. # Copyright 2011 Otavio Salvador # Copyright 2011 Marc-Andre Moreau # # 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(TSMF_FFMPEG_SRCS tsmf_ffmpeg.c ) include_directories(..) include_directories(${FFMPEG_INCLUDE_DIRS}) add_library(tsmf_ffmpeg ${TSMF_FFMPEG_SRCS}) set_target_properties(tsmf_ffmpeg PROPERTIES PREFIX "") target_link_libraries(tsmf_ffmpeg freerdp-utils) target_link_libraries(tsmf_ffmpeg ${FFMPEG_LIBRARIES}) install(TARGETS tsmf_ffmpeg DESTINATION ${FREERDP_PLUGIN_PATH}) FreeRDP-1.0.2/channels/drdynvc/tsmf/ffmpeg/tsmf_ffmpeg.c000066400000000000000000000342541207112532300230670ustar00rootroot00000000000000/** * FreeRDP: A Remote Desktop Protocol client. * Video Redirection Virtual Channel - FFmpeg Decoder * * Copyright 2010-2011 Vic Lee * * 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. */ #include #include #include #include #include #include #include #include "tsmf_constants.h" #include "tsmf_decoder.h" /* Compatibility with older FFmpeg */ #if LIBAVUTIL_VERSION_MAJOR < 50 #define AVMEDIA_TYPE_VIDEO 0 #define AVMEDIA_TYPE_AUDIO 1 #endif typedef struct _TSMFFFmpegDecoder { ITSMFDecoder iface; int media_type; enum CodecID codec_id; AVCodecContext* codec_context; AVCodec* codec; AVFrame* frame; int prepared; uint8* decoded_data; uint32 decoded_size; uint32 decoded_size_max; } TSMFFFmpegDecoder; static boolean tsmf_ffmpeg_init_context(ITSMFDecoder* decoder) { TSMFFFmpegDecoder* mdecoder = (TSMFFFmpegDecoder*) decoder; mdecoder->codec_context = avcodec_alloc_context(); if (!mdecoder->codec_context) { DEBUG_WARN("avcodec_alloc_context failed."); return false; } return true; } static boolean tsmf_ffmpeg_init_video_stream(ITSMFDecoder* decoder, const TS_AM_MEDIA_TYPE* media_type) { TSMFFFmpegDecoder* mdecoder = (TSMFFFmpegDecoder*) decoder; mdecoder->codec_context->width = media_type->Width; mdecoder->codec_context->height = media_type->Height; mdecoder->codec_context->bit_rate = media_type->BitRate; mdecoder->codec_context->time_base.den = media_type->SamplesPerSecond.Numerator; mdecoder->codec_context->time_base.num = media_type->SamplesPerSecond.Denominator; mdecoder->frame = avcodec_alloc_frame(); return true; } static boolean tsmf_ffmpeg_init_audio_stream(ITSMFDecoder* decoder, const TS_AM_MEDIA_TYPE* media_type) { TSMFFFmpegDecoder* mdecoder = (TSMFFFmpegDecoder*) decoder; mdecoder->codec_context->sample_rate = media_type->SamplesPerSecond.Numerator; mdecoder->codec_context->bit_rate = media_type->BitRate; mdecoder->codec_context->channels = media_type->Channels; mdecoder->codec_context->block_align = media_type->BlockAlign; #ifdef AV_CPU_FLAG_SSE2 mdecoder->codec_context->dsp_mask = AV_CPU_FLAG_SSE2 | AV_CPU_FLAG_MMX2; #else #if LIBAVCODEC_VERSION_MAJOR < 53 mdecoder->codec_context->dsp_mask = FF_MM_SSE2 | FF_MM_MMXEXT; #else mdecoder->codec_context->dsp_mask = FF_MM_SSE2 | FF_MM_MMX2; #endif #endif return true; } static boolean tsmf_ffmpeg_init_stream(ITSMFDecoder* decoder, const TS_AM_MEDIA_TYPE* media_type) { TSMFFFmpegDecoder* mdecoder = (TSMFFFmpegDecoder*) decoder; uint32 size; const uint8* s; uint8* p; mdecoder->codec = avcodec_find_decoder(mdecoder->codec_id); if (!mdecoder->codec) { DEBUG_WARN("avcodec_find_decoder failed."); return false; } mdecoder->codec_context->codec_id = mdecoder->codec_id; mdecoder->codec_context->codec_type = mdecoder->media_type; if (mdecoder->media_type == AVMEDIA_TYPE_VIDEO) { if (!tsmf_ffmpeg_init_video_stream(decoder, media_type)) return false; } else if (mdecoder->media_type == AVMEDIA_TYPE_AUDIO) { if (!tsmf_ffmpeg_init_audio_stream(decoder, media_type)) return false; } if (media_type->ExtraData) { if (media_type->SubType == TSMF_SUB_TYPE_AVC1 && media_type->FormatType == TSMF_FORMAT_TYPE_MPEG2VIDEOINFO) { /* The extradata format that FFmpeg uses is following CodecPrivate in Matroska. See http://haali.su/mkv/codecs.pdf */ mdecoder->codec_context->extradata_size = media_type->ExtraDataSize + 8; mdecoder->codec_context->extradata = xzalloc(mdecoder->codec_context->extradata_size); p = mdecoder->codec_context->extradata; *p++ = 1; /* Reserved? */ *p++ = media_type->ExtraData[8]; /* Profile */ *p++ = 0; /* Profile */ *p++ = media_type->ExtraData[12]; /* Level */ *p++ = 0xff; /* Flag? */ *p++ = 0xe0 | 0x01; /* Reserved | #sps */ s = media_type->ExtraData + 20; size = ((uint32)(*s)) * 256 + ((uint32)(*(s + 1))); memcpy(p, s, size + 2); s += size + 2; p += size + 2; *p++ = 1; /* #pps */ size = ((uint32)(*s)) * 256 + ((uint32)(*(s + 1))); memcpy(p, s, size + 2); } else { /* Add a padding to avoid invalid memory read in some codec */ mdecoder->codec_context->extradata_size = media_type->ExtraDataSize + 8; mdecoder->codec_context->extradata = xzalloc(mdecoder->codec_context->extradata_size); memcpy(mdecoder->codec_context->extradata, media_type->ExtraData, media_type->ExtraDataSize); memset(mdecoder->codec_context->extradata + media_type->ExtraDataSize, 0, 8); } } if (mdecoder->codec->capabilities & CODEC_CAP_TRUNCATED) mdecoder->codec_context->flags |= CODEC_FLAG_TRUNCATED; return true; } static boolean tsmf_ffmpeg_prepare(ITSMFDecoder* decoder) { TSMFFFmpegDecoder* mdecoder = (TSMFFFmpegDecoder*) decoder; if (avcodec_open(mdecoder->codec_context, mdecoder->codec) < 0) { DEBUG_WARN("avcodec_open failed."); return false; } mdecoder->prepared = 1; return true; } static boolean tsmf_ffmpeg_set_format(ITSMFDecoder* decoder, TS_AM_MEDIA_TYPE* media_type) { TSMFFFmpegDecoder* mdecoder = (TSMFFFmpegDecoder*) decoder; switch (media_type->MajorType) { case TSMF_MAJOR_TYPE_VIDEO: mdecoder->media_type = AVMEDIA_TYPE_VIDEO; break; case TSMF_MAJOR_TYPE_AUDIO: mdecoder->media_type = AVMEDIA_TYPE_AUDIO; break; default: return false; } switch (media_type->SubType) { case TSMF_SUB_TYPE_WVC1: mdecoder->codec_id = CODEC_ID_VC1; break; case TSMF_SUB_TYPE_WMA2: mdecoder->codec_id = CODEC_ID_WMAV2; break; case TSMF_SUB_TYPE_WMA9: mdecoder->codec_id = CODEC_ID_WMAPRO; break; case TSMF_SUB_TYPE_MP3: mdecoder->codec_id = CODEC_ID_MP3; break; case TSMF_SUB_TYPE_MP2A: mdecoder->codec_id = CODEC_ID_MP2; break; case TSMF_SUB_TYPE_MP2V: mdecoder->codec_id = CODEC_ID_MPEG2VIDEO; break; case TSMF_SUB_TYPE_WMV3: mdecoder->codec_id = CODEC_ID_WMV3; break; case TSMF_SUB_TYPE_AAC: mdecoder->codec_id = CODEC_ID_AAC; /* For AAC the pFormat is a HEAACWAVEINFO struct, and the codec data is at the end of it. See http://msdn.microsoft.com/en-us/library/dd757806.aspx */ if (media_type->ExtraData) { media_type->ExtraData += 12; media_type->ExtraDataSize -= 12; } break; case TSMF_SUB_TYPE_H264: case TSMF_SUB_TYPE_AVC1: mdecoder->codec_id = CODEC_ID_H264; break; case TSMF_SUB_TYPE_AC3: mdecoder->codec_id = CODEC_ID_AC3; break; default: return false; } if (!tsmf_ffmpeg_init_context(decoder)) return false; if (!tsmf_ffmpeg_init_stream(decoder, media_type)) return false; if (!tsmf_ffmpeg_prepare(decoder)) return false; return true; } static boolean tsmf_ffmpeg_decode_video(ITSMFDecoder* decoder, const uint8* data, uint32 data_size, uint32 extensions) { TSMFFFmpegDecoder* mdecoder = (TSMFFFmpegDecoder*) decoder; int decoded; int len; AVFrame* frame; boolean ret = true; #if LIBAVCODEC_VERSION_MAJOR < 52 || (LIBAVCODEC_VERSION_MAJOR == 52 && LIBAVCODEC_VERSION_MINOR <= 20) len = avcodec_decode_video(mdecoder->codec_context, mdecoder->frame, &decoded, data, data_size); #else { AVPacket pkt; av_init_packet(&pkt); pkt.data = (uint8*) data; pkt.size = data_size; if (extensions & TSMM_SAMPLE_EXT_CLEANPOINT) pkt.flags |= AV_PKT_FLAG_KEY; len = avcodec_decode_video2(mdecoder->codec_context, mdecoder->frame, &decoded, &pkt); } #endif if (len < 0) { DEBUG_WARN("data_size %d, avcodec_decode_video failed (%d)", data_size, len); ret = false; } else if (!decoded) { DEBUG_WARN("data_size %d, no frame is decoded.", data_size); ret = false; } else { DEBUG_DVC("linesize[0] %d linesize[1] %d linesize[2] %d linesize[3] %d " "pix_fmt %d width %d height %d", mdecoder->frame->linesize[0], mdecoder->frame->linesize[1], mdecoder->frame->linesize[2], mdecoder->frame->linesize[3], mdecoder->codec_context->pix_fmt, mdecoder->codec_context->width, mdecoder->codec_context->height); mdecoder->decoded_size = avpicture_get_size(mdecoder->codec_context->pix_fmt, mdecoder->codec_context->width, mdecoder->codec_context->height); mdecoder->decoded_data = xzalloc(mdecoder->decoded_size); frame = avcodec_alloc_frame(); avpicture_fill((AVPicture *) frame, mdecoder->decoded_data, mdecoder->codec_context->pix_fmt, mdecoder->codec_context->width, mdecoder->codec_context->height); av_picture_copy((AVPicture *) frame, (AVPicture *) mdecoder->frame, mdecoder->codec_context->pix_fmt, mdecoder->codec_context->width, mdecoder->codec_context->height); av_free(frame); } return ret; } static boolean tsmf_ffmpeg_decode_audio(ITSMFDecoder* decoder, const uint8* data, uint32 data_size, uint32 extensions) { TSMFFFmpegDecoder* mdecoder = (TSMFFFmpegDecoder*) decoder; int len; int frame_size; uint32 src_size; const uint8* src; uint8* dst; int dst_offset; #if 0 LLOGLN(0, ("tsmf_ffmpeg_decode_audio: data_size %d", data_size)); int i; for (i = 0; i < data_size; i++) { LLOG(0, ("%02X ", data[i])); if (i % 16 == 15) LLOG(0, ("\n")); } LLOG(0, ("\n")); #endif if (mdecoder->decoded_size_max == 0) mdecoder->decoded_size_max = AVCODEC_MAX_AUDIO_FRAME_SIZE + 16; mdecoder->decoded_data = xzalloc(mdecoder->decoded_size_max); /* align the memory for SSE2 needs */ dst = (uint8*) (((uintptr_t)mdecoder->decoded_data + 15) & ~ 0x0F); dst_offset = dst - mdecoder->decoded_data; src = data; src_size = data_size; while (src_size > 0) { /* Ensure enough space for decoding */ if (mdecoder->decoded_size_max - mdecoder->decoded_size < AVCODEC_MAX_AUDIO_FRAME_SIZE) { mdecoder->decoded_size_max = mdecoder->decoded_size_max * 2 + 16; mdecoder->decoded_data = xrealloc(mdecoder->decoded_data, mdecoder->decoded_size_max); dst = (uint8*) (((uintptr_t)mdecoder->decoded_data + 15) & ~ 0x0F); if (dst - mdecoder->decoded_data != dst_offset) { /* re-align the memory if the alignment has changed after realloc */ memmove(dst, mdecoder->decoded_data + dst_offset, mdecoder->decoded_size); dst_offset = dst - mdecoder->decoded_data; } dst += mdecoder->decoded_size; } frame_size = mdecoder->decoded_size_max - mdecoder->decoded_size; #if LIBAVCODEC_VERSION_MAJOR < 52 || (LIBAVCODEC_VERSION_MAJOR == 52 && LIBAVCODEC_VERSION_MINOR <= 20) len = avcodec_decode_audio2(mdecoder->codec_context, (int16_t*) dst, &frame_size, src, src_size); #else { AVPacket pkt; av_init_packet(&pkt); pkt.data = (uint8*) src; pkt.size = src_size; len = avcodec_decode_audio3(mdecoder->codec_context, (int16_t*) dst, &frame_size, &pkt); } #endif if (len <= 0 || frame_size <= 0) { DEBUG_WARN("error decoding"); break; } src += len; src_size -= len; mdecoder->decoded_size += frame_size; dst += frame_size; } if (mdecoder->decoded_size == 0) { xfree(mdecoder->decoded_data); mdecoder->decoded_data = NULL; } else if (dst_offset) { /* move the aligned decoded data to original place */ memmove(mdecoder->decoded_data, mdecoder->decoded_data + dst_offset, mdecoder->decoded_size); } DEBUG_DVC("data_size %d decoded_size %d", data_size, mdecoder->decoded_size); return true; } static boolean tsmf_ffmpeg_decode(ITSMFDecoder* decoder, const uint8* data, uint32 data_size, uint32 extensions) { TSMFFFmpegDecoder* mdecoder = (TSMFFFmpegDecoder*) decoder; if (mdecoder->decoded_data) { xfree(mdecoder->decoded_data); mdecoder->decoded_data = NULL; } mdecoder->decoded_size = 0; switch (mdecoder->media_type) { case AVMEDIA_TYPE_VIDEO: return tsmf_ffmpeg_decode_video(decoder, data, data_size, extensions); case AVMEDIA_TYPE_AUDIO: return tsmf_ffmpeg_decode_audio(decoder, data, data_size, extensions); default: DEBUG_WARN("unknown media type."); return false; } } static uint8* tsmf_ffmpeg_get_decoded_data(ITSMFDecoder* decoder, uint32* size) { TSMFFFmpegDecoder* mdecoder = (TSMFFFmpegDecoder*) decoder; uint8* buf; *size = mdecoder->decoded_size; buf = mdecoder->decoded_data; mdecoder->decoded_data = NULL; mdecoder->decoded_size = 0; return buf; } static uint32 tsmf_ffmpeg_get_decoded_format(ITSMFDecoder* decoder) { TSMFFFmpegDecoder* mdecoder = (TSMFFFmpegDecoder*) decoder; switch (mdecoder->codec_context->pix_fmt) { case PIX_FMT_YUV420P: return RDP_PIXFMT_I420; default: DEBUG_WARN("unsupported pixel format %u", mdecoder->codec_context->pix_fmt); return (uint32) -1; } } static boolean tsmf_ffmpeg_get_decoded_dimension(ITSMFDecoder* decoder, uint32* width, uint32* height) { TSMFFFmpegDecoder* mdecoder = (TSMFFFmpegDecoder*) decoder; if (mdecoder->codec_context->width > 0 && mdecoder->codec_context->height > 0) { *width = mdecoder->codec_context->width; *height = mdecoder->codec_context->height; return true; } else { return false; } } static void tsmf_ffmpeg_free(ITSMFDecoder* decoder) { TSMFFFmpegDecoder* mdecoder = (TSMFFFmpegDecoder*) decoder; if (mdecoder->frame) av_free(mdecoder->frame); if (mdecoder->decoded_data) xfree(mdecoder->decoded_data); if (mdecoder->codec_context) { if (mdecoder->prepared) avcodec_close(mdecoder->codec_context); if (mdecoder->codec_context->extradata) xfree(mdecoder->codec_context->extradata); av_free(mdecoder->codec_context); } xfree(decoder); } static boolean initialized = false; ITSMFDecoder* TSMFDecoderEntry(void) { TSMFFFmpegDecoder * decoder; if (!initialized) { avcodec_init(); avcodec_register_all(); initialized = true; } decoder = xnew(TSMFFFmpegDecoder); decoder->iface.SetFormat = tsmf_ffmpeg_set_format; decoder->iface.Decode = tsmf_ffmpeg_decode; decoder->iface.GetDecodedData = tsmf_ffmpeg_get_decoded_data; decoder->iface.GetDecodedFormat = tsmf_ffmpeg_get_decoded_format; decoder->iface.GetDecodedDimension = tsmf_ffmpeg_get_decoded_dimension; decoder->iface.Free = tsmf_ffmpeg_free; return (ITSMFDecoder*) decoder; } FreeRDP-1.0.2/channels/drdynvc/tsmf/pulse/000077500000000000000000000000001207112532300203025ustar00rootroot00000000000000FreeRDP-1.0.2/channels/drdynvc/tsmf/pulse/CMakeLists.txt000066400000000000000000000022131207112532300230400ustar00rootroot00000000000000# FreeRDP: A Remote Desktop Protocol Client # FreeRDP cmake build script # # Copyright 2011 O.S. Systems Software Ltda. # Copyright 2011 Otavio Salvador # Copyright 2011 Marc-Andre Moreau # # 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(TSMF_PULSE_SRCS tsmf_pulse.c ) include_directories(..) include_directories(${PULSE_INCLUDE_DIRS}) add_library(tsmf_pulse ${TSMF_PULSE_SRCS}) set_target_properties(tsmf_pulse PROPERTIES PREFIX "") target_link_libraries(tsmf_pulse freerdp-utils) target_link_libraries(tsmf_pulse ${PULSEAUDIO_LIBRARY}) install(TARGETS tsmf_pulse DESTINATION ${FREERDP_PLUGIN_PATH}) FreeRDP-1.0.2/channels/drdynvc/tsmf/pulse/tsmf_pulse.c000066400000000000000000000233531207112532300226350ustar00rootroot00000000000000/** * FreeRDP: A Remote Desktop Protocol client. * Video Redirection Virtual Channel - PulseAudio Device * * Copyright 2010-2011 Vic Lee * * 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. */ #include #include #include #include #include #include #include "tsmf_audio.h" typedef struct _TSMFPulseAudioDevice { ITSMFAudioDevice iface; char device[32]; pa_threaded_mainloop* mainloop; pa_context* context; pa_sample_spec sample_spec; pa_stream* stream; } TSMFPulseAudioDevice; static void tsmf_pulse_context_state_callback(pa_context* context, void* userdata) { TSMFPulseAudioDevice* pulse = (TSMFPulseAudioDevice*) userdata; pa_context_state_t state; state = pa_context_get_state(context); switch (state) { case PA_CONTEXT_READY: DEBUG_DVC("PA_CONTEXT_READY"); pa_threaded_mainloop_signal(pulse->mainloop, 0); break; case PA_CONTEXT_FAILED: case PA_CONTEXT_TERMINATED: DEBUG_DVC("state %d", (int)state); pa_threaded_mainloop_signal(pulse->mainloop, 0); break; default: DEBUG_DVC("state %d", (int)state); break; } } static boolean tsmf_pulse_connect(TSMFPulseAudioDevice* pulse) { pa_context_state_t state; if (!pulse->context) return false; if (pa_context_connect(pulse->context, NULL, 0, NULL)) { DEBUG_WARN("pa_context_connect failed (%d)", pa_context_errno(pulse->context)); return false; } pa_threaded_mainloop_lock(pulse->mainloop); if (pa_threaded_mainloop_start(pulse->mainloop) < 0) { pa_threaded_mainloop_unlock(pulse->mainloop); DEBUG_WARN("pa_threaded_mainloop_start failed (%d)", pa_context_errno(pulse->context)); return false; } for (;;) { state = pa_context_get_state(pulse->context); if (state == PA_CONTEXT_READY) break; if (!PA_CONTEXT_IS_GOOD(state)) { DEBUG_DVC("bad context state (%d)", pa_context_errno(pulse->context)); break; } pa_threaded_mainloop_wait(pulse->mainloop); } pa_threaded_mainloop_unlock(pulse->mainloop); if (state == PA_CONTEXT_READY) { DEBUG_DVC("connected"); return true; } else { pa_context_disconnect(pulse->context); return false; } } static boolean tsmf_pulse_open(ITSMFAudioDevice* audio, const char* device) { TSMFPulseAudioDevice* pulse = (TSMFPulseAudioDevice*) audio; if (device) { strcpy(pulse->device, device); } pulse->mainloop = pa_threaded_mainloop_new(); if (!pulse->mainloop) { DEBUG_WARN("pa_threaded_mainloop_new failed"); return false; } pulse->context = pa_context_new(pa_threaded_mainloop_get_api(pulse->mainloop), "freerdp"); if (!pulse->context) { DEBUG_WARN("pa_context_new failed"); return false; } pa_context_set_state_callback(pulse->context, tsmf_pulse_context_state_callback, pulse); if (tsmf_pulse_connect(pulse)) { DEBUG_WARN("tsmf_pulse_connect failed"); return false; } DEBUG_DVC("open device %s", pulse->device); return true; } static void tsmf_pulse_stream_success_callback(pa_stream* stream, int success, void* userdata) { TSMFPulseAudioDevice* pulse = (TSMFPulseAudioDevice*) userdata; pa_threaded_mainloop_signal(pulse->mainloop, 0); } static void tsmf_pulse_wait_for_operation(TSMFPulseAudioDevice* pulse, pa_operation* operation) { if (operation == NULL) return; while (pa_operation_get_state(operation) == PA_OPERATION_RUNNING) { pa_threaded_mainloop_wait(pulse->mainloop); } pa_operation_unref(operation); } static void tsmf_pulse_stream_state_callback(pa_stream* stream, void* userdata) { TSMFPulseAudioDevice* pulse = (TSMFPulseAudioDevice*) userdata; pa_stream_state_t state; state = pa_stream_get_state(stream); switch (state) { case PA_STREAM_READY: DEBUG_DVC("PA_STREAM_READY"); pa_threaded_mainloop_signal (pulse->mainloop, 0); break; case PA_STREAM_FAILED: case PA_STREAM_TERMINATED: DEBUG_DVC("state %d", (int)state); pa_threaded_mainloop_signal (pulse->mainloop, 0); break; default: DEBUG_DVC("state %d", (int)state); break; } } static void tsmf_pulse_stream_request_callback(pa_stream* stream, size_t length, void* userdata) { TSMFPulseAudioDevice* pulse = (TSMFPulseAudioDevice*) userdata; DEBUG_DVC("%d", (int) length); pa_threaded_mainloop_signal(pulse->mainloop, 0); } static boolean tsmf_pulse_close_stream(TSMFPulseAudioDevice* pulse) { if (!pulse->context || !pulse->stream) return false; DEBUG_DVC(""); pa_threaded_mainloop_lock(pulse->mainloop); pa_stream_set_write_callback(pulse->stream, NULL, NULL); tsmf_pulse_wait_for_operation(pulse, pa_stream_drain(pulse->stream, tsmf_pulse_stream_success_callback, pulse)); pa_stream_disconnect(pulse->stream); pa_stream_unref(pulse->stream); pulse->stream = NULL; pa_threaded_mainloop_unlock(pulse->mainloop); return true; } static boolean tsmf_pulse_open_stream(TSMFPulseAudioDevice* pulse) { pa_stream_state_t state; pa_buffer_attr buffer_attr = { 0 }; if (!pulse->context) return false; DEBUG_DVC(""); pa_threaded_mainloop_lock(pulse->mainloop); pulse->stream = pa_stream_new(pulse->context, "freerdp", &pulse->sample_spec, NULL); if (!pulse->stream) { pa_threaded_mainloop_unlock(pulse->mainloop); DEBUG_WARN("pa_stream_new failed (%d)", pa_context_errno(pulse->context)); return false; } pa_stream_set_state_callback(pulse->stream, tsmf_pulse_stream_state_callback, pulse); pa_stream_set_write_callback(pulse->stream, tsmf_pulse_stream_request_callback, pulse); buffer_attr.maxlength = pa_usec_to_bytes(500000, &pulse->sample_spec); buffer_attr.tlength = pa_usec_to_bytes(250000, &pulse->sample_spec); buffer_attr.prebuf = (uint32_t) -1; buffer_attr.minreq = (uint32_t) -1; buffer_attr.fragsize = (uint32_t) -1; if (pa_stream_connect_playback(pulse->stream, pulse->device[0] ? pulse->device : NULL, &buffer_attr, PA_STREAM_ADJUST_LATENCY | PA_STREAM_INTERPOLATE_TIMING | PA_STREAM_AUTO_TIMING_UPDATE, NULL, NULL) < 0) { pa_threaded_mainloop_unlock(pulse->mainloop); DEBUG_WARN("pa_stream_connect_playback failed (%d)", pa_context_errno(pulse->context)); return false; } for (;;) { state = pa_stream_get_state(pulse->stream); if (state == PA_STREAM_READY) break; if (!PA_STREAM_IS_GOOD(state)) { DEBUG_WARN("bad stream state (%d)", pa_context_errno(pulse->context)); break; } pa_threaded_mainloop_wait(pulse->mainloop); } pa_threaded_mainloop_unlock(pulse->mainloop); if (state == PA_STREAM_READY) { DEBUG_DVC("connected"); return true; } else { tsmf_pulse_close_stream(pulse); return false; } } static boolean tsmf_pulse_set_format(ITSMFAudioDevice* audio, uint32 sample_rate, uint32 channels, uint32 bits_per_sample) { TSMFPulseAudioDevice* pulse = (TSMFPulseAudioDevice*) audio; DEBUG_DVC("sample_rate %d channels %d bits_per_sample %d", sample_rate, channels, bits_per_sample); pulse->sample_spec.rate = sample_rate; pulse->sample_spec.channels = channels; pulse->sample_spec.format = PA_SAMPLE_S16LE; return tsmf_pulse_open_stream(pulse); } static boolean tsmf_pulse_play(ITSMFAudioDevice* audio, uint8* data, uint32 data_size) { TSMFPulseAudioDevice* pulse = (TSMFPulseAudioDevice*) audio; uint8* src; int len; int ret; DEBUG_DVC("data_size %d", data_size); if (pulse->stream) { pa_threaded_mainloop_lock(pulse->mainloop); src = data; while (data_size > 0) { while ((len = pa_stream_writable_size(pulse->stream)) == 0) { DEBUG_DVC("waiting"); pa_threaded_mainloop_wait(pulse->mainloop); } if (len < 0) break; if (len > data_size) len = data_size; ret = pa_stream_write(pulse->stream, src, len, NULL, 0LL, PA_SEEK_RELATIVE); if (ret < 0) { DEBUG_DVC("pa_stream_write failed (%d)", pa_context_errno(pulse->context)); break; } src += len; data_size -= len; } pa_threaded_mainloop_unlock(pulse->mainloop); } xfree(data); return true; } static uint64 tsmf_pulse_get_latency(ITSMFAudioDevice* audio) { pa_usec_t usec; uint64 latency = 0; TSMFPulseAudioDevice* pulse = (TSMFPulseAudioDevice*) audio; if (pulse->stream && pa_stream_get_latency(pulse->stream, &usec, NULL) == 0) { latency = ((uint64)usec) * 10LL; } return latency; } static void tsmf_pulse_flush(ITSMFAudioDevice* audio) { TSMFPulseAudioDevice* pulse = (TSMFPulseAudioDevice*) audio; pa_threaded_mainloop_lock(pulse->mainloop); tsmf_pulse_wait_for_operation(pulse, pa_stream_flush(pulse->stream, tsmf_pulse_stream_success_callback, pulse)); pa_threaded_mainloop_unlock(pulse->mainloop); } static void tsmf_pulse_free(ITSMFAudioDevice* audio) { TSMFPulseAudioDevice* pulse = (TSMFPulseAudioDevice*) audio; DEBUG_DVC(""); tsmf_pulse_close_stream(pulse); if (pulse->mainloop) { pa_threaded_mainloop_stop(pulse->mainloop); } if (pulse->context) { pa_context_disconnect(pulse->context); pa_context_unref(pulse->context); pulse->context = NULL; } if (pulse->mainloop) { pa_threaded_mainloop_free(pulse->mainloop); pulse->mainloop = NULL; } xfree(pulse); } ITSMFAudioDevice* TSMFAudioDeviceEntry(void) { TSMFPulseAudioDevice* pulse; pulse = xnew(TSMFPulseAudioDevice); pulse->iface.Open = tsmf_pulse_open; pulse->iface.SetFormat = tsmf_pulse_set_format; pulse->iface.Play = tsmf_pulse_play; pulse->iface.GetLatency = tsmf_pulse_get_latency; pulse->iface.Flush = tsmf_pulse_flush; pulse->iface.Free = tsmf_pulse_free; return (ITSMFAudioDevice*) pulse; } FreeRDP-1.0.2/channels/drdynvc/tsmf/tsmf_audio.c000066400000000000000000000037171207112532300214600ustar00rootroot00000000000000/** * FreeRDP: A Remote Desktop Protocol client. * Video Redirection Virtual Channel - Audio Device Manager * * Copyright 2010-2011 Vic Lee * * 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. */ #include #include #include #include #include #include "tsmf_audio.h" static ITSMFAudioDevice* tsmf_load_audio_device_by_name(const char* name, const char* device) { ITSMFAudioDevice* audio; TSMF_AUDIO_DEVICE_ENTRY entry; char* fullname; if (strrchr(name, '.') != NULL) entry = (TSMF_AUDIO_DEVICE_ENTRY) freerdp_load_plugin(name, TSMF_AUDIO_DEVICE_EXPORT_FUNC_NAME); else { fullname = xzalloc(strlen(name) + 6); strcpy(fullname, "tsmf_"); strcat(fullname, name); entry = (TSMF_AUDIO_DEVICE_ENTRY) freerdp_load_plugin(fullname, TSMF_AUDIO_DEVICE_EXPORT_FUNC_NAME); xfree(fullname); } if (entry == NULL) { return NULL; } audio = entry(); if (audio == NULL) { DEBUG_WARN("failed to call export function in %s", name); return NULL; } if (!audio->Open(audio, device)) { audio->Free(audio); audio = NULL; } return audio; } ITSMFAudioDevice* tsmf_load_audio_device(const char* name, const char* device) { ITSMFAudioDevice* audio; if (name) { audio = tsmf_load_audio_device_by_name(name, device); } else { audio = tsmf_load_audio_device_by_name("pulse", device); if (!audio) audio = tsmf_load_audio_device_by_name("alsa", device); } return audio; } FreeRDP-1.0.2/channels/drdynvc/tsmf/tsmf_audio.h000066400000000000000000000032071207112532300214570ustar00rootroot00000000000000/** * FreeRDP: A Remote Desktop Protocol client. * Video Redirection Virtual Channel - Audio Device Manager * * Copyright 2010-2011 Vic Lee * * 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. */ #ifndef __TSMF_AUDIO_H #define __TSMF_AUDIO_H #include "drdynvc_types.h" typedef struct _ITSMFAudioDevice ITSMFAudioDevice; struct _ITSMFAudioDevice { /* Open the audio device. */ boolean (*Open) (ITSMFAudioDevice* audio, const char* device); /* Set the audio data format. */ boolean (*SetFormat) (ITSMFAudioDevice* audio, uint32 sample_rate, uint32 channels, uint32 bits_per_sample); /* Play audio data. */ boolean (*Play) (ITSMFAudioDevice* audio, uint8* data, uint32 data_size); /* Get the latency of the last written sample, in 100ns */ uint64 (*GetLatency) (ITSMFAudioDevice* audio); /* Flush queued audio data */ void (*Flush) (ITSMFAudioDevice* audio); /* Free the audio device */ void (*Free) (ITSMFAudioDevice* audio); }; #define TSMF_AUDIO_DEVICE_EXPORT_FUNC_NAME "TSMFAudioDeviceEntry" typedef ITSMFAudioDevice* (*TSMF_AUDIO_DEVICE_ENTRY) (void); ITSMFAudioDevice* tsmf_load_audio_device(const char* name, const char* device); #endif FreeRDP-1.0.2/channels/drdynvc/tsmf/tsmf_codec.c000066400000000000000000000253131207112532300214300ustar00rootroot00000000000000/** * FreeRDP: A Remote Desktop Protocol client. * Video Redirection Virtual Channel - Codec * * Copyright 2010-2011 Vic Lee * * 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. */ #include #include #include #include #include #include "drdynvc_types.h" #include "tsmf_constants.h" #include "tsmf_types.h" #include "tsmf_codec.h" typedef struct _TSMFMediaTypeMap { uint8 guid[16]; const char* name; int type; } TSMFMediaTypeMap; static const TSMFMediaTypeMap tsmf_major_type_map[] = { /* 73646976-0000-0010-8000-00AA00389B71 */ { { 0x76, 0x69, 0x64, 0x73, 0x00, 0x00, 0x10, 0x00, 0x80, 0x00, 0x00, 0xAA, 0x00, 0x38, 0x9B, 0x71 }, "MEDIATYPE_Video", TSMF_MAJOR_TYPE_VIDEO }, /* 73647561-0000-0010-8000-00AA00389B71 */ { { 0x61, 0x75, 0x64, 0x73, 0x00, 0x00, 0x10, 0x00, 0x80, 0x00, 0x00, 0xAA, 0x00, 0x38, 0x9B, 0x71 }, "MEDIATYPE_Audio", TSMF_MAJOR_TYPE_AUDIO }, { { 0 }, "Unknown", TSMF_MAJOR_TYPE_UNKNOWN } }; static const TSMFMediaTypeMap tsmf_sub_type_map[] = { /* 31435657-0000-0010-8000-00AA00389B71 */ { { 0x57, 0x56, 0x43, 0x31, 0x00, 0x00, 0x10, 0x00, 0x80, 0x00, 0x00, 0xAA, 0x00, 0x38, 0x9B, 0x71 }, "MEDIASUBTYPE_WVC1", TSMF_SUB_TYPE_WVC1 }, /* 00000161-0000-0010-8000-00AA00389B71 */ { { 0x61, 0x01, 0x00, 0x00, 0x00, 0x00, 0x10, 0x00, 0x80, 0x00, 0x00, 0xAA, 0x00, 0x38, 0x9B, 0x71 }, "MEDIASUBTYPE_WMAudioV2", /* V7, V8 has the same GUID */ TSMF_SUB_TYPE_WMA2 }, /* 00000162-0000-0010-8000-00AA00389B71 */ { { 0x62, 0x01, 0x00, 0x00, 0x00, 0x00, 0x10, 0x00, 0x80, 0x00, 0x00, 0xAA, 0x00, 0x38, 0x9B, 0x71 }, "MEDIASUBTYPE_WMAudioV9", TSMF_SUB_TYPE_WMA9 }, /* 00000055-0000-0010-8000-00AA00389B71 */ { { 0x55, 0x00, 0x00, 0x00, 0x00, 0x00, 0x10, 0x00, 0x80, 0x00, 0x00, 0xAA, 0x00, 0x38, 0x9B, 0x71 }, "MEDIASUBTYPE_MP3", TSMF_SUB_TYPE_MP3 }, /* E06D802B-DB46-11CF-B4D1-00805F6CBBEA */ { { 0x2B, 0x80, 0x6D, 0xE0, 0x46, 0xDB, 0xCF, 0x11, 0xB4, 0xD1, 0x00, 0x80, 0x5F, 0x6C, 0xBB, 0xEA }, "MEDIASUBTYPE_MPEG2_AUDIO", TSMF_SUB_TYPE_MP2A }, /* E06D8026-DB46-11CF-B4D1-00805F6CBBEA */ { { 0x26, 0x80, 0x6D, 0xE0, 0x46, 0xDB, 0xCF, 0x11, 0xB4, 0xD1, 0x00, 0x80, 0x5F, 0x6C, 0xBB, 0xEA }, "MEDIASUBTYPE_MPEG2_VIDEO", TSMF_SUB_TYPE_MP2V }, /* 33564D57-0000-0010-8000-00AA00389B71 */ { { 0x57, 0x4D, 0x56, 0x33, 0x00, 0x00, 0x10, 0x00, 0x80, 0x00, 0x00, 0xAA, 0x00, 0x38, 0x9B, 0x71 }, "MEDIASUBTYPE_WMV3", TSMF_SUB_TYPE_WMV3 }, /* 00001610-0000-0010-8000-00AA00389B71 */ { { 0x10, 0x16, 0x00, 0x00, 0x00, 0x00, 0x10, 0x00, 0x80, 0x00, 0x00, 0xAA, 0x00, 0x38, 0x9B, 0x71 }, "MEDIASUBTYPE_MPEG_HEAAC", TSMF_SUB_TYPE_AAC }, /* 34363248-0000-0010-8000-00AA00389B71 */ { { 0x48, 0x32, 0x36, 0x34, 0x00, 0x00, 0x10, 0x00, 0x80, 0x00, 0x00, 0xAA, 0x00, 0x38, 0x9B, 0x71 }, "MEDIASUBTYPE_H264", TSMF_SUB_TYPE_H264 }, /* 31435641-0000-0010-8000-00AA00389B71 */ { { 0x41, 0x56, 0x43, 0x31, 0x00, 0x00, 0x10, 0x00, 0x80, 0x00, 0x00, 0xAA, 0x00, 0x38, 0x9B, 0x71 }, "MEDIASUBTYPE_AVC1", TSMF_SUB_TYPE_AVC1 }, /* E06D802C-DB46-11CF-B4D1-00805F6CBBEA */ { { 0x2C, 0x80, 0x6D, 0xE0, 0x46, 0xDB, 0xCF, 0x11, 0xB4, 0xD1, 0x00, 0x80, 0x5F, 0x6C, 0xBB, 0xEA }, "MEDIASUBTYPE_DOLBY_AC3", TSMF_SUB_TYPE_AC3 }, { { 0 }, "Unknown", TSMF_SUB_TYPE_UNKNOWN } }; static const TSMFMediaTypeMap tsmf_format_type_map[] = { /* AED4AB2D-7326-43CB-9464-C879CAB9C43D */ { { 0x2D, 0xAB, 0xD4, 0xAE, 0x26, 0x73, 0xCB, 0x43, 0x94, 0x64, 0xC8, 0x79, 0xCA, 0xB9, 0xC4, 0x3D }, "FORMAT_MFVideoFormat", TSMF_FORMAT_TYPE_MFVIDEOFORMAT }, /* 05589F81-C356-11CE-BF01-00AA0055595A */ { { 0x81, 0x9F, 0x58, 0x05, 0x56, 0xC3, 0xCE, 0x11, 0xBF, 0x01, 0x00, 0xAA, 0x00, 0x55, 0x59, 0x5A }, "FORMAT_WaveFormatEx", TSMF_FORMAT_TYPE_WAVEFORMATEX }, /* E06D80E3-DB46-11CF-B4D1-00805F6CBBEA */ { { 0xE3, 0x80, 0x6D, 0xE0, 0x46, 0xDB, 0xCF, 0x11, 0xB4, 0xD1, 0x00, 0x80, 0x5F, 0x6C, 0xBB, 0xEA }, "FORMAT_MPEG2_VIDEO", TSMF_FORMAT_TYPE_MPEG2VIDEOINFO }, /* F72A76A0-EB0A-11D0-ACE4-0000C0CC16BA */ { { 0xA0, 0x76, 0x2A, 0xF7, 0x0A, 0xEB, 0xD0, 0x11, 0xAC, 0xE4, 0x00, 0x00, 0xC0, 0xCC, 0x16, 0xBA }, "FORMAT_VideoInfo2", TSMF_FORMAT_TYPE_VIDEOINFO2 }, { { 0 }, "Unknown", TSMF_FORMAT_TYPE_UNKNOWN } }; static void tsmf_print_guid(const uint8* guid) { #ifdef WITH_DEBUG_DVC int i; for (i = 3; i >= 0; i--) printf("%02X", guid[i]); printf("-"); for (i = 5; i >= 4; i--) printf("%02X", guid[i]); printf("-"); for (i = 7; i >= 6; i--) printf("%02X", guid[i]); printf("-"); for (i = 8; i < 16; i++) { printf("%02X", guid[i]); if (i == 9) printf("-"); } printf("\n"); #endif } /* http://msdn.microsoft.com/en-us/library/dd318229.aspx */ static uint32 tsmf_codec_parse_BITMAPINFOHEADER(TS_AM_MEDIA_TYPE* mediatype, STREAM* s, boolean bypass) { uint32 biSize; uint32 biWidth; uint32 biHeight; stream_read_uint32(s, biSize); stream_read_uint32(s, biWidth); stream_read_uint32(s, biHeight); stream_seek(s, 28); if (mediatype->Width == 0) mediatype->Width = biWidth; if (mediatype->Height == 0) mediatype->Height = biHeight; /* Assume there will be no color table for video? */ if (bypass && biSize > 40) stream_seek(s, biSize - 40); return (bypass ? biSize : 40); } /* http://msdn.microsoft.com/en-us/library/dd407326.aspx */ static uint32 tsmf_codec_parse_VIDEOINFOHEADER2(TS_AM_MEDIA_TYPE* mediatype, STREAM* s) { uint64 AvgTimePerFrame; /* VIDEOINFOHEADER2.rcSource, RECT(LONG left, LONG top, LONG right, LONG bottom) */ stream_seek_uint32(s); stream_seek_uint32(s); stream_read_uint32(s, mediatype->Width); stream_read_uint32(s, mediatype->Height); /* VIDEOINFOHEADER2.rcTarget */ stream_seek(s, 16); /* VIDEOINFOHEADER2.dwBitRate */ stream_read_uint32(s, mediatype->BitRate); /* VIDEOINFOHEADER2.dwBitErrorRate */ stream_seek_uint32(s); /* VIDEOINFOHEADER2.AvgTimePerFrame */ stream_read_uint64(s, AvgTimePerFrame); mediatype->SamplesPerSecond.Numerator = 1000000; mediatype->SamplesPerSecond.Denominator = (int)(AvgTimePerFrame / 10LL); /* Remaining fields before bmiHeader */ stream_seek(s, 24); return 72; } boolean tsmf_codec_parse_media_type(TS_AM_MEDIA_TYPE* mediatype, STREAM* s) { int i; uint32 cbFormat; boolean ret = true; memset(mediatype, 0, sizeof(TS_AM_MEDIA_TYPE)); /* MajorType */ DEBUG_DVC("MajorType:"); tsmf_print_guid(stream_get_tail(s)); for (i = 0; tsmf_major_type_map[i].type != TSMF_MAJOR_TYPE_UNKNOWN; i++) { if (memcmp(tsmf_major_type_map[i].guid, stream_get_tail(s), 16) == 0) break; } mediatype->MajorType = tsmf_major_type_map[i].type; if (mediatype->MajorType == TSMF_MAJOR_TYPE_UNKNOWN) ret = false; DEBUG_DVC("MajorType %s", tsmf_major_type_map[i].name); stream_seek(s, 16); /* SubType */ DEBUG_DVC("SubType:"); tsmf_print_guid(stream_get_tail(s)); for (i = 0; tsmf_sub_type_map[i].type != TSMF_SUB_TYPE_UNKNOWN; i++) { if (memcmp(tsmf_sub_type_map[i].guid, stream_get_tail(s), 16) == 0) break; } mediatype->SubType = tsmf_sub_type_map[i].type; if (mediatype->SubType == TSMF_SUB_TYPE_UNKNOWN) ret = false; DEBUG_DVC("SubType %s", tsmf_sub_type_map[i].name); stream_seek(s, 16); /* bFixedSizeSamples, bTemporalCompression, SampleSize */ stream_seek(s, 12); /* FormatType */ DEBUG_DVC("FormatType:"); tsmf_print_guid(stream_get_tail(s)); for (i = 0; tsmf_format_type_map[i].type != TSMF_FORMAT_TYPE_UNKNOWN; i++) { if (memcmp(tsmf_format_type_map[i].guid, stream_get_tail(s), 16) == 0) break; } mediatype->FormatType = tsmf_format_type_map[i].type; if (mediatype->FormatType == TSMF_FORMAT_TYPE_UNKNOWN) ret = false; DEBUG_DVC("FormatType %s", tsmf_format_type_map[i].name); stream_seek(s, 16); /* cbFormat */ stream_read_uint32(s, cbFormat); DEBUG_DVC("cbFormat %d", cbFormat); #ifdef WITH_DEBUG_DVC freerdp_hexdump(stream_get_tail(s), cbFormat); #endif switch (mediatype->FormatType) { case TSMF_FORMAT_TYPE_MFVIDEOFORMAT: /* http://msdn.microsoft.com/en-us/library/aa473808.aspx */ stream_seek(s, 8); /* dwSize and ? */ stream_read_uint32(s, mediatype->Width); /* videoInfo.dwWidth */ stream_read_uint32(s, mediatype->Height); /* videoInfo.dwHeight */ stream_seek(s, 32); /* videoInfo.FramesPerSecond */ stream_read_uint32(s, mediatype->SamplesPerSecond.Numerator); stream_read_uint32(s, mediatype->SamplesPerSecond.Denominator); stream_seek(s, 80); stream_read_uint32(s, mediatype->BitRate); /* compressedInfo.AvgBitrate */ stream_seek(s, 36); if (cbFormat > 176) { mediatype->ExtraDataSize = cbFormat - 176; mediatype->ExtraData = stream_get_tail(s); } break; case TSMF_FORMAT_TYPE_WAVEFORMATEX: /* http://msdn.microsoft.com/en-us/library/dd757720.aspx */ stream_seek_uint16(s); stream_read_uint16(s, mediatype->Channels); stream_read_uint32(s, mediatype->SamplesPerSecond.Numerator); mediatype->SamplesPerSecond.Denominator = 1; stream_read_uint32(s, mediatype->BitRate); mediatype->BitRate *= 8; stream_read_uint16(s, mediatype->BlockAlign); stream_read_uint16(s, mediatype->BitsPerSample); stream_read_uint16(s, mediatype->ExtraDataSize); if (mediatype->ExtraDataSize > 0) mediatype->ExtraData = stream_get_tail(s); break; case TSMF_FORMAT_TYPE_MPEG2VIDEOINFO: /* http://msdn.microsoft.com/en-us/library/dd390707.aspx */ i = tsmf_codec_parse_VIDEOINFOHEADER2(mediatype, s); i += tsmf_codec_parse_BITMAPINFOHEADER(mediatype, s, true); if (cbFormat > i) { mediatype->ExtraDataSize = cbFormat - i; mediatype->ExtraData = stream_get_tail(s); } break; case TSMF_FORMAT_TYPE_VIDEOINFO2: i = tsmf_codec_parse_VIDEOINFOHEADER2(mediatype, s); i += tsmf_codec_parse_BITMAPINFOHEADER(mediatype, s, false); if (cbFormat > i) { mediatype->ExtraDataSize = cbFormat - i; mediatype->ExtraData = stream_get_tail(s); } break; default: break; } if (mediatype->SamplesPerSecond.Numerator == 0) mediatype->SamplesPerSecond.Numerator = 1; if (mediatype->SamplesPerSecond.Denominator == 0) mediatype->SamplesPerSecond.Denominator = 1; return ret; } boolean tsmf_codec_check_media_type(STREAM* s) { uint8* m; boolean ret; TS_AM_MEDIA_TYPE mediatype; stream_get_mark(s, m); ret = tsmf_codec_parse_media_type(&mediatype, s); stream_set_mark(s, m); return ret; } FreeRDP-1.0.2/channels/drdynvc/tsmf/tsmf_codec.h000066400000000000000000000015761207112532300214420ustar00rootroot00000000000000/** * FreeRDP: A Remote Desktop Protocol client. * Video Redirection Virtual Channel - Codec * * Copyright 2010-2011 Vic Lee * * 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. */ #ifndef __TSMF_CODEC #define __TSMF_CODEC #include "tsmf_types.h" boolean tsmf_codec_parse_media_type(TS_AM_MEDIA_TYPE* mediatype, STREAM* s); boolean tsmf_codec_check_media_type(STREAM* s); #endif FreeRDP-1.0.2/channels/drdynvc/tsmf/tsmf_constants.h000066400000000000000000000115611207112532300223740ustar00rootroot00000000000000/** * FreeRDP: A Remote Desktop Protocol client. * Video Redirection Virtual Channel - Constants * * Copyright 2010-2011 Vic Lee * * 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. */ #ifndef __TSMF_CONSTANTS_H #define __TSMF_CONSTANTS_H #define GUID_SIZE 16 #define TSMF_BUFFER_PADDING_SIZE 8 /* Interface IDs defined in [MS-RDPEV]. There's no constant names in the MS documentation, so we create them on our own. */ #define TSMF_INTERFACE_DEFAULT 0x00000000 #define TSMF_INTERFACE_CLIENT_NOTIFICATIONS 0x00000001 #define TSMF_INTERFACE_CAPABILITIES 0x00000002 /* Interface ID Mask */ #define STREAM_ID_STUB 0x80000000 #define STREAM_ID_PROXY 0x40000000 #define STREAM_ID_NONE 0x00000000 /* Functon ID */ /* Common IDs for all interfaces are as follows. */ #define RIMCALL_RELEASE 0x00000001 #define RIMCALL_QUERYINTERFACE 0x00000002 /* Capabilities Negotiator Interface IDs are as follows. */ #define RIM_EXCHANGE_CAPABILITY_REQUEST 0x00000100 /* The Client Notifications Interface ID is as follows. */ #define PLAYBACK_ACK 0x00000100 #define CLIENT_EVENT_NOTIFICATION 0x00000101 /* Server Data Interface IDs are as follows. */ #define EXCHANGE_CAPABILITIES_REQ 0x00000100 #define SET_CHANNEL_PARAMS 0x00000101 #define ADD_STREAM 0x00000102 #define ON_SAMPLE 0x00000103 #define SET_VIDEO_WINDOW 0x00000104 #define ON_NEW_PRESENTATION 0x00000105 #define SHUTDOWN_PRESENTATION_REQ 0x00000106 #define SET_TOPOLOGY_REQ 0x00000107 #define CHECK_FORMAT_SUPPORT_REQ 0x00000108 #define ON_PLAYBACK_STARTED 0x00000109 #define ON_PLAYBACK_PAUSED 0x0000010a #define ON_PLAYBACK_STOPPED 0x0000010b #define ON_PLAYBACK_RESTARTED 0x0000010c #define ON_PLAYBACK_RATE_CHANGED 0x0000010d #define ON_FLUSH 0x0000010e #define ON_STREAM_VOLUME 0x0000010f #define ON_CHANNEL_VOLUME 0x00000110 #define ON_END_OF_STREAM 0x00000111 #define SET_ALLOCATOR 0x00000112 #define NOTIFY_PREROLL 0x00000113 #define UPDATE_GEOMETRY_INFO 0x00000114 #define REMOVE_STREAM 0x00000115 /* Supported platform */ #define MMREDIR_CAPABILITY_PLATFORM_MF 0x00000001 #define MMREDIR_CAPABILITY_PLATFORM_DSHOW 0x00000002 #define MMREDIR_CAPABILITY_PLATFORM_OTHER 0x00000004 /* TSMM_CLIENT_EVENT Constants */ #define TSMM_CLIENT_EVENT_ENDOFSTREAM 0x0064 #define TSMM_CLIENT_EVENT_STOP_COMPLETED 0x00C8 #define TSMM_CLIENT_EVENT_START_COMPLETED 0x00C9 #define TSMM_CLIENT_EVENT_MONITORCHANGED 0x012C /* TS_MM_DATA_SAMPLE.SampleExtensions */ #define TSMM_SAMPLE_EXT_CLEANPOINT 0x00000001 #define TSMM_SAMPLE_EXT_DISCONTINUITY 0x00000002 #define TSMM_SAMPLE_EXT_INTERLACED 0x00000004 #define TSMM_SAMPLE_EXT_BOTTOMFIELDFIRST 0x00000008 #define TSMM_SAMPLE_EXT_REPEATFIELDFIRST 0x00000010 #define TSMM_SAMPLE_EXT_SINGLEFIELD 0x00000020 #define TSMM_SAMPLE_EXT_DERIVEDFROMTOPFIELD 0x00000040 #define TSMM_SAMPLE_EXT_HAS_NO_TIMESTAMPS 0x00000080 #define TSMM_SAMPLE_EXT_RELATIVE_TIMESTAMPS 0x00000100 #define TSMM_SAMPLE_EXT_ABSOLUTE_TIMESTAMPS 0x00000200 /* MajorType */ #define TSMF_MAJOR_TYPE_UNKNOWN 0 #define TSMF_MAJOR_TYPE_VIDEO 1 #define TSMF_MAJOR_TYPE_AUDIO 2 /* SubType */ #define TSMF_SUB_TYPE_UNKNOWN 0 #define TSMF_SUB_TYPE_WVC1 1 #define TSMF_SUB_TYPE_WMA2 2 #define TSMF_SUB_TYPE_WMA9 3 #define TSMF_SUB_TYPE_MP3 4 #define TSMF_SUB_TYPE_MP2A 5 #define TSMF_SUB_TYPE_MP2V 6 #define TSMF_SUB_TYPE_WMV3 7 #define TSMF_SUB_TYPE_AAC 8 #define TSMF_SUB_TYPE_H264 9 #define TSMF_SUB_TYPE_AVC1 10 #define TSMF_SUB_TYPE_AC3 11 /* FormatType */ #define TSMF_FORMAT_TYPE_UNKNOWN 0 #define TSMF_FORMAT_TYPE_MFVIDEOFORMAT 1 #define TSMF_FORMAT_TYPE_WAVEFORMATEX 2 #define TSMF_FORMAT_TYPE_MPEG2VIDEOINFO 3 #define TSMF_FORMAT_TYPE_VIDEOINFO2 4 #endif FreeRDP-1.0.2/channels/drdynvc/tsmf/tsmf_decoder.c000066400000000000000000000037151207112532300217620ustar00rootroot00000000000000/** * FreeRDP: A Remote Desktop Protocol client. * Video Redirection Virtual Channel - Decoder * * Copyright 2010-2011 Vic Lee * * 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. */ #include #include #include #include #include #include "drdynvc_types.h" #include "tsmf_types.h" #include "tsmf_constants.h" #include "tsmf_decoder.h" static ITSMFDecoder* tsmf_load_decoder_by_name(const char* name, TS_AM_MEDIA_TYPE* media_type) { ITSMFDecoder* decoder; TSMF_DECODER_ENTRY entry; char* fullname; if (strrchr(name, '.') != NULL) entry = (TSMF_DECODER_ENTRY) freerdp_load_plugin(name, TSMF_DECODER_EXPORT_FUNC_NAME); else { fullname = xzalloc(strlen(name) + 6); strcpy(fullname, "tsmf_"); strcat(fullname, name); entry = (TSMF_DECODER_ENTRY) freerdp_load_plugin(fullname, TSMF_DECODER_EXPORT_FUNC_NAME); xfree(fullname); } if (entry == NULL) { return NULL; } decoder = entry(); if (decoder == NULL) { DEBUG_WARN("failed to call export function in %s", name); return NULL; } if (!decoder->SetFormat(decoder, media_type)) { decoder->Free(decoder); decoder = NULL; } return decoder; } ITSMFDecoder* tsmf_load_decoder(const char* name, TS_AM_MEDIA_TYPE* media_type) { ITSMFDecoder* decoder; if (name) { decoder = tsmf_load_decoder_by_name(name, media_type); } else { decoder = tsmf_load_decoder_by_name("ffmpeg", media_type); } return decoder; } FreeRDP-1.0.2/channels/drdynvc/tsmf/tsmf_decoder.h000066400000000000000000000033011207112532300217560ustar00rootroot00000000000000/** * FreeRDP: A Remote Desktop Protocol client. * Video Redirection Virtual Channel - Decoder * * Copyright 2010-2011 Vic Lee * * 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. */ #ifndef __TSMF_DECODER_H #define __TSMF_DECODER_H #include "drdynvc_types.h" #include "tsmf_types.h" typedef struct _ITSMFDecoder ITSMFDecoder; struct _ITSMFDecoder { /* Set the decoder format. Return true if supported. */ boolean (*SetFormat) (ITSMFDecoder* decoder, TS_AM_MEDIA_TYPE* media_type); /* Decode a sample. */ boolean (*Decode) (ITSMFDecoder* decoder, const uint8* data, uint32 data_size, uint32 extensions); /* Get the decoded data */ uint8* (*GetDecodedData) (ITSMFDecoder* decoder, uint32* size); /* Get the pixel format of decoded video frame */ uint32 (*GetDecodedFormat) (ITSMFDecoder* decoder); /* Get the width and height of decoded video frame */ boolean (*GetDecodedDimension) (ITSMFDecoder* decoder, uint32* width, uint32* height); /* Free the decoder */ void (*Free) (ITSMFDecoder* decoder); }; #define TSMF_DECODER_EXPORT_FUNC_NAME "TSMFDecoderEntry" typedef ITSMFDecoder* (*TSMF_DECODER_ENTRY) (void); ITSMFDecoder* tsmf_load_decoder(const char* name, TS_AM_MEDIA_TYPE* media_type); #endif FreeRDP-1.0.2/channels/drdynvc/tsmf/tsmf_ifman.c000066400000000000000000000316261207112532300214510ustar00rootroot00000000000000/** * FreeRDP: A Remote Desktop Protocol client. * Video Redirection Virtual Channel - Interface Manipulation * * Copyright 2010-2011 Vic Lee * * 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. */ #include #include #include #include #include #include "drdynvc_types.h" #include "tsmf_constants.h" #include "tsmf_media.h" #include "tsmf_codec.h" #include "tsmf_ifman.h" int tsmf_ifman_rim_exchange_capability_request(TSMF_IFMAN* ifman) { uint32 CapabilityValue; stream_read_uint32(ifman->input, CapabilityValue); DEBUG_DVC("server CapabilityValue %d", CapabilityValue); stream_check_size(ifman->output, 8); stream_write_uint32(ifman->output, 1); /* CapabilityValue */ stream_write_uint32(ifman->output, 0); /* Result */ return 0; } int tsmf_ifman_exchange_capability_request(TSMF_IFMAN* ifman) { uint32 i; uint32 v; uint32 pos; uint32 CapabilityType; uint32 cbCapabilityLength; uint32 numHostCapabilities; pos = stream_get_pos(ifman->output); stream_check_size(ifman->output, ifman->input_size + 4); stream_copy(ifman->output, ifman->input, ifman->input_size); stream_set_pos(ifman->output, pos); stream_read_uint32(ifman->output, numHostCapabilities); for (i = 0; i < numHostCapabilities; i++) { stream_read_uint32(ifman->output, CapabilityType); stream_read_uint32(ifman->output, cbCapabilityLength); pos = stream_get_pos(ifman->output); switch (CapabilityType) { case 1: /* Protocol version request */ stream_read_uint32(ifman->output, v); DEBUG_DVC("server protocol version %d", v); break; case 2: /* Supported platform */ stream_peek_uint32(ifman->output, v); DEBUG_DVC("server supported platform %d", v); /* Claim that we support both MF and DShow platforms. */ stream_write_uint32(ifman->output, MMREDIR_CAPABILITY_PLATFORM_MF | MMREDIR_CAPABILITY_PLATFORM_DSHOW); break; default: DEBUG_WARN("unknown capability type %d", CapabilityType); break; } stream_set_pos(ifman->output, pos + cbCapabilityLength); } stream_write_uint32(ifman->output, 0); /* Result */ ifman->output_interface_id = TSMF_INTERFACE_DEFAULT | STREAM_ID_STUB; return 0; } int tsmf_ifman_check_format_support_request(TSMF_IFMAN* ifman) { uint32 numMediaType; uint32 PlatformCookie; uint32 FormatSupported = 1; stream_read_uint32(ifman->input, PlatformCookie); stream_seek_uint32(ifman->input); /* NoRolloverFlags (4 bytes) */ stream_read_uint32(ifman->input, numMediaType); DEBUG_DVC("PlatformCookie %d numMediaType %d", PlatformCookie, numMediaType); if (!tsmf_codec_check_media_type(ifman->input)) FormatSupported = 0; if (FormatSupported) DEBUG_DVC("format ok."); stream_check_size(ifman->output, 12); stream_write_uint32(ifman->output, FormatSupported); stream_write_uint32(ifman->output, PlatformCookie); stream_write_uint32(ifman->output, 0); /* Result */ ifman->output_interface_id = TSMF_INTERFACE_DEFAULT | STREAM_ID_STUB; return 0; } int tsmf_ifman_on_new_presentation(TSMF_IFMAN* ifman) { int error = 0; TSMF_PRESENTATION* presentation; DEBUG_DVC(""); presentation = tsmf_presentation_new(stream_get_tail(ifman->input), ifman->channel_callback); if (presentation == NULL) error = 1; tsmf_presentation_set_audio_device(presentation, ifman->audio_name, ifman->audio_device); ifman->output_pending = true; return error; } int tsmf_ifman_add_stream(TSMF_IFMAN* ifman) { uint32 StreamId; int error = 0; TSMF_STREAM* stream; TSMF_PRESENTATION* presentation; DEBUG_DVC(""); presentation = tsmf_presentation_find_by_id(stream_get_tail(ifman->input)); stream_seek(ifman->input, 16); if (presentation == NULL) error = 1; else { stream_read_uint32(ifman->input, StreamId); stream_seek_uint32(ifman->input); /* numMediaType */ stream = tsmf_stream_new(presentation, StreamId); if (stream) tsmf_stream_set_format(stream, ifman->decoder_name, ifman->input); } ifman->output_pending = true; return error; } int tsmf_ifman_set_topology_request(TSMF_IFMAN* ifman) { DEBUG_DVC(""); stream_check_size(ifman->output, 8); stream_write_uint32(ifman->output, 1); /* TopologyReady */ stream_write_uint32(ifman->output, 0); /* Result */ ifman->output_interface_id = TSMF_INTERFACE_DEFAULT | STREAM_ID_STUB; return 0; } int tsmf_ifman_remove_stream(TSMF_IFMAN* ifman) { int error = 0; uint32 StreamId; TSMF_STREAM* stream; TSMF_PRESENTATION* presentation; DEBUG_DVC(""); presentation = tsmf_presentation_find_by_id(stream_get_tail(ifman->input)); stream_seek(ifman->input, 16); if (presentation == NULL) error = 1; else { stream_read_uint32(ifman->input, StreamId); stream = tsmf_stream_find_by_id(presentation, StreamId); if (stream) tsmf_stream_free(stream); else error = 1; } ifman->output_pending = true; return error; } int tsmf_ifman_shutdown_presentation(TSMF_IFMAN* ifman) { TSMF_PRESENTATION* presentation; DEBUG_DVC(""); presentation = tsmf_presentation_find_by_id(stream_get_tail(ifman->input)); if (presentation) tsmf_presentation_free(presentation); stream_check_size(ifman->output, 4); stream_write_uint32(ifman->output, 0); /* Result */ ifman->output_interface_id = TSMF_INTERFACE_DEFAULT | STREAM_ID_STUB; return 0; } int tsmf_ifman_on_stream_volume(TSMF_IFMAN* ifman) { DEBUG_DVC(""); ifman->output_pending = true; return 0; } int tsmf_ifman_on_channel_volume(TSMF_IFMAN* ifman) { DEBUG_DVC(""); ifman->output_pending = true; return 0; } int tsmf_ifman_set_video_window(TSMF_IFMAN* ifman) { DEBUG_DVC(""); ifman->output_pending = true; return 0; } int tsmf_ifman_update_geometry_info(TSMF_IFMAN* ifman) { TSMF_PRESENTATION* presentation; uint32 numGeometryInfo; uint32 Left; uint32 Top; uint32 Width; uint32 Height; uint32 cbVisibleRect; RDP_RECT* rects = NULL; int num_rects = 0; int error = 0; int i; int pos; presentation = tsmf_presentation_find_by_id(stream_get_tail(ifman->input)); stream_seek(ifman->input, 16); stream_read_uint32(ifman->input, numGeometryInfo); pos = stream_get_pos(ifman->input); stream_seek(ifman->input, 12); /* VideoWindowId (8 bytes), VideoWindowState (4 bytes) */ stream_read_uint32(ifman->input, Width); stream_read_uint32(ifman->input, Height); stream_read_uint32(ifman->input, Left); stream_read_uint32(ifman->input, Top); stream_set_pos(ifman->input, pos + numGeometryInfo); stream_read_uint32(ifman->input, cbVisibleRect); num_rects = cbVisibleRect / 16; DEBUG_DVC("numGeometryInfo %d Width %d Height %d Left %d Top %d cbVisibleRect %d num_rects %d", numGeometryInfo, Width, Height, Left, Top, cbVisibleRect, num_rects); if (presentation == NULL) error = 1; else { if (num_rects > 0) { rects = (RDP_RECT*) xzalloc(sizeof(RDP_RECT) * num_rects); for (i = 0; i < num_rects; i++) { stream_read_uint16(ifman->input, rects[i].y); /* Top */ stream_seek_uint16(ifman->input); stream_read_uint16(ifman->input, rects[i].x); /* Left */ stream_seek_uint16(ifman->input); stream_read_uint16(ifman->input, rects[i].height); /* Bottom */ stream_seek_uint16(ifman->input); stream_read_uint16(ifman->input, rects[i].width); /* Right */ stream_seek_uint16(ifman->input); rects[i].width -= rects[i].x; rects[i].height -= rects[i].y; DEBUG_DVC("rect %d: %d %d %d %d", i, rects[i].x, rects[i].y, rects[i].width, rects[i].height); } } tsmf_presentation_set_geometry_info(presentation, Left, Top, Width, Height, num_rects, rects); } ifman->output_pending = true; return error; } int tsmf_ifman_set_allocator(TSMF_IFMAN* ifman) { DEBUG_DVC(""); ifman->output_pending = true; return 0; } int tsmf_ifman_notify_preroll(TSMF_IFMAN* ifman) { DEBUG_DVC(""); ifman->output_pending = true; return 0; } int tsmf_ifman_on_sample(TSMF_IFMAN* ifman) { TSMF_PRESENTATION* presentation; TSMF_STREAM* stream; uint32 StreamId; uint64 SampleStartTime; uint64 SampleEndTime; uint64 ThrottleDuration; uint32 SampleExtensions; uint32 cbData; stream_seek(ifman->input, 16); stream_read_uint32(ifman->input, StreamId); stream_seek_uint32(ifman->input); /* numSample */ stream_read_uint64(ifman->input, SampleStartTime); stream_read_uint64(ifman->input, SampleEndTime); stream_read_uint64(ifman->input, ThrottleDuration); stream_seek_uint32(ifman->input); /* SampleFlags */ stream_read_uint32(ifman->input, SampleExtensions); stream_read_uint32(ifman->input, cbData); DEBUG_DVC("MessageId %d StreamId %d SampleStartTime %d SampleEndTime %d " "ThrottleDuration %d SampleExtensions %d cbData %d", ifman->message_id, StreamId, (int)SampleStartTime, (int)SampleEndTime, (int)ThrottleDuration, SampleExtensions, cbData); presentation = tsmf_presentation_find_by_id(ifman->presentation_id); if (presentation == NULL) { DEBUG_WARN("unknown presentation id"); return 1; } stream = tsmf_stream_find_by_id(presentation, StreamId); if (stream == NULL) { DEBUG_WARN("unknown stream id"); return 1; } tsmf_stream_push_sample(stream, ifman->channel_callback, ifman->message_id, SampleStartTime, SampleEndTime, ThrottleDuration, SampleExtensions, cbData, stream_get_tail(ifman->input)); ifman->output_pending = true; return 0; } int tsmf_ifman_on_flush(TSMF_IFMAN* ifman) { TSMF_PRESENTATION* presentation; uint32 StreamId; stream_seek(ifman->input, 16); stream_read_uint32(ifman->input, StreamId); DEBUG_DVC("StreamId %d", StreamId); presentation = tsmf_presentation_find_by_id(ifman->presentation_id); if (presentation == NULL) { DEBUG_WARN("unknown presentation id"); return 1; } tsmf_presentation_flush(presentation); ifman->output_pending = true; return 0; } int tsmf_ifman_on_end_of_stream(TSMF_IFMAN* ifman) { TSMF_PRESENTATION* presentation; TSMF_STREAM* stream; uint32 StreamId; presentation = tsmf_presentation_find_by_id(stream_get_tail(ifman->input)); stream_seek(ifman->input, 16); stream_read_uint32(ifman->input, StreamId); stream = tsmf_stream_find_by_id(presentation, StreamId); tsmf_stream_end(stream); DEBUG_DVC("StreamId %d", StreamId); stream_check_size(ifman->output, 16); stream_write_uint32(ifman->output, CLIENT_EVENT_NOTIFICATION); /* FunctionId */ stream_write_uint32(ifman->output, StreamId); /* StreamId */ stream_write_uint32(ifman->output, TSMM_CLIENT_EVENT_ENDOFSTREAM); /* EventId */ stream_write_uint32(ifman->output, 0); /* cbData */ ifman->output_interface_id = TSMF_INTERFACE_CLIENT_NOTIFICATIONS | STREAM_ID_PROXY; return 0; } int tsmf_ifman_on_playback_started(TSMF_IFMAN* ifman) { TSMF_PRESENTATION* presentation; DEBUG_DVC(""); presentation = tsmf_presentation_find_by_id(stream_get_tail(ifman->input)); if (presentation) tsmf_presentation_start(presentation); else DEBUG_WARN("unknown presentation id"); stream_check_size(ifman->output, 16); stream_write_uint32(ifman->output, CLIENT_EVENT_NOTIFICATION); /* FunctionId */ stream_write_uint32(ifman->output, 0); /* StreamId */ stream_write_uint32(ifman->output, TSMM_CLIENT_EVENT_START_COMPLETED); /* EventId */ stream_write_uint32(ifman->output, 0); /* cbData */ ifman->output_interface_id = TSMF_INTERFACE_CLIENT_NOTIFICATIONS | STREAM_ID_PROXY; return 0; } int tsmf_ifman_on_playback_paused(TSMF_IFMAN* ifman) { DEBUG_DVC(""); ifman->output_pending = true; return 0; } int tsmf_ifman_on_playback_restarted(TSMF_IFMAN* ifman) { DEBUG_DVC(""); ifman->output_pending = true; return 0; } int tsmf_ifman_on_playback_stopped(TSMF_IFMAN* ifman) { TSMF_PRESENTATION* presentation; DEBUG_DVC(""); presentation = tsmf_presentation_find_by_id(stream_get_tail(ifman->input)); if (presentation) tsmf_presentation_stop(presentation); else DEBUG_WARN("unknown presentation id"); stream_check_size(ifman->output, 16); stream_write_uint32(ifman->output, CLIENT_EVENT_NOTIFICATION); /* FunctionId */ stream_write_uint32(ifman->output, 0); /* StreamId */ stream_write_uint32(ifman->output, TSMM_CLIENT_EVENT_STOP_COMPLETED); /* EventId */ stream_write_uint32(ifman->output, 0); /* cbData */ ifman->output_interface_id = TSMF_INTERFACE_CLIENT_NOTIFICATIONS | STREAM_ID_PROXY; return 0; } int tsmf_ifman_on_playback_rate_changed(TSMF_IFMAN * ifman) { DEBUG_DVC(""); stream_check_size(ifman->output, 16); stream_write_uint32(ifman->output, CLIENT_EVENT_NOTIFICATION); /* FunctionId */ stream_write_uint32(ifman->output, 0); /* StreamId */ stream_write_uint32(ifman->output, TSMM_CLIENT_EVENT_MONITORCHANGED); /* EventId */ stream_write_uint32(ifman->output, 0); /* cbData */ ifman->output_interface_id = TSMF_INTERFACE_CLIENT_NOTIFICATIONS | STREAM_ID_PROXY; return 0; } FreeRDP-1.0.2/channels/drdynvc/tsmf/tsmf_ifman.h000066400000000000000000000044211207112532300214470ustar00rootroot00000000000000/** * FreeRDP: A Remote Desktop Protocol client. * Video Redirection Virtual Channel - Interface Manipulation * * Copyright 2010-2011 Vic Lee * * 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. */ #ifndef __TSMF_IFMAN_H #define __TSMF_IFMAN_H typedef struct _TSMF_IFMAN TSMF_IFMAN; struct _TSMF_IFMAN { IWTSVirtualChannelCallback* channel_callback; const char* decoder_name; const char* audio_name; const char* audio_device; uint8 presentation_id[16]; uint32 stream_id; uint32 message_id; STREAM* input; uint32 input_size; STREAM* output; boolean output_pending; uint32 output_interface_id; }; int tsmf_ifman_rim_exchange_capability_request(TSMF_IFMAN* ifman); int tsmf_ifman_exchange_capability_request(TSMF_IFMAN* ifman); int tsmf_ifman_check_format_support_request(TSMF_IFMAN* ifman); int tsmf_ifman_on_new_presentation(TSMF_IFMAN* ifman); int tsmf_ifman_add_stream(TSMF_IFMAN* ifman); int tsmf_ifman_set_topology_request(TSMF_IFMAN* ifman); int tsmf_ifman_remove_stream(TSMF_IFMAN* ifman); int tsmf_ifman_shutdown_presentation(TSMF_IFMAN* ifman); int tsmf_ifman_on_stream_volume(TSMF_IFMAN* ifman); int tsmf_ifman_on_channel_volume(TSMF_IFMAN* ifman); int tsmf_ifman_set_video_window(TSMF_IFMAN* ifman); int tsmf_ifman_update_geometry_info(TSMF_IFMAN* ifman); int tsmf_ifman_set_allocator(TSMF_IFMAN* ifman); int tsmf_ifman_notify_preroll(TSMF_IFMAN* ifman); int tsmf_ifman_on_sample(TSMF_IFMAN* ifman); int tsmf_ifman_on_flush(TSMF_IFMAN* ifman); int tsmf_ifman_on_end_of_stream(TSMF_IFMAN* ifman); int tsmf_ifman_on_playback_started(TSMF_IFMAN* ifman); int tsmf_ifman_on_playback_paused(TSMF_IFMAN* ifman); int tsmf_ifman_on_playback_restarted(TSMF_IFMAN* ifman); int tsmf_ifman_on_playback_stopped(TSMF_IFMAN* ifman); int tsmf_ifman_on_playback_rate_changed(TSMF_IFMAN* ifman); #endif FreeRDP-1.0.2/channels/drdynvc/tsmf/tsmf_main.c000066400000000000000000000260641207112532300213030ustar00rootroot00000000000000/** * FreeRDP: A Remote Desktop Protocol client. * Video Redirection Virtual Channel * * Copyright 2010-2011 Vic Lee * * 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. */ #include #include #include #include #include #include "drdynvc_types.h" #include "tsmf_constants.h" #include "tsmf_ifman.h" #include "tsmf_media.h" #include "tsmf_main.h" typedef struct _TSMF_LISTENER_CALLBACK TSMF_LISTENER_CALLBACK; typedef struct _TSMF_CHANNEL_CALLBACK TSMF_CHANNEL_CALLBACK; typedef struct _TSMF_PLUGIN TSMF_PLUGIN; struct _TSMF_LISTENER_CALLBACK { IWTSListenerCallback iface; IWTSPlugin* plugin; IWTSVirtualChannelManager* channel_mgr; }; struct _TSMF_CHANNEL_CALLBACK { IWTSVirtualChannelCallback iface; IWTSPlugin* plugin; IWTSVirtualChannelManager* channel_mgr; IWTSVirtualChannel* channel; uint8 presentation_id[16]; uint32 stream_id; }; struct _TSMF_PLUGIN { IWTSPlugin iface; TSMF_LISTENER_CALLBACK* listener_callback; const char* decoder_name; const char* audio_name; const char* audio_device; }; void tsmf_playback_ack(IWTSVirtualChannelCallback* pChannelCallback, uint32 message_id, uint64 duration, uint32 data_size) { STREAM* s; int error; TSMF_CHANNEL_CALLBACK* callback = (TSMF_CHANNEL_CALLBACK*) pChannelCallback; s = stream_new(32); stream_write_uint32(s, TSMF_INTERFACE_CLIENT_NOTIFICATIONS | STREAM_ID_PROXY); stream_write_uint32(s, message_id); stream_write_uint32(s, PLAYBACK_ACK); /* FunctionId */ stream_write_uint32(s, callback->stream_id); /* StreamId */ stream_write_uint64(s, duration); /* DataDuration */ stream_write_uint64(s, data_size); /* cbData */ DEBUG_DVC("response size %d", stream_get_length(s)); error = callback->channel->Write(callback->channel, stream_get_length(s), stream_get_head(s), NULL); if (error) { DEBUG_WARN("response error %d", error); } stream_free(s); } boolean tsmf_push_event(IWTSVirtualChannelCallback* pChannelCallback, RDP_EVENT* event) { int error; TSMF_CHANNEL_CALLBACK* callback = (TSMF_CHANNEL_CALLBACK*) pChannelCallback; error = callback->channel_mgr->PushEvent(callback->channel_mgr, event); if (error) { DEBUG_WARN("response error %d", error); return false; } return true; } static int tsmf_on_data_received(IWTSVirtualChannelCallback* pChannelCallback, uint32 cbSize, uint8* pBuffer) { int length; STREAM* input; STREAM* output; int error = -1; TSMF_IFMAN ifman; uint32 MessageId; uint32 FunctionId; uint32 InterfaceId; TSMF_CHANNEL_CALLBACK* callback = (TSMF_CHANNEL_CALLBACK*) pChannelCallback; /* 2.2.1 Shared Message Header (SHARED_MSG_HEADER) */ if (cbSize < 12) { DEBUG_WARN("invalid size. cbSize=%d", cbSize); return 1; } input = stream_new(0); stream_attach(input, (uint8*) pBuffer, cbSize); output = stream_new(256); stream_seek(output, 8); stream_read_uint32(input, InterfaceId); stream_read_uint32(input, MessageId); stream_read_uint32(input, FunctionId); DEBUG_DVC("cbSize=%d InterfaceId=0x%X MessageId=0x%X FunctionId=0x%X", cbSize, InterfaceId, MessageId, FunctionId); memset(&ifman, 0, sizeof(TSMF_IFMAN)); ifman.channel_callback = pChannelCallback; ifman.decoder_name = ((TSMF_PLUGIN*) callback->plugin)->decoder_name; ifman.audio_name = ((TSMF_PLUGIN*) callback->plugin)->audio_name; ifman.audio_device = ((TSMF_PLUGIN*) callback->plugin)->audio_device; memcpy(ifman.presentation_id, callback->presentation_id, 16); ifman.stream_id = callback->stream_id; ifman.message_id = MessageId; ifman.input = input; ifman.input_size = cbSize - 12; ifman.output = output; ifman.output_pending = false; ifman.output_interface_id = InterfaceId; switch (InterfaceId) { case TSMF_INTERFACE_CAPABILITIES | STREAM_ID_NONE: switch (FunctionId) { case RIM_EXCHANGE_CAPABILITY_REQUEST: error = tsmf_ifman_rim_exchange_capability_request(&ifman); break; default: break; } break; case TSMF_INTERFACE_DEFAULT | STREAM_ID_PROXY: switch (FunctionId) { case SET_CHANNEL_PARAMS: memcpy(callback->presentation_id, stream_get_tail(input), 16); stream_seek(input, 16); stream_read_uint32(input, callback->stream_id); DEBUG_DVC("SET_CHANNEL_PARAMS StreamId=%d", callback->stream_id); ifman.output_pending = true; error = 0; break; case EXCHANGE_CAPABILITIES_REQ: error = tsmf_ifman_exchange_capability_request(&ifman); break; case CHECK_FORMAT_SUPPORT_REQ: error = tsmf_ifman_check_format_support_request(&ifman); break; case ON_NEW_PRESENTATION: error = tsmf_ifman_on_new_presentation(&ifman); break; case ADD_STREAM: error = tsmf_ifman_add_stream(&ifman); break; case SET_TOPOLOGY_REQ: error = tsmf_ifman_set_topology_request(&ifman); break; case REMOVE_STREAM: error = tsmf_ifman_remove_stream(&ifman); break; case SHUTDOWN_PRESENTATION_REQ: error = tsmf_ifman_shutdown_presentation(&ifman); break; case ON_STREAM_VOLUME: error = tsmf_ifman_on_stream_volume(&ifman); break; case ON_CHANNEL_VOLUME: error = tsmf_ifman_on_channel_volume(&ifman); break; case SET_VIDEO_WINDOW: error = tsmf_ifman_set_video_window(&ifman); break; case UPDATE_GEOMETRY_INFO: error = tsmf_ifman_update_geometry_info(&ifman); break; case SET_ALLOCATOR: error = tsmf_ifman_set_allocator(&ifman); break; case NOTIFY_PREROLL: error = tsmf_ifman_notify_preroll(&ifman); break; case ON_SAMPLE: error = tsmf_ifman_on_sample(&ifman); break; case ON_FLUSH: error = tsmf_ifman_on_flush(&ifman); break; case ON_END_OF_STREAM: error = tsmf_ifman_on_end_of_stream(&ifman); break; case ON_PLAYBACK_STARTED: error = tsmf_ifman_on_playback_started(&ifman); break; case ON_PLAYBACK_PAUSED: error = tsmf_ifman_on_playback_paused(&ifman); break; case ON_PLAYBACK_RESTARTED: error = tsmf_ifman_on_playback_restarted(&ifman); break; case ON_PLAYBACK_STOPPED: error = tsmf_ifman_on_playback_stopped(&ifman); break; case ON_PLAYBACK_RATE_CHANGED: error = tsmf_ifman_on_playback_rate_changed(&ifman); break; default: break; } break; default: break; } stream_detach(input); stream_free(input); input = NULL; ifman.input = NULL; if (error == -1) { switch (FunctionId) { case RIMCALL_RELEASE: /* [MS-RDPEXPS] 2.2.2.2 Interface Release (IFACE_RELEASE) This message does not require a reply. */ error = 0; ifman.output_pending = 1; break; case RIMCALL_QUERYINTERFACE: /* [MS-RDPEXPS] 2.2.2.1.2 Query Interface Response (QI_RSP) This message is not supported in this channel. */ error = 0; break; } if (error == -1) { DEBUG_WARN("InterfaceId 0x%X FunctionId 0x%X not processed.", InterfaceId, FunctionId); /* When a request is not implemented we return empty response indicating error */ } error = 0; } if (error == 0 && !ifman.output_pending) { /* Response packet does not have FunctionId */ length = stream_get_length(output); stream_set_pos(output, 0); stream_write_uint32(output, ifman.output_interface_id); stream_write_uint32(output, MessageId); DEBUG_DVC("response size %d", length); error = callback->channel->Write(callback->channel, length, stream_get_head(output), NULL); if (error) { DEBUG_WARN("response error %d", error); } } stream_free(output); return error; } static int tsmf_on_close(IWTSVirtualChannelCallback* pChannelCallback) { TSMF_STREAM* stream; TSMF_PRESENTATION* presentation; TSMF_CHANNEL_CALLBACK* callback = (TSMF_CHANNEL_CALLBACK*) pChannelCallback; DEBUG_DVC(""); if (callback->stream_id) { presentation = tsmf_presentation_find_by_id(callback->presentation_id); if (presentation) { stream = tsmf_stream_find_by_id(presentation, callback->stream_id); if (stream) tsmf_stream_free(stream); } } xfree(pChannelCallback); return 0; } static int tsmf_on_new_channel_connection(IWTSListenerCallback* pListenerCallback, IWTSVirtualChannel* pChannel, uint8* Data, int* pbAccept, IWTSVirtualChannelCallback** ppCallback) { TSMF_CHANNEL_CALLBACK* callback; TSMF_LISTENER_CALLBACK* listener_callback = (TSMF_LISTENER_CALLBACK*) pListenerCallback; DEBUG_DVC(""); callback = xnew(TSMF_CHANNEL_CALLBACK); callback->iface.OnDataReceived = tsmf_on_data_received; callback->iface.OnClose = tsmf_on_close; callback->plugin = listener_callback->plugin; callback->channel_mgr = listener_callback->channel_mgr; callback->channel = pChannel; *ppCallback = (IWTSVirtualChannelCallback*) callback; return 0; } static int tsmf_plugin_initialize(IWTSPlugin* pPlugin, IWTSVirtualChannelManager* pChannelMgr) { TSMF_PLUGIN* tsmf = (TSMF_PLUGIN*) pPlugin; DEBUG_DVC(""); tsmf->listener_callback = xnew(TSMF_LISTENER_CALLBACK); tsmf->listener_callback->iface.OnNewChannelConnection = tsmf_on_new_channel_connection; tsmf->listener_callback->plugin = pPlugin; tsmf->listener_callback->channel_mgr = pChannelMgr; return pChannelMgr->CreateListener(pChannelMgr, "TSMF", 0, (IWTSListenerCallback*) tsmf->listener_callback, NULL); } static int tsmf_plugin_terminated(IWTSPlugin* pPlugin) { TSMF_PLUGIN* tsmf = (TSMF_PLUGIN*) pPlugin; DEBUG_DVC(""); if (tsmf->listener_callback) xfree(tsmf->listener_callback); xfree(tsmf); return 0; } static void tsmf_process_plugin_data(IWTSPlugin* pPlugin, RDP_PLUGIN_DATA* data) { TSMF_PLUGIN* tsmf = (TSMF_PLUGIN*) pPlugin; while (data && data->size > 0) { if (data->data[0] && ( strcmp((char*)data->data[0], "tsmf") == 0 || strstr((char*)data->data[0], "/tsmf.") != NULL) ) { if (data->data[1] && strcmp((char*)data->data[1], "decoder") == 0) { tsmf->decoder_name = data->data[2]; } else if (data->data[1] && strcmp((char*)data->data[1], "audio") == 0) { tsmf->audio_name = data->data[2]; tsmf->audio_device = data->data[3]; } } data = (RDP_PLUGIN_DATA*)(((void*)data) + data->size); } } int DVCPluginEntry(IDRDYNVC_ENTRY_POINTS* pEntryPoints) { TSMF_PLUGIN * tsmf; int error = 0; tsmf = (TSMF_PLUGIN*) pEntryPoints->GetPlugin(pEntryPoints, "tsmf"); if (tsmf == NULL) { tsmf = xnew(TSMF_PLUGIN); tsmf->iface.Initialize = tsmf_plugin_initialize; tsmf->iface.Connected = NULL; tsmf->iface.Disconnected = NULL; tsmf->iface.Terminated = tsmf_plugin_terminated; error = pEntryPoints->RegisterPlugin(pEntryPoints, "tsmf", (IWTSPlugin*) tsmf); tsmf_media_init(); } if (error == 0) { tsmf_process_plugin_data((IWTSPlugin*) tsmf, pEntryPoints->GetPluginData(pEntryPoints)); } return error; } FreeRDP-1.0.2/channels/drdynvc/tsmf/tsmf_main.h000066400000000000000000000016711207112532300213050ustar00rootroot00000000000000/** * FreeRDP: A Remote Desktop Protocol client. * Video Redirection Virtual Channel * * Copyright 2010-2011 Vic Lee * * 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. */ #ifndef __TSMF_MAIN_H #define __TSMF_MAIN_H void tsmf_playback_ack(IWTSVirtualChannelCallback* pChannelCallback, uint32 message_id, uint64 duration, uint32 data_size); boolean tsmf_push_event(IWTSVirtualChannelCallback* pChannelCallback, RDP_EVENT* event); #endif FreeRDP-1.0.2/channels/drdynvc/tsmf/tsmf_media.c000066400000000000000000000503151207112532300214320ustar00rootroot00000000000000/** * FreeRDP: A Remote Desktop Protocol client. * Video Redirection Virtual Channel - Media Container * * Copyright 2010-2011 Vic Lee * * 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. */ #include #include #include #include #include #include #include #include #include #include #include #include #include "drdynvc_types.h" #include "tsmf_constants.h" #include "tsmf_types.h" #include "tsmf_decoder.h" #include "tsmf_audio.h" #include "tsmf_main.h" #include "tsmf_codec.h" #include "tsmf_media.h" #define AUDIO_TOLERANCE 10000000LL struct _TSMF_PRESENTATION { uint8 presentation_id[GUID_SIZE]; const char* audio_name; const char* audio_device; int eos; uint32 last_x; uint32 last_y; uint32 last_width; uint32 last_height; uint16 last_num_rects; RDP_RECT* last_rects; uint32 output_x; uint32 output_y; uint32 output_width; uint32 output_height; uint16 output_num_rects; RDP_RECT* output_rects; IWTSVirtualChannelCallback* channel_callback; uint64 audio_start_time; uint64 audio_end_time; /* The stream list could be accessed by differnt threads and need to be protected. */ freerdp_mutex mutex; LIST* stream_list; }; struct _TSMF_STREAM { uint32 stream_id; TSMF_PRESENTATION* presentation; ITSMFDecoder* decoder; int major_type; int eos; uint32 width; uint32 height; ITSMFAudioDevice* audio; uint32 sample_rate; uint32 channels; uint32 bits_per_sample; /* The end_time of last played sample */ uint64 last_end_time; /* Next sample should not start before this system time. */ uint64 next_start_time; freerdp_thread* thread; LIST* sample_list; /* The sample ack response queue will be accessed only by the stream thread. */ LIST* sample_ack_list; }; struct _TSMF_SAMPLE { uint32 sample_id; uint64 start_time; uint64 end_time; uint64 duration; uint32 extensions; uint32 data_size; uint8* data; uint32 decoded_size; uint32 pixfmt; TSMF_STREAM* stream; IWTSVirtualChannelCallback* channel_callback; uint64 ack_time; }; static LIST* presentation_list = NULL; static uint64 get_current_time(void) { struct timeval tp; gettimeofday(&tp, 0); return ((uint64)tp.tv_sec) * 10000000LL + ((uint64)tp.tv_usec) * 10LL; } static TSMF_SAMPLE* tsmf_stream_pop_sample(TSMF_STREAM* stream, int sync) { TSMF_STREAM* s; LIST_ITEM* item; TSMF_SAMPLE* sample; boolean pending = false; TSMF_PRESENTATION* presentation = stream->presentation; if (!stream->sample_list->head) return NULL; if (sync) { if (stream->major_type == TSMF_MAJOR_TYPE_AUDIO) { /* Check if some other stream has earlier sample that needs to be played first */ if (stream->last_end_time > AUDIO_TOLERANCE) { freerdp_mutex_lock(presentation->mutex); for (item = presentation->stream_list->head; item; item = item->next) { s = (TSMF_STREAM*) item->data; if (s != stream && !s->eos && s->last_end_time && s->last_end_time < stream->last_end_time - AUDIO_TOLERANCE) { pending = true; break; } } freerdp_mutex_unlock(presentation->mutex); } } else { if (stream->last_end_time > presentation->audio_end_time) { pending = true; } } } if (pending) return NULL; freerdp_thread_lock(stream->thread); sample = (TSMF_SAMPLE*) list_dequeue(stream->sample_list); freerdp_thread_unlock(stream->thread); if (sample && sample->end_time > stream->last_end_time) stream->last_end_time = sample->end_time; return sample; } static void tsmf_sample_free(TSMF_SAMPLE* sample) { if (sample->data) xfree(sample->data); xfree(sample); } static void tsmf_sample_ack(TSMF_SAMPLE* sample) { tsmf_playback_ack(sample->channel_callback, sample->sample_id, sample->duration, sample->data_size); } static void tsmf_sample_queue_ack(TSMF_SAMPLE* sample) { TSMF_STREAM* stream = sample->stream; list_enqueue(stream->sample_ack_list, sample); } static void tsmf_stream_process_ack(TSMF_STREAM* stream) { TSMF_SAMPLE* sample; uint64 ack_time; ack_time = get_current_time(); while (stream->sample_ack_list->head && !freerdp_thread_is_stopped(stream->thread)) { sample = (TSMF_SAMPLE*) list_peek(stream->sample_ack_list); if (sample->ack_time > ack_time) break; sample = list_dequeue(stream->sample_ack_list); tsmf_sample_ack(sample); tsmf_sample_free(sample); } } TSMF_PRESENTATION* tsmf_presentation_new(const uint8* guid, IWTSVirtualChannelCallback* pChannelCallback) { TSMF_PRESENTATION* presentation; presentation = tsmf_presentation_find_by_id(guid); if (presentation) { DEBUG_WARN("duplicated presentation id!"); return NULL; } presentation = xnew(TSMF_PRESENTATION); memcpy(presentation->presentation_id, guid, GUID_SIZE); presentation->channel_callback = pChannelCallback; presentation->mutex = freerdp_mutex_new(); presentation->stream_list = list_new(); list_enqueue(presentation_list, presentation); return presentation; } TSMF_PRESENTATION* tsmf_presentation_find_by_id(const uint8* guid) { LIST_ITEM* item; TSMF_PRESENTATION* presentation; for (item = presentation_list->head; item; item = item->next) { presentation = (TSMF_PRESENTATION*) item->data; if (memcmp(presentation->presentation_id, guid, GUID_SIZE) == 0) return presentation; } return NULL; } static void tsmf_presentation_restore_last_video_frame(TSMF_PRESENTATION* presentation) { RDP_REDRAW_EVENT* revent; if (presentation->last_width && presentation->last_height) { revent = (RDP_REDRAW_EVENT*) freerdp_event_new(RDP_EVENT_CLASS_TSMF, RDP_EVENT_TYPE_TSMF_REDRAW, NULL, NULL); revent->x = presentation->last_x; revent->y = presentation->last_y; revent->width = presentation->last_width; revent->height = presentation->last_height; if (!tsmf_push_event(presentation->channel_callback, (RDP_EVENT*) revent)) { freerdp_event_free((RDP_EVENT*) revent); } presentation->last_x = 0; presentation->last_y = 0; presentation->last_width = 0; presentation->last_height = 0; } } static void tsmf_sample_playback_video(TSMF_SAMPLE* sample) { uint64 t; RDP_VIDEO_FRAME_EVENT* vevent; TSMF_STREAM* stream = sample->stream; TSMF_PRESENTATION* presentation = stream->presentation; DEBUG_DVC("MessageId %d EndTime %d data_size %d consumed.", sample->sample_id, (int)sample->end_time, sample->data_size); if (sample->data) { t = get_current_time(); if (stream->next_start_time > t && (sample->end_time >= presentation->audio_start_time || sample->end_time < stream->last_end_time)) { freerdp_usleep((stream->next_start_time - t) / 10); } stream->next_start_time = t + sample->duration - 50000; if (presentation->last_x != presentation->output_x || presentation->last_y != presentation->output_y || presentation->last_width != presentation->output_width || presentation->last_height != presentation->output_height || presentation->last_num_rects != presentation->output_num_rects || (presentation->last_rects && presentation->output_rects && memcmp(presentation->last_rects, presentation->output_rects, presentation->last_num_rects * sizeof(RDP_RECT)) != 0)) { tsmf_presentation_restore_last_video_frame(presentation); presentation->last_x = presentation->output_x; presentation->last_y = presentation->output_y; presentation->last_width = presentation->output_width; presentation->last_height = presentation->output_height; if (presentation->last_rects) { xfree(presentation->last_rects); presentation->last_rects = NULL; } presentation->last_num_rects = presentation->output_num_rects; if (presentation->last_num_rects > 0) { presentation->last_rects = xzalloc(presentation->last_num_rects * sizeof(RDP_RECT)); memcpy(presentation->last_rects, presentation->output_rects, presentation->last_num_rects * sizeof(RDP_RECT)); } } vevent = (RDP_VIDEO_FRAME_EVENT*) freerdp_event_new(RDP_EVENT_CLASS_TSMF, RDP_EVENT_TYPE_TSMF_VIDEO_FRAME, NULL, NULL); vevent->frame_data = sample->data; vevent->frame_size = sample->decoded_size; vevent->frame_pixfmt = sample->pixfmt; vevent->frame_width = sample->stream->width; vevent->frame_height = sample->stream->height; vevent->x = presentation->output_x; vevent->y = presentation->output_y; vevent->width = presentation->output_width; vevent->height = presentation->output_height; if (presentation->output_num_rects > 0) { vevent->num_visible_rects = presentation->output_num_rects; vevent->visible_rects = (RDP_RECT*) xzalloc(presentation->output_num_rects * sizeof(RDP_RECT)); memcpy(vevent->visible_rects, presentation->output_rects, presentation->output_num_rects * sizeof(RDP_RECT)); } /* The frame data ownership is passed to the event object, and is freed after the event is processed. */ sample->data = NULL; sample->decoded_size = 0; if (!tsmf_push_event(sample->channel_callback, (RDP_EVENT*) vevent)) { freerdp_event_free((RDP_EVENT*) vevent); } #if 0 /* Dump a .ppm image for every 30 frames. Assuming the frame is in YUV format, we extract the Y values to create a grayscale image. */ static int frame_id = 0; char buf[100]; FILE * fp; if ((frame_id % 30) == 0) { snprintf(buf, sizeof(buf), "/tmp/FreeRDP_Frame_%d.ppm", frame_id); fp = fopen(buf, "wb"); fwrite("P5\n", 1, 3, fp); snprintf(buf, sizeof(buf), "%d %d\n", sample->stream->width, sample->stream->height); fwrite(buf, 1, strlen(buf), fp); fwrite("255\n", 1, 4, fp); fwrite(sample->data, 1, sample->stream->width * sample->stream->height, fp); fflush(fp); fclose(fp); } frame_id++; #endif } } static void tsmf_sample_playback_audio(TSMF_SAMPLE* sample) { uint64 latency = 0; TSMF_STREAM* stream = sample->stream; DEBUG_DVC("MessageId %d EndTime %d consumed.", sample->sample_id, (int)sample->end_time); if (sample->stream->audio && sample->data) { sample->stream->audio->Play(sample->stream->audio, sample->data, sample->decoded_size); sample->data = NULL; sample->decoded_size = 0; if (stream->audio && stream->audio->GetLatency) latency = stream->audio->GetLatency(stream->audio); } else { latency = 0; } sample->ack_time = latency + get_current_time(); stream->last_end_time = sample->end_time + latency; stream->presentation->audio_start_time = sample->start_time + latency; stream->presentation->audio_end_time = sample->end_time + latency; } static void tsmf_sample_playback(TSMF_SAMPLE* sample) { boolean ret = false; uint32 width; uint32 height; uint32 pixfmt = 0; TSMF_STREAM* stream = sample->stream; if (stream->decoder) ret = stream->decoder->Decode(stream->decoder, sample->data, sample->data_size, sample->extensions); if (!ret) { tsmf_sample_ack(sample); tsmf_sample_free(sample); return; } xfree(sample->data); sample->data = NULL; if (stream->major_type == TSMF_MAJOR_TYPE_VIDEO) { if (stream->decoder->GetDecodedFormat) { pixfmt = stream->decoder->GetDecodedFormat(stream->decoder); if (pixfmt == ((uint32) -1)) { tsmf_sample_ack(sample); tsmf_sample_free(sample); return; } sample->pixfmt = pixfmt; } if (stream->decoder->GetDecodedDimension) ret = stream->decoder->GetDecodedDimension(stream->decoder, &width, &height); if (ret && (width != stream->width || height != stream->height)) { DEBUG_DVC("video dimension changed to %d x %d", width, height); stream->width = width; stream->height = height; } } if (stream->decoder->GetDecodedData) { sample->data = stream->decoder->GetDecodedData(stream->decoder, &sample->decoded_size); } switch (sample->stream->major_type) { case TSMF_MAJOR_TYPE_VIDEO: tsmf_sample_playback_video(sample); tsmf_sample_ack(sample); tsmf_sample_free(sample); break; case TSMF_MAJOR_TYPE_AUDIO: tsmf_sample_playback_audio(sample); tsmf_sample_queue_ack(sample); break; } } static void* tsmf_stream_playback_func(void* arg) { TSMF_SAMPLE* sample; TSMF_STREAM* stream = (TSMF_STREAM*) arg; TSMF_PRESENTATION* presentation = stream->presentation; DEBUG_DVC("in %d", stream->stream_id); if (stream->major_type == TSMF_MAJOR_TYPE_AUDIO && stream->sample_rate && stream->channels && stream->bits_per_sample) { stream->audio = tsmf_load_audio_device( presentation->audio_name && presentation->audio_name[0] ? presentation->audio_name : NULL, presentation->audio_device && presentation->audio_device[0] ? presentation->audio_device : NULL); if (stream->audio) { stream->audio->SetFormat(stream->audio, stream->sample_rate, stream->channels, stream->bits_per_sample); } } while (!freerdp_thread_is_stopped(stream->thread)) { tsmf_stream_process_ack(stream); sample = tsmf_stream_pop_sample(stream, 1); if (sample) tsmf_sample_playback(sample); else freerdp_usleep(5000); } if (stream->eos || presentation->eos) { while ((sample = tsmf_stream_pop_sample(stream, 1)) != NULL) tsmf_sample_playback(sample); } if (stream->audio) { stream->audio->Free(stream->audio); stream->audio = NULL; } freerdp_thread_quit(stream->thread); DEBUG_DVC("out %d", stream->stream_id); return NULL; } static void tsmf_stream_start(TSMF_STREAM* stream) { if (!freerdp_thread_is_running(stream->thread)) { freerdp_thread_start(stream->thread, tsmf_stream_playback_func, stream); } } static void tsmf_stream_stop(TSMF_STREAM* stream) { if (freerdp_thread_is_running(stream->thread)) { freerdp_thread_stop(stream->thread); } } void tsmf_presentation_start(TSMF_PRESENTATION* presentation) { LIST_ITEM* item; TSMF_STREAM* stream; for (item = presentation->stream_list->head; item; item = item->next) { stream = (TSMF_STREAM*) item->data; tsmf_stream_start(stream); } } void tsmf_presentation_stop(TSMF_PRESENTATION* presentation) { LIST_ITEM* item; TSMF_STREAM* stream; tsmf_presentation_flush(presentation); for (item = presentation->stream_list->head; item; item = item->next) { stream = (TSMF_STREAM*) item->data; tsmf_stream_stop(stream); } tsmf_presentation_restore_last_video_frame(presentation); if (presentation->last_rects) { xfree(presentation->last_rects); presentation->last_rects = NULL; } presentation->last_num_rects = 0; if (presentation->output_rects) { xfree(presentation->output_rects); presentation->output_rects = NULL; } presentation->output_num_rects = 0; } void tsmf_presentation_set_geometry_info(TSMF_PRESENTATION* presentation, uint32 x, uint32 y, uint32 width, uint32 height, int num_rects, RDP_RECT* rects) { presentation->output_x = x; presentation->output_y = y; presentation->output_width = width; presentation->output_height = height; if (presentation->output_rects) xfree(presentation->output_rects); presentation->output_rects = rects; presentation->output_num_rects = num_rects; } void tsmf_presentation_set_audio_device(TSMF_PRESENTATION* presentation, const char* name, const char* device) { presentation->audio_name = name; presentation->audio_device = device; } static void tsmf_stream_flush(TSMF_STREAM* stream) { TSMF_SAMPLE* sample; while ((sample = tsmf_stream_pop_sample(stream, 0)) != NULL) tsmf_sample_free(sample); while ((sample = list_dequeue(stream->sample_ack_list)) != NULL) tsmf_sample_free(sample); if (stream->audio) stream->audio->Flush(stream->audio); stream->eos = 0; stream->last_end_time = 0; stream->next_start_time = 0; if (stream->major_type == TSMF_MAJOR_TYPE_AUDIO) { stream->presentation->audio_start_time = 0; stream->presentation->audio_end_time = 0; } } void tsmf_presentation_flush(TSMF_PRESENTATION* presentation) { LIST_ITEM* item; TSMF_STREAM * stream; for (item = presentation->stream_list->head; item; item = item->next) { stream = (TSMF_STREAM*) item->data; tsmf_stream_flush(stream); } presentation->eos = 0; presentation->audio_start_time = 0; presentation->audio_end_time = 0; } void tsmf_presentation_free(TSMF_PRESENTATION* presentation) { TSMF_STREAM* stream; tsmf_presentation_stop(presentation); list_remove(presentation_list, presentation); while (presentation->stream_list->head) { stream = (TSMF_STREAM*) list_peek(presentation->stream_list); tsmf_stream_free(stream); } list_free(presentation->stream_list); freerdp_mutex_free(presentation->mutex); xfree(presentation); } TSMF_STREAM* tsmf_stream_new(TSMF_PRESENTATION* presentation, uint32 stream_id) { TSMF_STREAM* stream; stream = tsmf_stream_find_by_id(presentation, stream_id); if (stream) { DEBUG_WARN("duplicated stream id %d!", stream_id); return NULL; } stream = xnew(TSMF_STREAM); stream->stream_id = stream_id; stream->presentation = presentation; stream->thread = freerdp_thread_new(); stream->sample_list = list_new(); stream->sample_ack_list = list_new(); freerdp_mutex_lock(presentation->mutex); list_enqueue(presentation->stream_list, stream); freerdp_mutex_unlock(presentation->mutex); return stream; } TSMF_STREAM* tsmf_stream_find_by_id(TSMF_PRESENTATION* presentation, uint32 stream_id) { LIST_ITEM* item; TSMF_STREAM* stream; for (item = presentation->stream_list->head; item; item = item->next) { stream = (TSMF_STREAM*) item->data; if (stream->stream_id == stream_id) return stream; } return NULL; } void tsmf_stream_set_format(TSMF_STREAM* stream, const char* name, STREAM* s) { TS_AM_MEDIA_TYPE mediatype; if (stream->decoder) { DEBUG_WARN("duplicated call"); return; } tsmf_codec_parse_media_type(&mediatype, s); if (mediatype.MajorType == TSMF_MAJOR_TYPE_VIDEO) { DEBUG_DVC("video width %d height %d bit_rate %d frame_rate %f codec_data %d", mediatype.Width, mediatype.Height, mediatype.BitRate, (double)mediatype.SamplesPerSecond.Numerator / (double)mediatype.SamplesPerSecond.Denominator, mediatype.ExtraDataSize); } else if (mediatype.MajorType == TSMF_MAJOR_TYPE_AUDIO) { DEBUG_DVC("audio channel %d sample_rate %d bits_per_sample %d codec_data %d", mediatype.Channels, mediatype.SamplesPerSecond.Numerator, mediatype.BitsPerSample, mediatype.ExtraDataSize); stream->sample_rate = mediatype.SamplesPerSecond.Numerator; stream->channels = mediatype.Channels; stream->bits_per_sample = mediatype.BitsPerSample; if (stream->bits_per_sample == 0) stream->bits_per_sample = 16; } stream->major_type = mediatype.MajorType; stream->width = mediatype.Width; stream->height = mediatype.Height; stream->decoder = tsmf_load_decoder(name, &mediatype); } void tsmf_stream_end(TSMF_STREAM* stream) { stream->eos = 1; stream->presentation->eos = 1; } void tsmf_stream_free(TSMF_STREAM* stream) { TSMF_PRESENTATION* presentation = stream->presentation; tsmf_stream_stop(stream); tsmf_stream_flush(stream); freerdp_mutex_lock(presentation->mutex); list_remove(presentation->stream_list, stream); freerdp_mutex_unlock(presentation->mutex); list_free(stream->sample_list); list_free(stream->sample_ack_list); if (stream->decoder) stream->decoder->Free(stream->decoder); freerdp_thread_free(stream->thread); xfree(stream); } void tsmf_stream_push_sample(TSMF_STREAM* stream, IWTSVirtualChannelCallback* pChannelCallback, uint32 sample_id, uint64 start_time, uint64 end_time, uint64 duration, uint32 extensions, uint32 data_size, uint8* data) { TSMF_SAMPLE* sample; sample = xnew(TSMF_SAMPLE); sample->sample_id = sample_id; sample->start_time = start_time; sample->end_time = end_time; sample->duration = duration; sample->extensions = extensions; sample->stream = stream; sample->channel_callback = pChannelCallback; sample->data_size = data_size; sample->data = xzalloc(data_size + TSMF_BUFFER_PADDING_SIZE); memcpy(sample->data, data, data_size); freerdp_thread_lock(stream->thread); list_enqueue(stream->sample_list, sample); freerdp_thread_unlock(stream->thread); } void tsmf_media_init(void) { if (presentation_list == NULL) presentation_list = list_new(); } FreeRDP-1.0.2/channels/drdynvc/tsmf/tsmf_media.h000066400000000000000000000043731207112532300214420ustar00rootroot00000000000000/** * FreeRDP: A Remote Desktop Protocol client. * Video Redirection Virtual Channel - Media Container * * Copyright 2010-2011 Vic Lee * * 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. */ /** * The media container maintains a global list of presentations, and a list of * streams in each presentation. */ #ifndef __TSMF_MEDIA_H #define __TSMF_MEDIA_H typedef struct _TSMF_PRESENTATION TSMF_PRESENTATION; typedef struct _TSMF_STREAM TSMF_STREAM; typedef struct _TSMF_SAMPLE TSMF_SAMPLE; TSMF_PRESENTATION* tsmf_presentation_new(const uint8* guid, IWTSVirtualChannelCallback* pChannelCallback); TSMF_PRESENTATION* tsmf_presentation_find_by_id(const uint8* guid); void tsmf_presentation_start(TSMF_PRESENTATION* presentation); void tsmf_presentation_stop(TSMF_PRESENTATION* presentation); void tsmf_presentation_set_geometry_info(TSMF_PRESENTATION* presentation, uint32 x, uint32 y, uint32 width, uint32 height, int num_rects, RDP_RECT* rects); void tsmf_presentation_set_audio_device(TSMF_PRESENTATION* presentation, const char* name, const char* device); void tsmf_presentation_flush(TSMF_PRESENTATION* presentation); void tsmf_presentation_free(TSMF_PRESENTATION* presentation); TSMF_STREAM* tsmf_stream_new(TSMF_PRESENTATION* presentation, uint32 stream_id); TSMF_STREAM* tsmf_stream_find_by_id(TSMF_PRESENTATION* presentation, uint32 stream_id); void tsmf_stream_set_format(TSMF_STREAM* stream, const char* name, STREAM* s); void tsmf_stream_end(TSMF_STREAM* stream); void tsmf_stream_free(TSMF_STREAM* stream); void tsmf_stream_push_sample(TSMF_STREAM* stream, IWTSVirtualChannelCallback* pChannelCallback, uint32 sample_id, uint64 start_time, uint64 end_time, uint64 duration, uint32 extensions, uint32 data_size, uint8* data); void tsmf_media_init(void); #endif FreeRDP-1.0.2/channels/drdynvc/tsmf/tsmf_types.h000066400000000000000000000021271207112532300215220ustar00rootroot00000000000000/** * FreeRDP: A Remote Desktop Protocol client. * Video Redirection Virtual Channel - Types * * Copyright 2010-2011 Vic Lee * * 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. */ #ifndef __TSMF_TYPES_H #define __TSMF_TYPES_H #include typedef struct _TS_AM_MEDIA_TYPE { int MajorType; int SubType; int FormatType; uint32 Width; uint32 Height; uint32 BitRate; struct { uint32 Numerator; uint32 Denominator; } SamplesPerSecond; uint32 Channels; uint32 BitsPerSample; uint32 BlockAlign; const uint8* ExtraData; uint32 ExtraDataSize; } TS_AM_MEDIA_TYPE; #endif FreeRDP-1.0.2/channels/rail/000077500000000000000000000000001207112532300154575ustar00rootroot00000000000000FreeRDP-1.0.2/channels/rail/CMakeLists.txt000066400000000000000000000020241207112532300202150ustar00rootroot00000000000000# FreeRDP: A Remote Desktop Protocol Client # FreeRDP cmake build script # # Copyright 2011 O.S. Systems Software Ltda. # Copyright 2011 Otavio Salvador # Copyright 2011 Marc-Andre Moreau # # 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(RAIL_SRCS rail_main.c rail_main.h rail_orders.c rail_orders.h) add_library(rail ${RAIL_SRCS}) set_target_properties(rail PROPERTIES PREFIX "") target_link_libraries(rail freerdp-utils) install(TARGETS rail DESTINATION ${FREERDP_PLUGIN_PATH}) FreeRDP-1.0.2/channels/rail/rail_main.c000066400000000000000000000162301207112532300175600ustar00rootroot00000000000000/** * FreeRDP: A Remote Desktop Protocol Client * RAIL Virtual Channel Plugin * * Copyright 2011 Marc-Andre Moreau * Copyright 2011 Roman Barabanov * Copyright 2011 Vic Lee * * 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. */ #include #include #include #include #include #include #include #include #include #include "rail_orders.h" #include "rail_main.h" void rail_send_channel_data(void* rail_object, void* data, size_t length) { STREAM* s = NULL; railPlugin* plugin = (railPlugin*) rail_object; s = stream_new(length); stream_write(s, data, length); svc_plugin_send((rdpSvcPlugin*) plugin, s); } static void on_free_rail_channel_event(RDP_EVENT* event) { if (event->event_class == RDP_EVENT_CLASS_RAIL) { rail_free_cloned_order(event->event_type, event->user_data); } } void rail_send_channel_event(void* rail_object, uint16 event_type, void* param) { void * payload = NULL; RDP_EVENT* out_event = NULL; railPlugin* plugin = (railPlugin*) rail_object; payload = rail_clone_order(event_type, param); if (payload != NULL) { out_event = freerdp_event_new(RDP_EVENT_CLASS_RAIL, event_type, on_free_rail_channel_event, payload); svc_plugin_send_event((rdpSvcPlugin*) plugin, out_event); } } static void rail_process_connect(rdpSvcPlugin* plugin) { railPlugin* rail = (railPlugin*) plugin; rail->rail_order = rail_order_new(); rail->rail_order->plugin_data = (RDP_PLUGIN_DATA*)plugin->channel_entry_points.pExtendedData; rail->rail_order->plugin = rail; } static void rail_process_terminate(rdpSvcPlugin* plugin) { } static void rail_process_receive(rdpSvcPlugin* plugin, STREAM* s) { railPlugin* rail = (railPlugin*) plugin; rail_order_recv(rail->rail_order, s); stream_free(s); } static void rail_process_plugin_data(rdpRailOrder* rail_order, RDP_PLUGIN_DATA* data) { char* exeOrFile; exeOrFile = (char*) data->data[0]; if (strlen(exeOrFile) >= 2) { if (strncmp(exeOrFile, "||", 2) != 0) rail_order->exec.flags |= RAIL_EXEC_FLAG_FILE; } rail_string_to_unicode_string(rail_order, (char*) data->data[0], &rail_order->exec.exeOrFile); rail_string_to_unicode_string(rail_order, (char*) data->data[1], &rail_order->exec.workingDir); rail_string_to_unicode_string(rail_order, (char*) data->data[2], &rail_order->exec.arguments); rail_send_client_exec_order(rail_order); } static void rail_recv_set_sysparams_event(rdpRailOrder* rail_order, RDP_EVENT* event) { RDP_PLUGIN_DATA* data; RAIL_SYSPARAM_ORDER* sysparam; /* Send System Parameters */ sysparam = (RAIL_SYSPARAM_ORDER*)event->user_data; memmove(&rail_order->sysparam, sysparam, sizeof(RAIL_SYSPARAM_ORDER)); rail_send_client_sysparams_order(rail_order); /* execute */ rail_order->exec.flags = RAIL_EXEC_FLAG_EXPAND_ARGUMENTS; data = rail_order->plugin_data; while (data && data->size > 0) { rail_process_plugin_data(rail_order, data); data = (RDP_PLUGIN_DATA*)(((void*) data) + data->size); } } static void rail_recv_exec_remote_app_event(rdpRailOrder* rail_order, RDP_EVENT* event) { RDP_PLUGIN_DATA* data = (RDP_PLUGIN_DATA*) event->user_data; rail_process_plugin_data(rail_order, data); } static void rail_recv_activate_event(rdpRailOrder* rail_order, RDP_EVENT* event) { RAIL_ACTIVATE_ORDER* activate = (RAIL_ACTIVATE_ORDER*) event->user_data; memcpy(&rail_order->activate, activate, sizeof(RAIL_ACTIVATE_ORDER)); rail_send_client_activate_order(rail_order); } static void rail_recv_sysmenu_event(rdpRailOrder* rail_order, RDP_EVENT* event) { RAIL_SYSMENU_ORDER* sysmenu = (RAIL_SYSMENU_ORDER*) event->user_data; memcpy(&rail_order->sysmenu, sysmenu, sizeof(RAIL_SYSMENU_ORDER)); rail_send_client_sysmenu_order(rail_order); } static void rail_recv_syscommand_event(rdpRailOrder* rail_order, RDP_EVENT* event) { RAIL_SYSCOMMAND_ORDER* syscommand = (RAIL_SYSCOMMAND_ORDER*) event->user_data; memcpy(&rail_order->syscommand, syscommand, sizeof(RAIL_SYSCOMMAND_ORDER)); rail_send_client_syscommand_order(rail_order); } static void rail_recv_notify_event(rdpRailOrder* rail_order, RDP_EVENT* event) { RAIL_NOTIFY_EVENT_ORDER* notify = (RAIL_NOTIFY_EVENT_ORDER*) event->user_data; memcpy(&rail_order->notify_event, notify, sizeof(RAIL_NOTIFY_EVENT_ORDER)); rail_send_client_notify_event_order(rail_order); } static void rail_recv_window_move_event(rdpRailOrder* rail_order, RDP_EVENT* event) { RAIL_WINDOW_MOVE_ORDER* window_move = (RAIL_WINDOW_MOVE_ORDER*) event->user_data; memcpy(&rail_order->window_move, window_move, sizeof(RAIL_WINDOW_MOVE_ORDER)); rail_send_client_window_move_order(rail_order); } static void rail_recv_app_req_event(rdpRailOrder* rail_order, RDP_EVENT* event) { RAIL_GET_APPID_REQ_ORDER* get_appid_req = (RAIL_GET_APPID_REQ_ORDER*) event->user_data; memcpy(&rail_order->get_appid_req, get_appid_req, sizeof(RAIL_GET_APPID_REQ_ORDER)); rail_send_client_get_appid_req_order(rail_order); } static void rail_recv_langbarinfo_event(rdpRailOrder* rail_order, RDP_EVENT* event) { RAIL_LANGBAR_INFO_ORDER* langbar_info = (RAIL_LANGBAR_INFO_ORDER*) event->user_data; memcpy(&rail_order->langbar_info, langbar_info, sizeof(RAIL_LANGBAR_INFO_ORDER)); rail_send_client_langbar_info_order(rail_order); } static void rail_process_event(rdpSvcPlugin* plugin, RDP_EVENT* event) { railPlugin* rail = NULL; rail = (railPlugin*) plugin; switch (event->event_type) { case RDP_EVENT_TYPE_RAIL_CLIENT_SET_SYSPARAMS: rail_recv_set_sysparams_event(rail->rail_order, event); break; case RDP_EVENT_TYPE_RAIL_CLIENT_EXEC_REMOTE_APP: rail_recv_exec_remote_app_event(rail->rail_order, event); break; case RDP_EVENT_TYPE_RAIL_CLIENT_ACTIVATE: rail_recv_activate_event(rail->rail_order, event); break; case RDP_EVENT_TYPE_RAIL_CLIENT_SYSMENU: rail_recv_sysmenu_event(rail->rail_order, event); break; case RDP_EVENT_TYPE_RAIL_CLIENT_SYSCOMMAND: rail_recv_syscommand_event(rail->rail_order, event); break; case RDP_EVENT_TYPE_RAIL_CLIENT_NOTIFY_EVENT: rail_recv_notify_event(rail->rail_order, event); break; case RDP_EVENT_TYPE_RAIL_CLIENT_WINDOW_MOVE: rail_recv_window_move_event(rail->rail_order, event); break; case RDP_EVENT_TYPE_RAIL_CLIENT_APPID_REQ: rail_recv_app_req_event(rail->rail_order, event); break; case RDP_EVENT_TYPE_RAIL_CLIENT_LANGBARINFO: rail_recv_langbarinfo_event(rail->rail_order, event); break; default: break; } freerdp_event_free(event); } DEFINE_SVC_PLUGIN(rail, "rail", CHANNEL_OPTION_INITIALIZED | CHANNEL_OPTION_ENCRYPT_RDP | CHANNEL_OPTION_COMPRESS_RDP | CHANNEL_OPTION_SHOW_PROTOCOL) FreeRDP-1.0.2/channels/rail/rail_main.h000066400000000000000000000040761207112532300175720ustar00rootroot00000000000000/** * FreeRDP: A Remote Desktop Protocol Client * RAIL Virtual Channel Plugin * * Copyright 2011 Marc-Andre Moreau * Copyright 2011 Roman Barabanov * Copyright 2011 Vic Lee * * 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. */ #ifndef __RAIL_MAIN_H #define __RAIL_MAIN_H #include #include #include #include struct rdp_rail_order { UNICONV* uniconv; RDP_PLUGIN_DATA* plugin_data; void* plugin; RAIL_HANDSHAKE_ORDER handshake; RAIL_CLIENT_STATUS_ORDER client_status; RAIL_EXEC_ORDER exec; RAIL_EXEC_RESULT_ORDER exec_result; RAIL_SYSPARAM_ORDER sysparam; RAIL_ACTIVATE_ORDER activate; RAIL_SYSMENU_ORDER sysmenu; RAIL_SYSCOMMAND_ORDER syscommand; RAIL_NOTIFY_EVENT_ORDER notify_event; RAIL_MINMAXINFO_ORDER minmaxinfo; RAIL_LOCALMOVESIZE_ORDER localmovesize; RAIL_WINDOW_MOVE_ORDER window_move; RAIL_LANGBAR_INFO_ORDER langbar_info; RAIL_GET_APPID_REQ_ORDER get_appid_req; RAIL_GET_APPID_RESP_ORDER get_appid_resp; }; typedef struct rdp_rail_order rdpRailOrder; struct rail_plugin { rdpSvcPlugin plugin; rdpRailOrder* rail_order; }; typedef struct rail_plugin railPlugin; void rail_send_channel_event(void* rail_object, uint16 event_type, void* param); void rail_send_channel_data(void* rail_object, void* data, size_t length); #ifdef WITH_DEBUG_RAIL #define DEBUG_RAIL(fmt, ...) DEBUG_CLASS(RAIL, fmt, ## __VA_ARGS__) #else #define DEBUG_RAIL(fmt, ...) DEBUG_NULL(fmt, ## __VA_ARGS__) #endif #endif /* __RAIL_MAIN_H */ FreeRDP-1.0.2/channels/rail/rail_orders.c000066400000000000000000000463451207112532300201440ustar00rootroot00000000000000/** * FreeRDP: A Remote Desktop Protocol client. * Remote Applications Integrated Locally (RAIL) Orders * * Copyright 2009 Marc-Andre Moreau * Copyright 2011 Roman Barabanov * * 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. */ #include #include #include "rail_orders.h" #define RAIL_ORDER_TYPE_EXEC 0x0001 #define RAIL_ORDER_TYPE_ACTIVATE 0x0002 #define RAIL_ORDER_TYPE_SYSPARAM 0x0003 #define RAIL_ORDER_TYPE_SYSCOMMAND 0x0004 #define RAIL_ORDER_TYPE_HANDSHAKE 0x0005 #define RAIL_ORDER_TYPE_NOTIFY_EVENT 0x0006 #define RAIL_ORDER_TYPE_WINDOW_MOVE 0x0008 #define RAIL_ORDER_TYPE_LOCALMOVESIZE 0x0009 #define RAIL_ORDER_TYPE_MINMAXINFO 0x000A #define RAIL_ORDER_TYPE_CLIENT_STATUS 0x000B #define RAIL_ORDER_TYPE_SYSMENU 0x000C #define RAIL_ORDER_TYPE_LANGBAR_INFO 0x000D #define RAIL_ORDER_TYPE_EXEC_RESULT 0x0080 #define RAIL_ORDER_TYPE_GET_APPID_REQ 0x000E #define RAIL_ORDER_TYPE_GET_APPID_RESP 0x000F static const char* const RAIL_ORDER_TYPE_STRINGS[] = { "", "Execute", "Activate", "System Parameters Update", "System Command", "Handshake", "Notify Event", "", "Window Move", "Local Move/Size", "Min Max Info", "Client Status", "System Menu", "Language Bar Info", "Get Application ID Request", "Get Application ID Response", "Execute Result" }; void rail_string_to_unicode_string(rdpRailOrder* rail_order, char* string, UNICODE_STRING* unicode_string) { char* buffer; size_t length = 0; if (unicode_string->string != NULL) xfree(unicode_string->string); unicode_string->string = NULL; unicode_string->length = 0; if (string == NULL || strlen(string) < 1) return; buffer = freerdp_uniconv_out(rail_order->uniconv, string, &length); unicode_string->string = (uint8*) buffer; unicode_string->length = (uint16) length; } void rail_read_pdu_header(STREAM* s, uint16* orderType, uint16* orderLength) { stream_read_uint16(s, *orderType); /* orderType (2 bytes) */ stream_read_uint16(s, *orderLength); /* orderLength (2 bytes) */ } void rail_write_pdu_header(STREAM* s, uint16 orderType, uint16 orderLength) { stream_write_uint16(s, orderType); /* orderType (2 bytes) */ stream_write_uint16(s, orderLength); /* orderLength (2 bytes) */ } STREAM* rail_pdu_init(int length) { STREAM* s; s = stream_new(length + RAIL_PDU_HEADER_LENGTH); stream_seek(s, RAIL_PDU_HEADER_LENGTH); return s; } void rail_send_pdu(rdpRailOrder* rail_order, STREAM* s, uint16 orderType) { uint16 orderLength; orderLength = stream_get_length(s); stream_set_pos(s, 0); rail_write_pdu_header(s, orderType, orderLength); stream_set_pos(s, orderLength); /* send */ DEBUG_RAIL("Sending %s PDU, length:%d", RAIL_ORDER_TYPE_STRINGS[((orderType & 0xF0) >> 3) + (orderType & 0x0F)], orderLength); rail_send_channel_data(rail_order->plugin, s->data, orderLength); } void rail_write_high_contrast(STREAM* s, HIGH_CONTRAST* high_contrast) { high_contrast->colorSchemeLength = high_contrast->colorScheme.length + 2; stream_write_uint32(s, high_contrast->flags); /* flags (4 bytes) */ stream_write_uint32(s, high_contrast->colorSchemeLength); /* colorSchemeLength (4 bytes) */ rail_write_unicode_string(s, &high_contrast->colorScheme); /* colorScheme */ } void rail_read_handshake_order(STREAM* s, RAIL_HANDSHAKE_ORDER* handshake) { stream_read_uint32(s, handshake->buildNumber); /* buildNumber (4 bytes) */ } void rail_read_server_exec_result_order(STREAM* s, RAIL_EXEC_RESULT_ORDER* exec_result) { stream_read_uint16(s, exec_result->flags); /* flags (2 bytes) */ stream_read_uint16(s, exec_result->execResult); /* execResult (2 bytes) */ stream_read_uint32(s, exec_result->rawResult); /* rawResult (4 bytes) */ stream_seek_uint16(s); /* padding (2 bytes) */ rail_read_unicode_string(s, &exec_result->exeOrFile); /* exeOrFile */ } void rail_read_server_sysparam_order(STREAM* s, RAIL_SYSPARAM_ORDER* sysparam) { uint8 body; stream_read_uint32(s, sysparam->param); /* systemParam (4 bytes) */ stream_read_uint8(s, body); /* body (1 byte) */ switch (sysparam->param) { case SPI_SET_SCREEN_SAVE_ACTIVE: sysparam->setScreenSaveActive = (body != 0) ? true : false; break; case SPI_SET_SCREEN_SAVE_SECURE: sysparam->setScreenSaveSecure = (body != 0) ? true : false; break; default: break; } } void rail_read_server_minmaxinfo_order(STREAM* s, RAIL_MINMAXINFO_ORDER* minmaxinfo) { stream_read_uint32(s, minmaxinfo->windowId); /* windowId (4 bytes) */ stream_read_uint16(s, minmaxinfo->maxWidth); /* maxWidth (2 bytes) */ stream_read_uint16(s, minmaxinfo->maxHeight); /* maxHeight (2 bytes) */ stream_read_uint16(s, minmaxinfo->maxPosX); /* maxPosX (2 bytes) */ stream_read_uint16(s, minmaxinfo->maxPosY); /* maxPosY (2 bytes) */ stream_read_uint16(s, minmaxinfo->minTrackWidth); /* minTrackWidth (2 bytes) */ stream_read_uint16(s, minmaxinfo->minTrackHeight); /* minTrackHeight (2 bytes) */ stream_read_uint16(s, minmaxinfo->maxTrackWidth); /* maxTrackWidth (2 bytes) */ stream_read_uint16(s, minmaxinfo->maxTrackHeight); /* maxTrackHeight (2 bytes) */ } void rail_read_server_localmovesize_order(STREAM* s, RAIL_LOCALMOVESIZE_ORDER* localmovesize) { uint16 isMoveSizeStart; stream_read_uint32(s, localmovesize->windowId); /* windowId (4 bytes) */ stream_read_uint16(s, isMoveSizeStart); /* isMoveSizeStart (2 bytes) */ localmovesize->isMoveSizeStart = (isMoveSizeStart != 0) ? true : false; stream_read_uint16(s, localmovesize->moveSizeType); /* moveSizeType (2 bytes) */ stream_read_uint16(s, localmovesize->posX); /* posX (2 bytes) */ stream_read_uint16(s, localmovesize->posY); /* posY (2 bytes) */ } void rail_read_server_get_appid_resp_order(STREAM* s, RAIL_GET_APPID_RESP_ORDER* get_appid_resp) { stream_read_uint32(s, get_appid_resp->windowId); /* windowId (4 bytes) */ stream_read(s, &get_appid_resp->applicationIdBuffer[0], 512); /* applicationId (256 UNICODE chars) */ get_appid_resp->applicationId.length = 512; get_appid_resp->applicationId.string = &get_appid_resp->applicationIdBuffer[0]; } void rail_read_langbar_info_order(STREAM* s, RAIL_LANGBAR_INFO_ORDER* langbar_info) { stream_read_uint32(s, langbar_info->languageBarStatus); /* languageBarStatus (4 bytes) */ } void rail_write_handshake_order(STREAM* s, RAIL_HANDSHAKE_ORDER* handshake) { stream_write_uint32(s, handshake->buildNumber); /* buildNumber (4 bytes) */ } void rail_write_client_status_order(STREAM* s, RAIL_CLIENT_STATUS_ORDER* client_status) { stream_write_uint32(s, client_status->flags); /* flags (4 bytes) */ } void rail_write_client_exec_order(STREAM* s, RAIL_EXEC_ORDER* exec) { stream_write_uint16(s, exec->flags); /* flags (2 bytes) */ stream_write_uint16(s, exec->exeOrFile.length); /* exeOrFileLength (2 bytes) */ stream_write_uint16(s, exec->workingDir.length); /* workingDirLength (2 bytes) */ stream_write_uint16(s, exec->arguments.length); /* argumentsLength (2 bytes) */ rail_write_unicode_string_value(s, &exec->exeOrFile); /* exeOrFile */ rail_write_unicode_string_value(s, &exec->workingDir); /* workingDir */ rail_write_unicode_string_value(s, &exec->arguments); /* arguments */ } void rail_write_client_sysparam_order(STREAM* s, RAIL_SYSPARAM_ORDER* sysparam) { uint8 body; stream_write_uint32(s, sysparam->param); /* systemParam (4 bytes) */ switch (sysparam->param) { case SPI_SET_DRAG_FULL_WINDOWS: body = sysparam->dragFullWindows; stream_write_uint8(s, body); break; case SPI_SET_KEYBOARD_CUES: body = sysparam->keyboardCues; stream_write_uint8(s, body); break; case SPI_SET_KEYBOARD_PREF: body = sysparam->keyboardPref; stream_write_uint8(s, body); break; case SPI_SET_MOUSE_BUTTON_SWAP: body = sysparam->mouseButtonSwap; stream_write_uint8(s, body); break; case SPI_SET_WORK_AREA: freerdp_write_rectangle_16(s, &sysparam->workArea); break; case SPI_DISPLAY_CHANGE: freerdp_write_rectangle_16(s, &sysparam->displayChange); break; case SPI_TASKBAR_POS: freerdp_write_rectangle_16(s, &sysparam->taskbarPos); break; case SPI_SET_HIGH_CONTRAST: rail_write_high_contrast(s, &sysparam->highContrast); break; } } void rail_write_client_activate_order(STREAM* s, RAIL_ACTIVATE_ORDER* activate) { uint8 enabled; stream_write_uint32(s, activate->windowId); /* windowId (4 bytes) */ enabled = activate->enabled; stream_write_uint8(s, enabled); /* enabled (1 byte) */ } void rail_write_client_sysmenu_order(STREAM* s, RAIL_SYSMENU_ORDER* sysmenu) { stream_write_uint32(s, sysmenu->windowId); /* windowId (4 bytes) */ stream_write_uint16(s, sysmenu->left); /* left (2 bytes) */ stream_write_uint16(s, sysmenu->top); /* top (2 bytes) */ } void rail_write_client_syscommand_order(STREAM* s, RAIL_SYSCOMMAND_ORDER* syscommand) { stream_write_uint32(s, syscommand->windowId); /* windowId (4 bytes) */ stream_write_uint16(s, syscommand->command); /* command (2 bytes) */ } void rail_write_client_notify_event_order(STREAM* s, RAIL_NOTIFY_EVENT_ORDER* notify_event) { stream_write_uint32(s, notify_event->windowId); /* windowId (4 bytes) */ stream_write_uint32(s, notify_event->notifyIconId); /* notifyIconId (4 bytes) */ stream_write_uint32(s, notify_event->message); /* notifyIconId (4 bytes) */ } void rail_write_client_window_move_order(STREAM* s, RAIL_WINDOW_MOVE_ORDER* window_move) { stream_write_uint32(s, window_move->windowId); /* windowId (4 bytes) */ stream_write_uint16(s, window_move->left); /* left (2 bytes) */ stream_write_uint16(s, window_move->top); /* top (2 bytes) */ stream_write_uint16(s, window_move->right); /* right (2 bytes) */ stream_write_uint16(s, window_move->bottom); /* bottom (2 bytes) */ } void rail_write_client_get_appid_req_order(STREAM* s, RAIL_GET_APPID_REQ_ORDER* get_appid_req) { stream_write_uint32(s, get_appid_req->windowId); /* windowId (4 bytes) */ } void rail_write_langbar_info_order(STREAM* s, RAIL_LANGBAR_INFO_ORDER* langbar_info) { stream_write_uint32(s, langbar_info->languageBarStatus); /* languageBarStatus (4 bytes) */ } void rail_recv_handshake_order(rdpRailOrder* rail_order, STREAM* s) { rail_read_handshake_order(s, &rail_order->handshake); rail_order->handshake.buildNumber = 0x00001DB0; rail_send_handshake_order(rail_order); rail_order->client_status.flags = RAIL_CLIENTSTATUS_ALLOWLOCALMOVESIZE; rail_send_client_status_order(rail_order); /* sysparam update */ rail_order->sysparam.params = 0; rail_order->sysparam.params |= SPI_MASK_SET_HIGH_CONTRAST; rail_order->sysparam.highContrast.colorScheme.string = NULL; rail_order->sysparam.highContrast.colorScheme.length = 0; rail_order->sysparam.highContrast.flags = 0x7E; rail_order->sysparam.params |= SPI_MASK_SET_MOUSE_BUTTON_SWAP; rail_order->sysparam.mouseButtonSwap = false; rail_order->sysparam.params |= SPI_MASK_SET_KEYBOARD_PREF; rail_order->sysparam.keyboardPref = false; rail_order->sysparam.params |= SPI_MASK_SET_DRAG_FULL_WINDOWS; rail_order->sysparam.dragFullWindows = false; rail_order->sysparam.params |= SPI_MASK_SET_KEYBOARD_CUES; rail_order->sysparam.keyboardCues = false; rail_order->sysparam.params |= SPI_MASK_SET_WORK_AREA; rail_order->sysparam.workArea.left = 0; rail_order->sysparam.workArea.top = 0; rail_order->sysparam.workArea.right = 1024; rail_order->sysparam.workArea.bottom = 768; rail_send_channel_event(rail_order->plugin, RDP_EVENT_TYPE_RAIL_CHANNEL_GET_SYSPARAMS, &rail_order->sysparam); } void rail_recv_exec_result_order(rdpRailOrder* rail_order, STREAM* s) { rail_read_server_exec_result_order(s, &rail_order->exec_result); rail_send_channel_event(rail_order->plugin, RDP_EVENT_TYPE_RAIL_CHANNEL_EXEC_RESULTS, &rail_order->exec_result); } void rail_recv_server_sysparam_order(rdpRailOrder* rail_order, STREAM* s) { rail_read_server_sysparam_order(s, &rail_order->sysparam); rail_send_channel_event(rail_order->plugin, RDP_EVENT_TYPE_RAIL_CHANNEL_SERVER_SYSPARAM, &rail_order->sysparam); } void rail_recv_server_minmaxinfo_order(rdpRailOrder* rail_order, STREAM* s) { rail_read_server_minmaxinfo_order(s, &rail_order->minmaxinfo); rail_send_channel_event(rail_order->plugin, RDP_EVENT_TYPE_RAIL_CHANNEL_SERVER_MINMAXINFO, &rail_order->minmaxinfo); } void rail_recv_server_localmovesize_order(rdpRailOrder* rail_order, STREAM* s) { rail_read_server_localmovesize_order(s, &rail_order->localmovesize); rail_send_channel_event(rail_order->plugin, RDP_EVENT_TYPE_RAIL_CHANNEL_SERVER_LOCALMOVESIZE, &rail_order->localmovesize); } void rail_recv_server_get_appid_resp_order(rdpRailOrder* rail_order, STREAM* s) { rail_read_server_get_appid_resp_order(s, &rail_order->get_appid_resp); rail_send_channel_event(rail_order->plugin, RDP_EVENT_TYPE_RAIL_CHANNEL_APPID_RESP, &rail_order->get_appid_resp); } void rail_recv_langbar_info_order(rdpRailOrder* rail_order, STREAM* s) { rail_read_langbar_info_order(s, &rail_order->langbar_info); rail_send_channel_event(rail_order->plugin, RDP_EVENT_TYPE_RAIL_CHANNEL_LANGBARINFO, &rail_order->langbar_info); } void rail_order_recv(rdpRailOrder* rail_order, STREAM* s) { uint16 orderType; uint16 orderLength; rail_read_pdu_header(s, &orderType, &orderLength); DEBUG_RAIL("Received %s PDU, length:%d", RAIL_ORDER_TYPE_STRINGS[((orderType & 0xF0) >> 3) + (orderType & 0x0F)], orderLength); switch (orderType) { case RDP_RAIL_ORDER_HANDSHAKE: rail_recv_handshake_order(rail_order, s); break; case RDP_RAIL_ORDER_EXEC_RESULT: rail_recv_exec_result_order(rail_order, s); break; case RDP_RAIL_ORDER_SYSPARAM: rail_recv_server_sysparam_order(rail_order, s); break; case RDP_RAIL_ORDER_MINMAXINFO: rail_recv_server_minmaxinfo_order(rail_order, s); break; case RDP_RAIL_ORDER_LOCALMOVESIZE: rail_recv_server_localmovesize_order(rail_order, s); break; case RDP_RAIL_ORDER_GET_APPID_RESP: rail_recv_server_get_appid_resp_order(rail_order, s); break; case RDP_RAIL_ORDER_LANGBARINFO: rail_recv_langbar_info_order(rail_order, s); break; default: printf("Unknown RAIL PDU order reveived."); break; } } void rail_send_handshake_order(rdpRailOrder* rail_order) { STREAM* s; s = rail_pdu_init(RAIL_HANDSHAKE_ORDER_LENGTH); rail_write_handshake_order(s, &rail_order->handshake); rail_send_pdu(rail_order, s, RAIL_ORDER_TYPE_HANDSHAKE); } void rail_send_client_status_order(rdpRailOrder* rail_order) { STREAM* s; s = rail_pdu_init(RAIL_CLIENT_STATUS_ORDER_LENGTH); rail_write_client_status_order(s, &rail_order->client_status); rail_send_pdu(rail_order, s, RAIL_ORDER_TYPE_CLIENT_STATUS); } void rail_send_client_exec_order(rdpRailOrder* rail_order) { STREAM* s; int length; length = RAIL_EXEC_ORDER_LENGTH + rail_order->exec.exeOrFile.length + rail_order->exec.workingDir.length + rail_order->exec.arguments.length; s = rail_pdu_init(RAIL_EXEC_ORDER_LENGTH); rail_write_client_exec_order(s, &rail_order->exec); rail_send_pdu(rail_order, s, RAIL_ORDER_TYPE_EXEC); } void rail_send_client_sysparam_order(rdpRailOrder* rail_order) { STREAM* s; int length; length = RAIL_SYSPARAM_ORDER_LENGTH; switch (rail_order->sysparam.param) { case SPI_SET_DRAG_FULL_WINDOWS: case SPI_SET_KEYBOARD_CUES: case SPI_SET_KEYBOARD_PREF: case SPI_SET_MOUSE_BUTTON_SWAP: length += 1; break; case SPI_SET_WORK_AREA: case SPI_DISPLAY_CHANGE: case SPI_TASKBAR_POS: length += 8; break; case SPI_SET_HIGH_CONTRAST: length += rail_order->sysparam.highContrast.colorSchemeLength + 10; break; } s = rail_pdu_init(RAIL_SYSPARAM_ORDER_LENGTH + 8); rail_write_client_sysparam_order(s, &rail_order->sysparam); rail_send_pdu(rail_order, s, RAIL_ORDER_TYPE_SYSPARAM); } void rail_send_client_sysparams_order(rdpRailOrder* rail_order) { if (rail_order->sysparam.params & SPI_MASK_SET_HIGH_CONTRAST) { rail_order->sysparam.param = SPI_SET_HIGH_CONTRAST; rail_send_client_sysparam_order(rail_order); } if (rail_order->sysparam.params & SPI_MASK_TASKBAR_POS) { rail_order->sysparam.param = SPI_TASKBAR_POS; rail_send_client_sysparam_order(rail_order); } if (rail_order->sysparam.params & SPI_MASK_SET_MOUSE_BUTTON_SWAP) { rail_order->sysparam.param = SPI_SET_MOUSE_BUTTON_SWAP; rail_send_client_sysparam_order(rail_order); } if (rail_order->sysparam.params & SPI_MASK_SET_KEYBOARD_PREF) { rail_order->sysparam.param = SPI_SET_KEYBOARD_PREF; rail_send_client_sysparam_order(rail_order); } if (rail_order->sysparam.params & SPI_MASK_SET_DRAG_FULL_WINDOWS) { rail_order->sysparam.param = SPI_SET_DRAG_FULL_WINDOWS; rail_send_client_sysparam_order(rail_order); } if (rail_order->sysparam.params & SPI_MASK_SET_KEYBOARD_CUES) { rail_order->sysparam.param = SPI_SET_KEYBOARD_CUES; rail_send_client_sysparam_order(rail_order); } if (rail_order->sysparam.params & SPI_MASK_SET_WORK_AREA) { rail_order->sysparam.param = SPI_SET_WORK_AREA; rail_send_client_sysparam_order(rail_order); } } void rail_send_client_activate_order(rdpRailOrder* rail_order) { STREAM* s; s = rail_pdu_init(RAIL_ACTIVATE_ORDER_LENGTH); rail_write_client_activate_order(s, &rail_order->activate); rail_send_pdu(rail_order, s, RAIL_ORDER_TYPE_ACTIVATE); } void rail_send_client_sysmenu_order(rdpRailOrder* rail_order) { STREAM* s; s = rail_pdu_init(RAIL_SYSMENU_ORDER_LENGTH); rail_write_client_sysmenu_order(s, &rail_order->sysmenu); rail_send_pdu(rail_order, s, RAIL_ORDER_TYPE_SYSMENU); } void rail_send_client_syscommand_order(rdpRailOrder* rail_order) { STREAM* s; s = rail_pdu_init(RAIL_SYSCOMMAND_ORDER_LENGTH); rail_write_client_syscommand_order(s, &rail_order->syscommand); rail_send_pdu(rail_order, s, RAIL_ORDER_TYPE_SYSCOMMAND); } void rail_send_client_notify_event_order(rdpRailOrder* rail_order) { STREAM* s; s = rail_pdu_init(RAIL_NOTIFY_EVENT_ORDER_LENGTH); rail_write_client_notify_event_order(s, &rail_order->notify_event); rail_send_pdu(rail_order, s, RAIL_ORDER_TYPE_NOTIFY_EVENT); } void rail_send_client_window_move_order(rdpRailOrder* rail_order) { STREAM* s; s = rail_pdu_init(RAIL_WINDOW_MOVE_ORDER_LENGTH); rail_write_client_window_move_order(s, &rail_order->window_move); rail_send_pdu(rail_order, s, RAIL_ORDER_TYPE_WINDOW_MOVE); } void rail_send_client_get_appid_req_order(rdpRailOrder* rail_order) { STREAM* s; s = rail_pdu_init(RAIL_GET_APPID_REQ_ORDER_LENGTH); rail_write_client_get_appid_req_order(s, &rail_order->get_appid_req); rail_send_pdu(rail_order, s, RAIL_ORDER_TYPE_GET_APPID_REQ); } void rail_send_client_langbar_info_order(rdpRailOrder* rail_order) { STREAM* s; s = rail_pdu_init(RAIL_LANGBAR_INFO_ORDER_LENGTH); rail_write_langbar_info_order(s, &rail_order->langbar_info); rail_send_pdu(rail_order, s, RAIL_ORDER_TYPE_LANGBAR_INFO); } rdpRailOrder* rail_order_new() { rdpRailOrder* rail_order; rail_order = xnew(rdpRailOrder); if (rail_order != NULL) { rail_order->uniconv = freerdp_uniconv_new(); } return rail_order; } void rail_order_free(rdpRailOrder* rail_order) { if (rail_order != NULL) { freerdp_uniconv_free(rail_order->uniconv); xfree(rail_order); } } FreeRDP-1.0.2/channels/rail/rail_orders.h000066400000000000000000000112531207112532300201370ustar00rootroot00000000000000/** * FreeRDP: A Remote Desktop Protocol client. * Remote Applications Integrated Locally (RAIL) * * Copyright 2009 Marc-Andre Moreau * Copyright 2011 Roman Barabanov * * 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. */ #ifndef __RAIL_ORDERS_H #define __RAIL_ORDERS_H #include "rail_main.h" #define RAIL_ORDER_TYPE_EXEC 0x0001 #define RAIL_ORDER_TYPE_ACTIVATE 0x0002 #define RAIL_ORDER_TYPE_SYSPARAM 0x0003 #define RAIL_ORDER_TYPE_SYSCOMMAND 0x0004 #define RAIL_ORDER_TYPE_HANDSHAKE 0x0005 #define RAIL_ORDER_TYPE_NOTIFY_EVENT 0x0006 #define RAIL_ORDER_TYPE_WINDOW_MOVE 0x0008 #define RAIL_ORDER_TYPE_LOCALMOVESIZE 0x0009 #define RAIL_ORDER_TYPE_MINMAXINFO 0x000A #define RAIL_ORDER_TYPE_CLIENT_STATUS 0x000B #define RAIL_ORDER_TYPE_SYSMENU 0x000C #define RAIL_ORDER_TYPE_LANGBAR_INFO 0x000D #define RAIL_ORDER_TYPE_EXEC_RESULT 0x0080 #define RAIL_ORDER_TYPE_GET_APPID_REQ 0x000E #define RAIL_ORDER_TYPE_GET_APPID_RESP 0x000F #define RAIL_PDU_HEADER_LENGTH 4 /* Fixed length of PDUs, excluding variable lengths */ #define RAIL_HANDSHAKE_ORDER_LENGTH 4 /* fixed */ #define RAIL_CLIENT_STATUS_ORDER_LENGTH 4 /* fixed */ #define RAIL_EXEC_ORDER_LENGTH 8 /* variable */ #define RAIL_SYSPARAM_ORDER_LENGTH 4 /* variable */ #define RAIL_ACTIVATE_ORDER_LENGTH 5 /* fixed */ #define RAIL_SYSMENU_ORDER_LENGTH 8 /* fixed */ #define RAIL_SYSCOMMAND_ORDER_LENGTH 6 /* fixed */ #define RAIL_NOTIFY_EVENT_ORDER_LENGTH 12 /* fixed */ #define RAIL_WINDOW_MOVE_ORDER_LENGTH 12 /* fixed */ #define RAIL_GET_APPID_REQ_ORDER_LENGTH 4 /* fixed */ #define RAIL_LANGBAR_INFO_ORDER_LENGTH 4 /* fixed */ void rail_string_to_unicode_string(rdpRailOrder* rail_order, char* string, UNICODE_STRING* unicode_string); void rail_read_handshake_order(STREAM* s, RAIL_HANDSHAKE_ORDER* handshake); void rail_read_server_exec_result_order(STREAM* s, RAIL_EXEC_RESULT_ORDER* exec_result); void rail_read_server_sysparam_order(STREAM* s, RAIL_SYSPARAM_ORDER* sysparam); void rail_read_server_minmaxinfo_order(STREAM* s, RAIL_MINMAXINFO_ORDER* minmaxinfo); void rail_read_server_localmovesize_order(STREAM* s, RAIL_LOCALMOVESIZE_ORDER* localmovesize); void rail_read_server_get_appid_resp_order(STREAM* s, RAIL_GET_APPID_RESP_ORDER* get_appid_resp); void rail_read_langbar_info_order(STREAM* s, RAIL_LANGBAR_INFO_ORDER* langbar_info); void rail_write_handshake_order(STREAM* s, RAIL_HANDSHAKE_ORDER* handshake); void rail_write_client_status_order(STREAM* s, RAIL_CLIENT_STATUS_ORDER* client_status); void rail_write_client_exec_order(STREAM* s, RAIL_EXEC_ORDER* exec); void rail_write_client_sysparam_order(STREAM* s, RAIL_SYSPARAM_ORDER* sysparam); void rail_write_client_activate_order(STREAM* s, RAIL_ACTIVATE_ORDER* activate); void rail_write_client_sysmenu_order(STREAM* s, RAIL_SYSMENU_ORDER* sysmenu); void rail_write_client_syscommand_order(STREAM* s, RAIL_SYSCOMMAND_ORDER* syscommand); void rail_write_client_notify_event_order(STREAM* s, RAIL_NOTIFY_EVENT_ORDER* notify_event); void rail_write_client_window_move_order(STREAM* s, RAIL_WINDOW_MOVE_ORDER* window_move); void rail_write_client_get_appid_req_order(STREAM* s, RAIL_GET_APPID_REQ_ORDER* get_appid_req); void rail_write_langbar_info_order(STREAM* s, RAIL_LANGBAR_INFO_ORDER* langbar_info); void rail_order_recv(rdpRailOrder* rail_order, STREAM* s); void rail_send_handshake_order(rdpRailOrder* rail_order); void rail_send_client_status_order(rdpRailOrder* rail_order); void rail_send_client_exec_order(rdpRailOrder* rail_order); void rail_send_client_sysparam_order(rdpRailOrder* rail_order); void rail_send_client_sysparams_order(rdpRailOrder* rail_order); void rail_send_client_activate_order(rdpRailOrder* rail_order); void rail_send_client_sysmenu_order(rdpRailOrder* rail_order); void rail_send_client_syscommand_order(rdpRailOrder* rail_order); void rail_send_client_notify_event_order(rdpRailOrder* rail_order); void rail_send_client_window_move_order(rdpRailOrder* rail_order); void rail_send_client_get_appid_req_order(rdpRailOrder* rail_order); void rail_send_client_langbar_info_order(rdpRailOrder* rail_order); rdpRailOrder* rail_order_new(); void rail_order_free(rdpRailOrder* rail_order); #endif /* __RAIL_ORDERS_H */ FreeRDP-1.0.2/channels/rdpdbg/000077500000000000000000000000001207112532300157725ustar00rootroot00000000000000FreeRDP-1.0.2/channels/rdpdbg/CMakeLists.txt000066400000000000000000000017671207112532300205450ustar00rootroot00000000000000# FreeRDP: A Remote Desktop Protocol Client # FreeRDP cmake build script # # Copyright 2011 O.S. Systems Software Ltda. # Copyright 2011 Otavio Salvador # Copyright 2011 Marc-Andre Moreau # # 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(RDPDBG_SRCS rdpdbg_main.c ) add_library(rdpdbg ${RDPDBG_SRCS}) set_target_properties(rdpdbg PROPERTIES PREFIX "") target_link_libraries(rdpdbg freerdp-utils) install(TARGETS rdpdbg DESTINATION ${FREERDP_PLUGIN_PATH}) FreeRDP-1.0.2/channels/rdpdbg/rdpdbg_main.c000066400000000000000000000035711207112532300204120ustar00rootroot00000000000000/** * FreeRDP: A Remote Desktop Protocol client. * Debugging Virtual Channel * * Copyright 2010-2011 Marc-Andre Moreau * Copyright 2011 Vic Lee * * 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. */ #include #include #include #include #include #include #include typedef struct rdpdbg_plugin rdpdbgPlugin; struct rdpdbg_plugin { rdpSvcPlugin plugin; }; static void rdpdbg_process_connect(rdpSvcPlugin* plugin) { DEBUG_WARN("connecting"); } static void rdpdbg_process_receive(rdpSvcPlugin* plugin, STREAM* data_in) { STREAM* data_out; DEBUG_WARN("size %d", stream_get_size(data_in)); stream_free(data_in); data_out = stream_new(8); stream_write(data_out, "senddata", 8); svc_plugin_send(plugin, data_out); } static void rdpdbg_process_event(rdpSvcPlugin* plugin, RDP_EVENT* event) { DEBUG_WARN("event_type %d", event->event_type); freerdp_event_free(event); event = freerdp_event_new(RDP_EVENT_CLASS_DEBUG, 0, NULL, NULL); svc_plugin_send_event(plugin, event); } static void rdpdbg_process_terminate(rdpSvcPlugin* plugin) { DEBUG_WARN("terminating"); xfree(plugin); } DEFINE_SVC_PLUGIN(rdpdbg, "rdpdbg", CHANNEL_OPTION_INITIALIZED | CHANNEL_OPTION_ENCRYPT_RDP | CHANNEL_OPTION_COMPRESS_RDP | CHANNEL_OPTION_SHOW_PROTOCOL) FreeRDP-1.0.2/channels/rdpdr/000077500000000000000000000000001207112532300156435ustar00rootroot00000000000000FreeRDP-1.0.2/channels/rdpdr/CMakeLists.txt000066400000000000000000000024101207112532300204000ustar00rootroot00000000000000# FreeRDP: A Remote Desktop Protocol Client # FreeRDP cmake build script # # Copyright 2011 O.S. Systems Software Ltda. # Copyright 2011 Otavio Salvador # Copyright 2011 Marc-Andre Moreau # # 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(RDPDR_SRCS rdpdr_constants.h rdpdr_types.h rdpdr_capabilities.c rdpdr_capabilities.h devman.c devman.h irp.c irp.h rdpdr_main.c rdpdr_main.h ) add_library(rdpdr ${RDPDR_SRCS}) set_target_properties(rdpdr PROPERTIES PREFIX "") target_link_libraries(rdpdr freerdp-utils) install(TARGETS rdpdr DESTINATION ${FREERDP_PLUGIN_PATH}) add_subdirectory(disk) add_subdirectory(printer) add_subdirectory(parallel) add_subdirectory(serial) if(WITH_PCSC) add_subdirectory(smartcard) endif() FreeRDP-1.0.2/channels/rdpdr/devman.c000066400000000000000000000050031207112532300172570ustar00rootroot00000000000000/** * FreeRDP: A Remote Desktop Protocol client. * File System Virtual Channel * * Copyright 2010-2011 Marc-Andre Moreau * Copyright 2010-2011 Vic Lee * * 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. */ #include "config.h" #include #include #include #include #include #include #include #include #include #include "rdpdr_types.h" #include "devman.h" DEVMAN* devman_new(rdpSvcPlugin* plugin) { DEVMAN* devman; devman = xnew(DEVMAN); devman->plugin = plugin; devman->id_sequence = 1; devman->devices = list_new(); return devman; } void devman_free(DEVMAN* devman) { DEVICE* device; while ((device = (DEVICE*) list_dequeue(devman->devices)) != NULL) IFCALL(device->Free, device); list_free(devman->devices); xfree(devman); } static void devman_register_device(DEVMAN* devman, DEVICE* device) { device->id = devman->id_sequence++; list_add(devman->devices, device); DEBUG_SVC("device %d.%s registered", device->id, device->name); } static void devman_unregister_device(DEVMAN* devman, DEVICE* device) { list_remove(devman->devices, device); DEBUG_SVC("device %d.%s unregistered", device->id, device->name); } boolean devman_load_device_service(DEVMAN* devman, RDP_PLUGIN_DATA* plugin_data) { DEVICE_SERVICE_ENTRY_POINTS ep; PDEVICE_SERVICE_ENTRY entry; entry = freerdp_load_plugin((char*) plugin_data->data[0], "DeviceServiceEntry"); if (entry == NULL) return false; ep.devman = devman; ep.RegisterDevice = devman_register_device; ep.UnregisterDevice = devman_unregister_device; ep.plugin_data = plugin_data; entry(&ep); return true; } DEVICE* devman_get_device_by_id(DEVMAN* devman, uint32 id) { LIST_ITEM* item; DEVICE* device; for (item = devman->devices->head; item; item = item->next) { device = (DEVICE*) item->data; if (device->id == id) return device; } return NULL; } FreeRDP-1.0.2/channels/rdpdr/devman.h000066400000000000000000000020061207112532300172640ustar00rootroot00000000000000/** * FreeRDP: A Remote Desktop Protocol client. * File System Virtual Channel * * Copyright 2010-2011 Marc-Andre Moreau * Copyright 2010-2011 Vic Lee * * 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. */ #ifndef __DEVMAN_H #define __DEVMAN_H DEVMAN* devman_new(rdpSvcPlugin* plugin); void devman_free(DEVMAN* devman); boolean devman_load_device_service(DEVMAN* devman, RDP_PLUGIN_DATA* plugin_data); DEVICE* devman_get_device_by_id(DEVMAN* devman, uint32 id); #endif /* __DEVMAN_H */ FreeRDP-1.0.2/channels/rdpdr/disk/000077500000000000000000000000001207112532300165755ustar00rootroot00000000000000FreeRDP-1.0.2/channels/rdpdr/disk/CMakeLists.txt000066400000000000000000000020341207112532300213340ustar00rootroot00000000000000# FreeRDP: A Remote Desktop Protocol Client # FreeRDP cmake build script # # Copyright 2011 O.S. Systems Software Ltda. # Copyright 2011 Otavio Salvador # Copyright 2011 Marc-Andre Moreau # # 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(DISK_SRCS disk_file.c disk_file.h disk_main.c ) include_directories(..) add_library(disk ${DISK_SRCS}) set_target_properties(disk PROPERTIES PREFIX "") target_link_libraries(disk freerdp-utils) install(TARGETS disk DESTINATION ${FREERDP_PLUGIN_PATH}) FreeRDP-1.0.2/channels/rdpdr/disk/disk_file.c000066400000000000000000000411371207112532300207000ustar00rootroot00000000000000/** * FreeRDP: A Remote Desktop Protocol client. * File System Virtual Channel * * Copyright 2010-2011 Marc-Andre Moreau * Copyright 2010-2011 Vic Lee * * 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. */ #ifndef _WIN32 #include #endif #include "config.h" #include #include #include #include #include #include #include #include #include #ifdef HAVE_UNISTD_H #include #endif #ifdef HAVE_FCNTL_H #include #endif #include "rdpdr_constants.h" #include "rdpdr_types.h" #include "disk_file.h" #define FILE_TIME_SYSTEM_TO_RDP(_t) \ (((uint64)(_t) + 11644473600LL) * 10000000LL) #define FILE_TIME_RDP_TO_SYSTEM(_t) \ (((_t) == 0LL || (_t) == (uint64)(-1LL)) ? 0 : (time_t)((_t) / 10000000LL - 11644473600LL)) #define FILE_ATTR_SYSTEM_TO_RDP(_f, _st) ( \ (S_ISDIR(_st.st_mode) ? FILE_ATTRIBUTE_DIRECTORY : 0) | \ (_f->filename[0] == '.' ? FILE_ATTRIBUTE_HIDDEN : 0) | \ (_f->delete_pending ? FILE_ATTRIBUTE_TEMPORARY : 0) | \ (st.st_mode & S_IWUSR ? 0 : FILE_ATTRIBUTE_READONLY)) static boolean disk_file_wildcard_match(const char* pattern, const char* filename) { const char *p = pattern, *f = filename; char c; /* * TODO: proper wildcard rules per msft's File System Behavior Overview * Simple cases for now. */ f = filename; while ((c = *p++)) { if (c == '*') { c = *p++; if (!c) /* shortcut */ return true; /* TODO: skip to tail comparison */ } if (c != *f++) return false; } if (!*f) return true; return false; } static void disk_file_fix_path(char* path) { int len; int i; len = strlen(path); for (i = 0; i < len; i++) { if (path[i] == '\\') path[i] = '/'; } if (len > 0 && path[len - 1] == '/') path[len - 1] = '\0'; } static char* disk_file_combine_fullpath(const char* base_path, const char* path) { char* fullpath; fullpath = xmalloc(strlen(base_path) + strlen(path) + 1); strcpy(fullpath, base_path); strcat(fullpath, path); disk_file_fix_path(fullpath); return fullpath; } static boolean disk_file_remove_dir(const char* path) { DIR* dir; struct dirent* pdirent; struct stat st; char* p; boolean ret = true; dir = opendir(path); if (dir == NULL) return false; pdirent = readdir(dir); while (pdirent) { if (strcmp(pdirent->d_name, ".") == 0 || strcmp(pdirent->d_name, "..") == 0) { pdirent = readdir(dir); continue; } p = xmalloc(strlen(path) + strlen(pdirent->d_name) + 2); sprintf(p, "%s/%s", path, pdirent->d_name); if (stat(p, &st) != 0) { DEBUG_WARN("stat %s failed.", p); ret = false; } else if (S_ISDIR(st.st_mode)) { ret = disk_file_remove_dir(p); } else if (unlink(p) < 0) { DEBUG_WARN("unlink %s failed.", p); ret = false; } else ret = true; xfree(p); if (!ret) break; pdirent = readdir(dir); } closedir(dir); if (ret) { if (rmdir(path) < 0) { DEBUG_WARN("rmdir %s failed.", path); ret = false; } } return ret; } static void disk_file_set_fullpath(DISK_FILE* file, char* fullpath) { xfree(file->fullpath); file->fullpath = fullpath; file->filename = strrchr(file->fullpath, '/'); if (file->filename == NULL) file->filename = file->fullpath; else file->filename += 1; } static boolean disk_file_init(DISK_FILE* file, uint32 DesiredAccess, uint32 CreateDisposition, uint32 CreateOptions) { const static int mode = S_IRWXU | S_IRWXG | S_IROTH | S_IXOTH; struct stat st; boolean exists; int oflag = 0; if (stat(file->fullpath, &st) == 0) { file->is_dir = (S_ISDIR(st.st_mode) ? true : false); exists = true; } else { file->is_dir = ((CreateOptions & FILE_DIRECTORY_FILE) ? true : false); if (file->is_dir) { if (mkdir(file->fullpath, mode) != 0) { file->err = errno; return true; } } exists = false; } if (file->is_dir) { file->dir = opendir(file->fullpath); if (file->dir == NULL) { file->err = errno; return true; } } else { switch (CreateDisposition) { case FILE_SUPERSEDE: oflag = O_TRUNC | O_CREAT; break; case FILE_OPEN: break; case FILE_CREATE: oflag = O_CREAT | O_EXCL; break; case FILE_OPEN_IF: oflag = O_CREAT; break; case FILE_OVERWRITE: oflag = O_TRUNC; break; case FILE_OVERWRITE_IF: oflag = O_TRUNC | O_CREAT; break; default: break; } if (CreateOptions & FILE_DELETE_ON_CLOSE && DesiredAccess & DELETE) { file->delete_pending = true; } if ((DesiredAccess & GENERIC_ALL) || (DesiredAccess & GENERIC_WRITE) || (DesiredAccess & FILE_WRITE_DATA) || (DesiredAccess & FILE_APPEND_DATA)) { oflag |= O_RDWR; } else { oflag |= O_RDONLY; } file->fd = open(file->fullpath, oflag, mode); if (file->fd == -1) { file->err = errno; return true; } } return true; } DISK_FILE* disk_file_new(const char* base_path, const char* path, uint32 id, uint32 DesiredAccess, uint32 CreateDisposition, uint32 CreateOptions) { DISK_FILE* file; file = xnew(DISK_FILE); file->id = id; file->basepath = (char*) base_path; disk_file_set_fullpath(file, disk_file_combine_fullpath(base_path, path)); file->fd = -1; if (!disk_file_init(file, DesiredAccess, CreateDisposition, CreateOptions)) { disk_file_free(file); return NULL; } return file; } void disk_file_free(DISK_FILE* file) { if (file->fd != -1) close(file->fd); if (file->dir != NULL) closedir(file->dir); if (file->delete_pending) { if (file->is_dir) disk_file_remove_dir(file->fullpath); else unlink(file->fullpath); } xfree(file->pattern); xfree(file->fullpath); xfree(file); } boolean disk_file_seek(DISK_FILE* file, uint64 Offset) { if (file->is_dir || file->fd == -1) return false; if (lseek(file->fd, Offset, SEEK_SET) == (off_t)-1) return false; return true; } boolean disk_file_read(DISK_FILE* file, uint8* buffer, uint32* Length) { ssize_t r; if (file->is_dir || file->fd == -1) return false; r = read(file->fd, buffer, *Length); if (r < 0) return false; *Length = (uint32)r; return true; } boolean disk_file_write(DISK_FILE* file, uint8* buffer, uint32 Length) { ssize_t r; if (file->is_dir || file->fd == -1) return false; while (Length > 0) { r = write(file->fd, buffer, Length); if (r == -1) return false; Length -= r; buffer += r; } return true; } boolean disk_file_query_information(DISK_FILE* file, uint32 FsInformationClass, STREAM* output) { struct stat st; if (stat(file->fullpath, &st) != 0) { stream_write_uint32(output, 0); /* Length */ return false; } switch (FsInformationClass) { case FileBasicInformation: /* http://msdn.microsoft.com/en-us/library/cc232094.aspx */ stream_write_uint32(output, 36); /* Length */ stream_check_size(output, 36); stream_write_uint64(output, FILE_TIME_SYSTEM_TO_RDP(st.st_mtime)); /* CreationTime */ stream_write_uint64(output, FILE_TIME_SYSTEM_TO_RDP(st.st_atime)); /* LastAccessTime */ stream_write_uint64(output, FILE_TIME_SYSTEM_TO_RDP(st.st_mtime)); /* LastWriteTime */ stream_write_uint64(output, FILE_TIME_SYSTEM_TO_RDP(st.st_ctime)); /* ChangeTime */ stream_write_uint32(output, FILE_ATTR_SYSTEM_TO_RDP(file, st)); /* FileAttributes */ /* Reserved(4), MUST NOT be added! */ break; case FileStandardInformation: /* http://msdn.microsoft.com/en-us/library/cc232088.aspx */ stream_write_uint32(output, 22); /* Length */ stream_check_size(output, 22); stream_write_uint64(output, st.st_size); /* AllocationSize */ stream_write_uint64(output, st.st_size); /* EndOfFile */ stream_write_uint32(output, st.st_nlink); /* NumberOfLinks */ stream_write_uint8(output, file->delete_pending ? 1 : 0); /* DeletePending */ stream_write_uint8(output, file->is_dir ? 1 : 0); /* Directory */ /* Reserved(2), MUST NOT be added! */ break; case FileAttributeTagInformation: /* http://msdn.microsoft.com/en-us/library/cc232093.aspx */ stream_write_uint32(output, 8); /* Length */ stream_check_size(output, 8); stream_write_uint32(output, FILE_ATTR_SYSTEM_TO_RDP(file, st)); /* FileAttributes */ stream_write_uint32(output, 0); /* ReparseTag */ break; default: stream_write_uint32(output, 0); /* Length */ DEBUG_WARN("invalid FsInformationClass %d", FsInformationClass); return false; } return true; } boolean disk_file_set_information(DISK_FILE* file, uint32 FsInformationClass, uint32 Length, STREAM* input) { char* s; mode_t m; uint64 size; char* fullpath; struct stat st; UNICONV* uniconv; struct timeval tv[2]; uint64 LastWriteTime; uint32 FileAttributes; uint32 FileNameLength; switch (FsInformationClass) { case FileBasicInformation: /* http://msdn.microsoft.com/en-us/library/cc232094.aspx */ stream_seek_uint64(input); /* CreationTime */ stream_seek_uint64(input); /* LastAccessTime */ stream_read_uint64(input, LastWriteTime); stream_seek_uint64(input); /* ChangeTime */ stream_read_uint32(input, FileAttributes); if (fstat(file->fd, &st) != 0) return false; tv[0].tv_sec = st.st_atime; tv[0].tv_usec = 0; tv[1].tv_sec = (LastWriteTime > 0 ? FILE_TIME_RDP_TO_SYSTEM(LastWriteTime) : st.st_mtime); tv[1].tv_usec = 0; futimes(file->fd, tv); if (FileAttributes > 0) { m = st.st_mode; if ((FileAttributes & FILE_ATTRIBUTE_READONLY) == 0) m |= S_IWUSR; else m &= ~S_IWUSR; if (m != st.st_mode) fchmod(file->fd, st.st_mode); } break; case FileEndOfFileInformation: /* http://msdn.microsoft.com/en-us/library/cc232067.aspx */ case FileAllocationInformation: /* http://msdn.microsoft.com/en-us/library/cc232076.aspx */ stream_read_uint64(input, size); if (ftruncate(file->fd, size) != 0) return false; break; case FileDispositionInformation: /* http://msdn.microsoft.com/en-us/library/cc232098.aspx */ /* http://msdn.microsoft.com/en-us/library/cc241371.aspx */ if (Length) stream_read_uint8(input, file->delete_pending); else file->delete_pending = 1; break; case FileRenameInformation: /* http://msdn.microsoft.com/en-us/library/cc232085.aspx */ stream_seek_uint8(input); /* ReplaceIfExists */ stream_seek_uint8(input); /* RootDirectory */ stream_read_uint32(input, FileNameLength); uniconv = freerdp_uniconv_new(); s = freerdp_uniconv_in(uniconv, stream_get_tail(input), FileNameLength); freerdp_uniconv_free(uniconv); fullpath = disk_file_combine_fullpath(file->basepath, s); xfree(s); if (rename(file->fullpath, fullpath) == 0) { DEBUG_SVC("renamed %s to %s", file->fullpath, fullpath); disk_file_set_fullpath(file, fullpath); } else { DEBUG_WARN("rename %s to %s failed", file->fullpath, fullpath); free(fullpath); return false; } break; default: DEBUG_WARN("invalid FsInformationClass %d", FsInformationClass); return false; } return true; } boolean disk_file_query_directory(DISK_FILE* file, uint32 FsInformationClass, uint8 InitialQuery, const char* path, STREAM* output) { struct dirent* ent; char* ent_path; struct stat st; UNICONV* uniconv; size_t len; boolean ret; DEBUG_SVC("path %s FsInformationClass %d InitialQuery %d", path, FsInformationClass, InitialQuery); if (!file->dir) { stream_write_uint32(output, 0); /* Length */ stream_write_uint8(output, 0); /* Padding */ return false; } if (InitialQuery != 0) { rewinddir(file->dir); xfree(file->pattern); if (path[0]) file->pattern = strdup(strrchr(path, '\\') + 1); else file->pattern = NULL; } if (file->pattern) { do { ent = readdir(file->dir); if (ent == NULL) continue; if (disk_file_wildcard_match(file->pattern, ent->d_name)) break; } while (ent); } else { ent = readdir(file->dir); } if (ent == NULL) { DEBUG_SVC(" pattern %s not found.", file->pattern); stream_write_uint32(output, 0); /* Length */ stream_write_uint8(output, 0); /* Padding */ return false; } memset(&st, 0, sizeof(struct stat)); ent_path = xmalloc(strlen(file->fullpath) + strlen(ent->d_name) + 2); sprintf(ent_path, "%s/%s", file->fullpath, ent->d_name); if (stat(ent_path, &st) != 0) { DEBUG_WARN("stat %s failed.", ent_path); } xfree(ent_path); DEBUG_SVC(" pattern %s matched %s\n", file->pattern, ent_path); uniconv = freerdp_uniconv_new(); ent_path = freerdp_uniconv_out(uniconv, ent->d_name, &len); freerdp_uniconv_free(uniconv); ret = true; switch (FsInformationClass) { case FileDirectoryInformation: /* http://msdn.microsoft.com/en-us/library/cc232097.aspx */ stream_write_uint32(output, 64 + len); /* Length */ stream_check_size(output, 64 + len); stream_write_uint32(output, 0); /* NextEntryOffset */ stream_write_uint32(output, 0); /* FileIndex */ stream_write_uint64(output, FILE_TIME_SYSTEM_TO_RDP(st.st_mtime)); /* CreationTime */ stream_write_uint64(output, FILE_TIME_SYSTEM_TO_RDP(st.st_atime)); /* LastAccessTime */ stream_write_uint64(output, FILE_TIME_SYSTEM_TO_RDP(st.st_mtime)); /* LastWriteTime */ stream_write_uint64(output, FILE_TIME_SYSTEM_TO_RDP(st.st_ctime)); /* ChangeTime */ stream_write_uint64(output, st.st_size); /* EndOfFile */ stream_write_uint64(output, st.st_size); /* AllocationSize */ stream_write_uint32(output, FILE_ATTR_SYSTEM_TO_RDP(file, st)); /* FileAttributes */ stream_write_uint32(output, len); /* FileNameLength */ stream_write(output, ent_path, len); break; case FileFullDirectoryInformation: /* http://msdn.microsoft.com/en-us/library/cc232068.aspx */ stream_write_uint32(output, 68 + len); /* Length */ stream_check_size(output, 68 + len); stream_write_uint32(output, 0); /* NextEntryOffset */ stream_write_uint32(output, 0); /* FileIndex */ stream_write_uint64(output, FILE_TIME_SYSTEM_TO_RDP(st.st_mtime)); /* CreationTime */ stream_write_uint64(output, FILE_TIME_SYSTEM_TO_RDP(st.st_atime)); /* LastAccessTime */ stream_write_uint64(output, FILE_TIME_SYSTEM_TO_RDP(st.st_mtime)); /* LastWriteTime */ stream_write_uint64(output, FILE_TIME_SYSTEM_TO_RDP(st.st_ctime)); /* ChangeTime */ stream_write_uint64(output, st.st_size); /* EndOfFile */ stream_write_uint64(output, st.st_size); /* AllocationSize */ stream_write_uint32(output, FILE_ATTR_SYSTEM_TO_RDP(file, st)); /* FileAttributes */ stream_write_uint32(output, len); /* FileNameLength */ stream_write_uint32(output, 0); /* EaSize */ stream_write(output, ent_path, len); break; case FileBothDirectoryInformation: /* http://msdn.microsoft.com/en-us/library/cc232095.aspx */ stream_write_uint32(output, 93 + len); /* Length */ stream_check_size(output, 93 + len); stream_write_uint32(output, 0); /* NextEntryOffset */ stream_write_uint32(output, 0); /* FileIndex */ stream_write_uint64(output, FILE_TIME_SYSTEM_TO_RDP(st.st_mtime)); /* CreationTime */ stream_write_uint64(output, FILE_TIME_SYSTEM_TO_RDP(st.st_atime)); /* LastAccessTime */ stream_write_uint64(output, FILE_TIME_SYSTEM_TO_RDP(st.st_mtime)); /* LastWriteTime */ stream_write_uint64(output, FILE_TIME_SYSTEM_TO_RDP(st.st_ctime)); /* ChangeTime */ stream_write_uint64(output, st.st_size); /* EndOfFile */ stream_write_uint64(output, st.st_size); /* AllocationSize */ stream_write_uint32(output, FILE_ATTR_SYSTEM_TO_RDP(file, st)); /* FileAttributes */ stream_write_uint32(output, len); /* FileNameLength */ stream_write_uint32(output, 0); /* EaSize */ stream_write_uint8(output, 0); /* ShortNameLength */ /* Reserved(1), MUST NOT be added! */ stream_write_zero(output, 24); /* ShortName */ stream_write(output, ent_path, len); break; case FileNamesInformation: /* http://msdn.microsoft.com/en-us/library/cc232077.aspx */ stream_write_uint32(output, 12 + len); /* Length */ stream_check_size(output, 12 + len); stream_write_uint32(output, 0); /* NextEntryOffset */ stream_write_uint32(output, 0); /* FileIndex */ stream_write_uint32(output, len); /* FileNameLength */ stream_write(output, ent_path, len); break; default: stream_write_uint32(output, 0); /* Length */ stream_write_uint8(output, 0); /* Padding */ DEBUG_WARN("invalid FsInformationClass %d", FsInformationClass); ret = false; break; } xfree(ent_path); return ret; } FreeRDP-1.0.2/channels/rdpdr/disk/disk_file.h000066400000000000000000000034431207112532300207030ustar00rootroot00000000000000/** * FreeRDP: A Remote Desktop Protocol client. * File System Virtual Channel * * Copyright 2010-2011 Marc-Andre Moreau * Copyright 2010-2011 Vic Lee * * 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. */ #ifndef __DISK_FILE_H #define __DISK_FILE_H #include #include #include typedef struct _DISK_FILE DISK_FILE; struct _DISK_FILE { uint32 id; boolean is_dir; int fd; int err; DIR* dir; char* basepath; char* fullpath; char* filename; char* pattern; boolean delete_pending; }; DISK_FILE* disk_file_new(const char* base_path, const char* path, uint32 id, uint32 DesiredAccess, uint32 CreateDisposition, uint32 CreateOptions); void disk_file_free(DISK_FILE* file); boolean disk_file_seek(DISK_FILE* file, uint64 Offset); boolean disk_file_read(DISK_FILE* file, uint8* buffer, uint32* Length); boolean disk_file_write(DISK_FILE* file, uint8* buffer, uint32 Length); boolean disk_file_query_information(DISK_FILE* file, uint32 FsInformationClass, STREAM* output); boolean disk_file_set_information(DISK_FILE* file, uint32 FsInformationClass, uint32 Length, STREAM* input); boolean disk_file_query_directory(DISK_FILE* file, uint32 FsInformationClass, uint8 InitialQuery, const char* path, STREAM* output); #endif /* __DISK_FILE_H */ FreeRDP-1.0.2/channels/rdpdr/disk/disk_main.c000066400000000000000000000364411207112532300207070ustar00rootroot00000000000000/** * FreeRDP: A Remote Desktop Protocol client. * File System Virtual Channel * * Copyright 2010-2011 Marc-Andre Moreau * Copyright 2010-2011 Vic Lee * * 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. */ #include "config.h" #include #include #include #include #include #include #include #include #include #include #include "rdpdr_constants.h" #include "rdpdr_types.h" #include "disk_file.h" typedef struct _DISK_DEVICE DISK_DEVICE; struct _DISK_DEVICE { DEVICE device; char* path; LIST* files; LIST* irp_list; freerdp_thread* thread; }; static uint32 disk_map_posix_err(int fs_errno) { uint32 rc; /* try to return NTSTATUS version of error code */ switch (fs_errno) { case EPERM: case EACCES: rc = STATUS_ACCESS_DENIED; break; case ENOENT: rc = STATUS_NO_SUCH_FILE; break; case EBUSY: rc = STATUS_DEVICE_BUSY; break; case EEXIST: rc = STATUS_OBJECT_NAME_COLLISION; break; case EISDIR: rc = STATUS_FILE_IS_A_DIRECTORY; break; default: rc = STATUS_UNSUCCESSFUL; break; } DEBUG_SVC("errno 0x%x mapped to 0x%x\n", fs_errno, rc); return rc; } static DISK_FILE* disk_get_file_by_id(DISK_DEVICE* disk, uint32 id) { LIST_ITEM* item; DISK_FILE* file; for (item = disk->files->head; item; item = item->next) { file = (DISK_FILE*)item->data; if (file->id == id) return file; } return NULL; } static void disk_process_irp_create(DISK_DEVICE* disk, IRP* irp) { DISK_FILE* file; uint32 DesiredAccess; uint32 CreateDisposition; uint32 CreateOptions; uint32 PathLength; UNICONV* uniconv; char* path; uint32 FileId; uint8 Information; stream_read_uint32(irp->input, DesiredAccess); stream_seek(irp->input, 16); /* AllocationSize(8), FileAttributes(4), SharedAccess(4) */ stream_read_uint32(irp->input, CreateDisposition); stream_read_uint32(irp->input, CreateOptions); stream_read_uint32(irp->input, PathLength); uniconv = freerdp_uniconv_new(); path = freerdp_uniconv_in(uniconv, stream_get_tail(irp->input), PathLength); freerdp_uniconv_free(uniconv); FileId = irp->devman->id_sequence++; file = disk_file_new(disk->path, path, FileId, DesiredAccess, CreateDisposition, CreateOptions); if (file == NULL) { irp->IoStatus = STATUS_UNSUCCESSFUL; FileId = 0; Information = 0; DEBUG_WARN("failed to create %s.", path); } else if (file->err) { FileId = 0; Information = 0; /* map errno to windows result*/ irp->IoStatus = disk_map_posix_err(file->err); disk_file_free(file); } else { list_enqueue(disk->files, file); switch (CreateDisposition) { case FILE_SUPERSEDE: case FILE_OPEN: case FILE_CREATE: case FILE_OVERWRITE: Information = FILE_SUPERSEDED; break; case FILE_OPEN_IF: Information = FILE_OPENED; break; case FILE_OVERWRITE_IF: Information = FILE_OVERWRITTEN; break; default: Information = 0; break; } DEBUG_SVC("%s(%d) created.", file->fullpath, file->id); } stream_write_uint32(irp->output, FileId); stream_write_uint8(irp->output, Information); xfree(path); irp->Complete(irp); } static void disk_process_irp_close(DISK_DEVICE* disk, IRP* irp) { DISK_FILE* file; file = disk_get_file_by_id(disk, irp->FileId); if (file == NULL) { irp->IoStatus = STATUS_UNSUCCESSFUL; DEBUG_WARN("FileId %d not valid.", irp->FileId); } else { DEBUG_SVC("%s(%d) closed.", file->fullpath, file->id); list_remove(disk->files, file); disk_file_free(file); } stream_write_zero(irp->output, 5); /* Padding(5) */ irp->Complete(irp); } static void disk_process_irp_read(DISK_DEVICE* disk, IRP* irp) { DISK_FILE* file; uint32 Length; uint64 Offset; uint8* buffer = NULL; stream_read_uint32(irp->input, Length); stream_read_uint64(irp->input, Offset); file = disk_get_file_by_id(disk, irp->FileId); if (file == NULL) { irp->IoStatus = STATUS_UNSUCCESSFUL; Length = 0; DEBUG_WARN("FileId %d not valid.", irp->FileId); } else if (!disk_file_seek(file, Offset)) { irp->IoStatus = STATUS_UNSUCCESSFUL; Length = 0; DEBUG_WARN("seek %s(%d) failed.", file->fullpath, file->id); } else { buffer = (uint8*)xmalloc(Length); if (!disk_file_read(file, buffer, &Length)) { irp->IoStatus = STATUS_UNSUCCESSFUL; xfree(buffer); buffer = NULL; Length = 0; DEBUG_WARN("read %s(%d) failed.", file->fullpath, file->id); } else { DEBUG_SVC("read %llu-%llu from %s(%d).", Offset, Offset + Length, file->fullpath, file->id); } } stream_write_uint32(irp->output, Length); if (Length > 0) { stream_check_size(irp->output, Length); stream_write(irp->output, buffer, Length); } xfree(buffer); irp->Complete(irp); } static void disk_process_irp_write(DISK_DEVICE* disk, IRP* irp) { DISK_FILE* file; uint32 Length; uint64 Offset; stream_read_uint32(irp->input, Length); stream_read_uint64(irp->input, Offset); stream_seek(irp->input, 20); /* Padding */ file = disk_get_file_by_id(disk, irp->FileId); if (file == NULL) { irp->IoStatus = STATUS_UNSUCCESSFUL; Length = 0; DEBUG_WARN("FileId %d not valid.", irp->FileId); } else if (!disk_file_seek(file, Offset)) { irp->IoStatus = STATUS_UNSUCCESSFUL; Length = 0; DEBUG_WARN("seek %s(%d) failed.", file->fullpath, file->id); } else if (!disk_file_write(file, stream_get_tail(irp->input), Length)) { irp->IoStatus = STATUS_UNSUCCESSFUL; Length = 0; DEBUG_WARN("write %s(%d) failed.", file->fullpath, file->id); } else { DEBUG_SVC("write %llu-%llu to %s(%d).", Offset, Offset + Length, file->fullpath, file->id); } stream_write_uint32(irp->output, Length); stream_write_uint8(irp->output, 0); /* Padding */ irp->Complete(irp); } static void disk_process_irp_query_information(DISK_DEVICE* disk, IRP* irp) { DISK_FILE* file; uint32 FsInformationClass; stream_read_uint32(irp->input, FsInformationClass); file = disk_get_file_by_id(disk, irp->FileId); if (file == NULL) { irp->IoStatus = STATUS_UNSUCCESSFUL; DEBUG_WARN("FileId %d not valid.", irp->FileId); } else if (!disk_file_query_information(file, FsInformationClass, irp->output)) { irp->IoStatus = STATUS_UNSUCCESSFUL; DEBUG_WARN("FsInformationClass %d on %s(%d) failed.", FsInformationClass, file->fullpath, file->id); } else { DEBUG_SVC("FsInformationClass %d on %s(%d).", FsInformationClass, file->fullpath, file->id); } irp->Complete(irp); } static void disk_process_irp_set_information(DISK_DEVICE* disk, IRP* irp) { DISK_FILE* file; uint32 FsInformationClass; uint32 Length; stream_read_uint32(irp->input, FsInformationClass); stream_read_uint32(irp->input, Length); stream_seek(irp->input, 24); /* Padding */ file = disk_get_file_by_id(disk, irp->FileId); if (file == NULL) { irp->IoStatus = STATUS_UNSUCCESSFUL; DEBUG_WARN("FileId %d not valid.", irp->FileId); } else if (!disk_file_set_information(file, FsInformationClass, Length, irp->input)) { irp->IoStatus = STATUS_UNSUCCESSFUL; DEBUG_WARN("FsInformationClass %d on %s(%d) failed.", FsInformationClass, file->fullpath, file->id); } else { DEBUG_SVC("FsInformationClass %d on %s(%d) ok.", FsInformationClass, file->fullpath, file->id); } stream_write_uint32(irp->output, Length); irp->Complete(irp); } static void disk_process_irp_query_volume_information(DISK_DEVICE* disk, IRP* irp) { uint32 FsInformationClass; STREAM* output = irp->output; stream_read_uint32(irp->input, FsInformationClass); switch (FsInformationClass) { case FileFsVolumeInformation: /* http://msdn.microsoft.com/en-us/library/cc232108.aspx */ stream_write_uint32(output, 34); /* Length */ stream_check_size(output, 34); stream_write_uint64(output, 0); /* VolumeCreationTime */ stream_write_uint32(output, 0); /* VolumeSerialNumber */ stream_write_uint32(output, 16); /* VolumeLabelLength */ stream_write_uint8(output, 0); /* SupportsObjects */ stream_write_uint8(output, 0); /* Reserved */ stream_write(output, "F\0R\0E\0E\0R\0D\0P\0\0\0", 16); /* VolumeLabel (Unicode) */ break; case FileFsSizeInformation: /* http://msdn.microsoft.com/en-us/library/cc232107.aspx */ stream_write_uint32(output, 24); /* Length */ stream_check_size(output, 24); stream_write_uint64(output, 0x1000000); /* TotalAllocationUnits */ stream_write_uint64(output, 0x800000); /* AvailableAllocationUnits */ stream_write_uint32(output, 1); /* SectorsPerAllocationUnit */ stream_write_uint32(output, 0x400); /* BytesPerSector */ break; case FileFsAttributeInformation: /* http://msdn.microsoft.com/en-us/library/cc232101.aspx */ stream_write_uint32(output, 22); /* Length */ stream_check_size(output, 22); stream_write_uint32(output, FILE_CASE_SENSITIVE_SEARCH | FILE_CASE_PRESERVED_NAMES | FILE_UNICODE_ON_DISK); /* FileSystemAttributes */ stream_write_uint32(output, 510); /* MaximumComponentNameLength */ stream_write_uint32(output, 10); /* FileSystemNameLength */ stream_write(output, "F\0A\0T\03\02\0", 10); /* FileSystemName */ break; case FileFsFullSizeInformation: /* http://msdn.microsoft.com/en-us/library/cc232104.aspx */ stream_write_uint32(output, 32); /* Length */ stream_check_size(output, 32); stream_write_uint64(output, 0x1000000); /* TotalAllocationUnits */ stream_write_uint64(output, 0x800000); /* CallerAvailableAllocationUnits */ stream_write_uint64(output, 0x800000); /* ActualAvailableAllocationUnits */ stream_write_uint32(output, 1); /* SectorsPerAllocationUnit */ stream_write_uint32(output, 0x400); /* BytesPerSector */ break; case FileFsDeviceInformation: /* http://msdn.microsoft.com/en-us/library/cc232109.aspx */ stream_write_uint32(output, 8); /* Length */ stream_check_size(output, 8); stream_write_uint32(output, FILE_DEVICE_DISK); /* DeviceType */ stream_write_uint32(output, 0); /* Characteristics */ break; default: irp->IoStatus = STATUS_UNSUCCESSFUL; stream_write_uint32(output, 0); /* Length */ DEBUG_WARN("invalid FsInformationClass %d", FsInformationClass); break; } irp->Complete(irp); } static void disk_process_irp_query_directory(DISK_DEVICE* disk, IRP* irp) { DISK_FILE* file; uint32 FsInformationClass; uint8 InitialQuery; uint32 PathLength; UNICONV* uniconv; char* path; stream_read_uint32(irp->input, FsInformationClass); stream_read_uint8(irp->input, InitialQuery); stream_read_uint32(irp->input, PathLength); stream_seek(irp->input, 23); /* Padding */ uniconv = freerdp_uniconv_new(); path = freerdp_uniconv_in(uniconv, stream_get_tail(irp->input), PathLength); freerdp_uniconv_free(uniconv); file = disk_get_file_by_id(disk, irp->FileId); if (file == NULL) { irp->IoStatus = STATUS_UNSUCCESSFUL; stream_write_uint32(irp->output, 0); /* Length */ DEBUG_WARN("FileId %d not valid.", irp->FileId); } else if (!disk_file_query_directory(file, FsInformationClass, InitialQuery, path, irp->output)) { irp->IoStatus = STATUS_NO_MORE_FILES; } xfree(path); irp->Complete(irp); } static void disk_process_irp_directory_control(DISK_DEVICE* disk, IRP* irp) { switch (irp->MinorFunction) { case IRP_MN_QUERY_DIRECTORY: disk_process_irp_query_directory(disk, irp); break; case IRP_MN_NOTIFY_CHANGE_DIRECTORY: /* TODO */ irp->Discard(irp); break; default: DEBUG_WARN("MinorFunction 0x%X not supported", irp->MinorFunction); irp->IoStatus = STATUS_NOT_SUPPORTED; stream_write_uint32(irp->output, 0); /* Length */ irp->Complete(irp); break; } } static void disk_process_irp_device_control(DISK_DEVICE* disk, IRP* irp) { stream_write_uint32(irp->output, 0); /* OutputBufferLength */ irp->Complete(irp); } static void disk_process_irp(DISK_DEVICE* disk, IRP* irp) { switch (irp->MajorFunction) { case IRP_MJ_CREATE: disk_process_irp_create(disk, irp); break; case IRP_MJ_CLOSE: disk_process_irp_close(disk, irp); break; case IRP_MJ_READ: disk_process_irp_read(disk, irp); break; case IRP_MJ_WRITE: disk_process_irp_write(disk, irp); break; case IRP_MJ_QUERY_INFORMATION: disk_process_irp_query_information(disk, irp); break; case IRP_MJ_SET_INFORMATION: disk_process_irp_set_information(disk, irp); break; case IRP_MJ_QUERY_VOLUME_INFORMATION: disk_process_irp_query_volume_information(disk, irp); break; case IRP_MJ_DIRECTORY_CONTROL: disk_process_irp_directory_control(disk, irp); break; case IRP_MJ_DEVICE_CONTROL: disk_process_irp_device_control(disk, irp); break; default: DEBUG_WARN("MajorFunction 0x%X not supported", irp->MajorFunction); irp->IoStatus = STATUS_NOT_SUPPORTED; irp->Complete(irp); break; } } static void disk_process_irp_list(DISK_DEVICE* disk) { IRP* irp; while (1) { if (freerdp_thread_is_stopped(disk->thread)) break; freerdp_thread_lock(disk->thread); irp = (IRP*)list_dequeue(disk->irp_list); freerdp_thread_unlock(disk->thread); if (irp == NULL) break; disk_process_irp(disk, irp); } } static void* disk_thread_func(void* arg) { DISK_DEVICE* disk = (DISK_DEVICE*)arg; while (1) { freerdp_thread_wait(disk->thread); if (freerdp_thread_is_stopped(disk->thread)) break; freerdp_thread_reset(disk->thread); disk_process_irp_list(disk); } freerdp_thread_quit(disk->thread); return NULL; } static void disk_irp_request(DEVICE* device, IRP* irp) { DISK_DEVICE* disk = (DISK_DEVICE*)device; freerdp_thread_lock(disk->thread); list_enqueue(disk->irp_list, irp); freerdp_thread_unlock(disk->thread); freerdp_thread_signal(disk->thread); } static void disk_free(DEVICE* device) { DISK_DEVICE* disk = (DISK_DEVICE*)device; IRP* irp; DISK_FILE* file; freerdp_thread_stop(disk->thread); freerdp_thread_free(disk->thread); while ((irp = (IRP*)list_dequeue(disk->irp_list)) != NULL) irp->Discard(irp); list_free(disk->irp_list); while ((file = (DISK_FILE*)list_dequeue(disk->files)) != NULL) disk_file_free(file); list_free(disk->files); xfree(disk); } int DeviceServiceEntry(PDEVICE_SERVICE_ENTRY_POINTS pEntryPoints) { DISK_DEVICE* disk; char* name; char* path; int i, len; name = (char*)pEntryPoints->plugin_data->data[1]; path = (char*)pEntryPoints->plugin_data->data[2]; if (name && name[0] && path && path[0]) { disk = xnew(DISK_DEVICE); disk->device.type = RDPDR_DTYP_FILESYSTEM; disk->device.name = name; disk->device.IRPRequest = disk_irp_request; disk->device.Free = disk_free; len = strlen(name); disk->device.data = stream_new(len + 1); for (i = 0; i <= len; i++) stream_write_uint8(disk->device.data, name[i] < 0 ? '_' : name[i]); disk->path = path; disk->files = list_new(); disk->irp_list = list_new(); disk->thread = freerdp_thread_new(); pEntryPoints->RegisterDevice(pEntryPoints->devman, (DEVICE*)disk); freerdp_thread_start(disk->thread, disk_thread_func, disk); } return 0; } FreeRDP-1.0.2/channels/rdpdr/irp.c000066400000000000000000000052711207112532300166060ustar00rootroot00000000000000/** * FreeRDP: A Remote Desktop Protocol client. * File System Virtual Channel * * Copyright 2010-2011 Marc-Andre Moreau * Copyright 2010-2011 Vic Lee * * 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. */ #include "config.h" #include #include #include #include #include #include #include "rdpdr_types.h" #include "rdpdr_constants.h" #include "devman.h" #include "irp.h" static void irp_free(IRP* irp) { DEBUG_SVC("DeviceId %d FileId %d CompletionId %d", irp->device->id, irp->FileId, irp->CompletionId); stream_free(irp->input); stream_free(irp->output); xfree(irp); } static void irp_complete(IRP* irp) { int pos; DEBUG_SVC("DeviceId %d FileId %d CompletionId %d", irp->device->id, irp->FileId, irp->CompletionId); pos = stream_get_pos(irp->output); stream_set_pos(irp->output, 12); stream_write_uint32(irp->output, irp->IoStatus); stream_set_pos(irp->output, pos); svc_plugin_send(irp->devman->plugin, irp->output); irp->output = NULL; irp_free(irp); } IRP* irp_new(DEVMAN* devman, STREAM* data_in) { IRP* irp; uint32 DeviceId; DEVICE* device; stream_read_uint32(data_in, DeviceId); device = devman_get_device_by_id(devman, DeviceId); if (device == NULL) { DEBUG_WARN("unknown DeviceId %d", DeviceId); return NULL; } irp = xnew(IRP); irp->device = device; irp->devman = devman; stream_read_uint32(data_in, irp->FileId); stream_read_uint32(data_in, irp->CompletionId); stream_read_uint32(data_in, irp->MajorFunction); stream_read_uint32(data_in, irp->MinorFunction); irp->input = data_in; irp->output = stream_new(256); stream_write_uint16(irp->output, RDPDR_CTYP_CORE); stream_write_uint16(irp->output, PAKID_CORE_DEVICE_IOCOMPLETION); stream_write_uint32(irp->output, DeviceId); stream_write_uint32(irp->output, irp->CompletionId); stream_seek_uint32(irp->output); /* IoStatus */ irp->Complete = irp_complete; irp->Discard = irp_free; DEBUG_SVC("DeviceId %d FileId %d CompletionId %d MajorFunction 0x%X MinorFunction 0x%x", irp->device->id, irp->FileId, irp->CompletionId, irp->MajorFunction, irp->MinorFunction); return irp; } FreeRDP-1.0.2/channels/rdpdr/irp.h000066400000000000000000000015541207112532300166130ustar00rootroot00000000000000/** * FreeRDP: A Remote Desktop Protocol client. * File System Virtual Channel * * Copyright 2010-2011 Marc-Andre Moreau * Copyright 2010-2011 Vic Lee * * 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. */ #ifndef __IRP_H #define __IRP_H #include "rdpdr_types.h" IRP* irp_new(DEVMAN* devman, STREAM* data_in); #endif /* __IRP_H */ FreeRDP-1.0.2/channels/rdpdr/parallel/000077500000000000000000000000001207112532300174375ustar00rootroot00000000000000FreeRDP-1.0.2/channels/rdpdr/parallel/CMakeLists.txt000066400000000000000000000020361207112532300222000ustar00rootroot00000000000000# FreeRDP: A Remote Desktop Protocol Client # FreeRDP cmake build script # # Copyright 2011 O.S. Systems Software Ltda. # Copyright 2011 Otavio Salvador # Copyright 2011 Marc-Andre Moreau # # 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(PARALLEL_SRCS parallel_main.c ) include_directories(..) add_library(parallel ${PARALLEL_SRCS}) set_target_properties(parallel PROPERTIES PREFIX "") target_link_libraries(parallel freerdp-utils) install(TARGETS parallel DESTINATION ${FREERDP_PLUGIN_PATH}) FreeRDP-1.0.2/channels/rdpdr/parallel/parallel_main.c000066400000000000000000000170341207112532300224100ustar00rootroot00000000000000/** * FreeRDP: A Remote Desktop Protocol client. * Redirected Parallel Port Device Service * * Copyright 2010 O.S. Systems Software Ltda. * Copyright 2010 Eduardo Fiss Beloni * * 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. */ #include #include #include #include #include #include #include #include #include #ifdef __LINUX__ #include #include #endif #include #include #include #include #include #include #include #include "rdpdr_constants.h" #include "rdpdr_types.h" struct _PARALLEL_DEVICE { DEVICE device; int file; char* path; uint32 id; LIST* irp_list; freerdp_thread* thread; }; typedef struct _PARALLEL_DEVICE PARALLEL_DEVICE; static void parallel_process_irp_create(PARALLEL_DEVICE* parallel, IRP* irp) { uint32 PathLength; char* path; UNICONV* uniconv; stream_seek(irp->input, 28); /* DesiredAccess(4) AllocationSize(8), FileAttributes(4) */ /* SharedAccess(4) CreateDisposition(4), CreateOptions(4) */ stream_read_uint32(irp->input, PathLength); uniconv = freerdp_uniconv_new(); path = freerdp_uniconv_in(uniconv, stream_get_tail(irp->input), PathLength); freerdp_uniconv_free(uniconv); parallel->id = irp->devman->id_sequence++; parallel->file = open(parallel->path, O_RDWR); if (parallel->file < 0) { irp->IoStatus = STATUS_ACCESS_DENIED; parallel->id = 0; DEBUG_WARN("failed to create %s: %s", parallel->path, strerror(errno)); } else { /* all read and write operations should be non-blocking */ if (fcntl(parallel->file, F_SETFL, O_NONBLOCK) == -1) DEBUG_WARN("%s fcntl %s", path, strerror(errno)); DEBUG_SVC("%s(%d) created", parallel->path, parallel->file); } stream_write_uint32(irp->output, parallel->id); stream_write_uint8(irp->output, 0); xfree(path); irp->Complete(irp); } static void parallel_process_irp_close(PARALLEL_DEVICE* parallel, IRP* irp) { if (close(parallel->file) < 0) DEBUG_SVC("failed to close %s(%d)", parallel->path, parallel->id); else DEBUG_SVC("%s(%d) closed", parallel->path, parallel->id); stream_write_zero(irp->output, 5); /* Padding(5) */ irp->Complete(irp); } static void parallel_process_irp_read(PARALLEL_DEVICE* parallel, IRP* irp) { uint32 Length; uint64 Offset; ssize_t status; uint8* buffer = NULL; stream_read_uint32(irp->input, Length); stream_read_uint64(irp->input, Offset); buffer = (uint8*) xmalloc(Length); status = read(parallel->file, irp->output->p, Length); if (status < 0) { irp->IoStatus = STATUS_UNSUCCESSFUL; xfree(buffer); buffer = NULL; Length = 0; DEBUG_WARN("read %s(%d) failed", parallel->path, parallel->id); } else { DEBUG_SVC("read %llu-%llu from %d", Offset, Offset + Length, parallel->id); } stream_write_uint32(irp->output, Length); if (Length > 0) { stream_check_size(irp->output, Length); stream_write(irp->output, buffer, Length); } xfree(buffer); irp->Complete(irp); } static void parallel_process_irp_write(PARALLEL_DEVICE* parallel, IRP* irp) { uint32 Length; uint64 Offset; ssize_t status; uint32 len; stream_read_uint32(irp->input, Length); stream_read_uint64(irp->input, Offset); stream_seek(irp->input, 20); /* Padding */ DEBUG_SVC("Length %u Offset %llu", Length, Offset); len = Length; while (len > 0) { status = write(parallel->file, stream_get_tail(irp->input), len); if (status < 0) { irp->IoStatus = STATUS_UNSUCCESSFUL; Length = 0; DEBUG_WARN("write %s(%d) failed.", parallel->path, parallel->id); break; } stream_seek(irp->input, status); len -= status; } stream_write_uint32(irp->output, Length); stream_write_uint8(irp->output, 0); /* Padding */ irp->Complete(irp); } static void parallel_process_irp_device_control(PARALLEL_DEVICE* parallel, IRP* irp) { DEBUG_SVC("in"); stream_write_uint32(irp->output, 0); /* OutputBufferLength */ irp->Complete(irp); } static void parallel_process_irp(PARALLEL_DEVICE* parallel, IRP* irp) { DEBUG_SVC("MajorFunction %u", irp->MajorFunction); switch (irp->MajorFunction) { case IRP_MJ_CREATE: parallel_process_irp_create(parallel, irp); break; case IRP_MJ_CLOSE: parallel_process_irp_close(parallel, irp); break; case IRP_MJ_READ: parallel_process_irp_read(parallel, irp); break; case IRP_MJ_WRITE: parallel_process_irp_write(parallel, irp); break; case IRP_MJ_DEVICE_CONTROL: parallel_process_irp_device_control(parallel, irp); break; default: DEBUG_WARN("MajorFunction 0x%X not supported", irp->MajorFunction); irp->IoStatus = STATUS_NOT_SUPPORTED; irp->Complete(irp); break; } } static void parallel_process_irp_list(PARALLEL_DEVICE* parallel) { IRP* irp; while (1) { if (freerdp_thread_is_stopped(parallel->thread)) break; freerdp_thread_lock(parallel->thread); irp = (IRP*) list_dequeue(parallel->irp_list); freerdp_thread_unlock(parallel->thread); if (irp == NULL) break; parallel_process_irp(parallel, irp); } } static void* parallel_thread_func(void* arg) { PARALLEL_DEVICE* parallel = (PARALLEL_DEVICE*) arg; while (1) { freerdp_thread_wait(parallel->thread); if (freerdp_thread_is_stopped(parallel->thread)) break; freerdp_thread_reset(parallel->thread); parallel_process_irp_list(parallel); } freerdp_thread_quit(parallel->thread); return NULL; } static void parallel_irp_request(DEVICE* device, IRP* irp) { PARALLEL_DEVICE* parallel = (PARALLEL_DEVICE*) device; freerdp_thread_lock(parallel->thread); list_enqueue(parallel->irp_list, irp); freerdp_thread_unlock(parallel->thread); freerdp_thread_signal(parallel->thread); } static void parallel_free(DEVICE* device) { IRP* irp; PARALLEL_DEVICE* parallel = (PARALLEL_DEVICE*) device; DEBUG_SVC("freeing device"); freerdp_thread_stop(parallel->thread); freerdp_thread_free(parallel->thread); while ((irp = (IRP*) list_dequeue(parallel->irp_list)) != NULL) irp->Discard(irp); list_free(parallel->irp_list); xfree(parallel); } int DeviceServiceEntry(PDEVICE_SERVICE_ENTRY_POINTS pEntryPoints) { char* name; char* path; int i, length; PARALLEL_DEVICE* parallel; name = (char*) pEntryPoints->plugin_data->data[1]; path = (char*) pEntryPoints->plugin_data->data[2]; if (name[0] && path[0]) { parallel = xnew(PARALLEL_DEVICE); parallel->device.type = RDPDR_DTYP_PARALLEL; parallel->device.name = name; parallel->device.IRPRequest = parallel_irp_request; parallel->device.Free = parallel_free; length = strlen(name); parallel->device.data = stream_new(length + 1); for (i = 0; i <= length; i++) stream_write_uint8(parallel->device.data, name[i] < 0 ? '_' : name[i]); parallel->path = path; parallel->irp_list = list_new(); parallel->thread = freerdp_thread_new(); pEntryPoints->RegisterDevice(pEntryPoints->devman, (DEVICE*) parallel); freerdp_thread_start(parallel->thread, parallel_thread_func, parallel); } return 0; } FreeRDP-1.0.2/channels/rdpdr/printer/000077500000000000000000000000001207112532300173265ustar00rootroot00000000000000FreeRDP-1.0.2/channels/rdpdr/printer/CMakeLists.txt000066400000000000000000000024301207112532300220650ustar00rootroot00000000000000# FreeRDP: A Remote Desktop Protocol Client # FreeRDP cmake build script # # Copyright 2011 O.S. Systems Software Ltda. # Copyright 2011 Otavio Salvador # Copyright 2011 Marc-Andre Moreau # # 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(PRINTER_SRCS printer_main.c printer_main.h ) if(WITH_CUPS) set(PRINTER_SRCS ${PRINTER_SRCS} printer_cups.c printer_cups.h ) include_directories(${CUPS_INCLUDE_DIR}) add_definitions(-DWITH_CUPS) endif() include_directories(..) add_library(printer ${PRINTER_SRCS}) set_target_properties(printer PROPERTIES PREFIX "") target_link_libraries(printer freerdp-utils) if(WITH_CUPS) target_link_libraries(printer ${CUPS_LIBRARIES}) endif() install(TARGETS printer DESTINATION ${FREERDP_PLUGIN_PATH}) FreeRDP-1.0.2/channels/rdpdr/printer/printer_cups.c000066400000000000000000000160231207112532300222110ustar00rootroot00000000000000/** * FreeRDP: A Remote Desktop Protocol client. * Print Virtual Channel - CUPS driver * * Copyright 2010-2011 Vic Lee * * 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. */ #include #include #include #include #include #include #include #include #include "rdpdr_constants.h" #include "rdpdr_types.h" #include "printer_main.h" #include "printer_cups.h" typedef struct rdp_cups_printer_driver rdpCupsPrinterDriver; typedef struct rdp_cups_printer rdpCupsPrinter; typedef struct rdp_cups_print_job rdpCupsPrintJob; struct rdp_cups_printer_driver { rdpPrinterDriver driver; int id_sequence; }; struct rdp_cups_printer { rdpPrinter printer; rdpCupsPrintJob* printjob; }; struct rdp_cups_print_job { rdpPrintJob printjob; void* printjob_object; int printjob_id; }; static void printer_cups_get_printjob_name(char* buf, int size) { time_t tt; struct tm* t; tt = time(NULL); t = localtime(&tt); snprintf(buf, size - 1, "FreeRDP Print Job %d%02d%02d%02d%02d%02d", t->tm_year + 1900, t->tm_mon + 1, t->tm_mday, t->tm_hour, t->tm_min, t->tm_sec); } static void printer_cups_write_printjob(rdpPrintJob* printjob, uint8* data, int size) { rdpCupsPrintJob* cups_printjob = (rdpCupsPrintJob*)printjob; #ifndef _CUPS_API_1_4 { FILE* fp; fp = fopen((const char*)cups_printjob->printjob_object, "a+b"); if (fp == NULL) { DEBUG_WARN("failed to open file %s", (char*)cups_printjob->printjob_object); return; } if (fwrite(data, 1, size, fp) < size) { DEBUG_WARN("failed to write file %s", (char*)cups_printjob->printjob_object); } fclose(fp); } #else cupsWriteRequestData((http_t*)cups_printjob->printjob_object, (const char*)data, size); #endif } static void printer_cups_close_printjob(rdpPrintJob* printjob) { rdpCupsPrintJob* cups_printjob = (rdpCupsPrintJob*)printjob; #ifndef _CUPS_API_1_4 { char buf[100]; printer_cups_get_printjob_name(buf, sizeof(buf)); if (cupsPrintFile(printjob->printer->name, (const char *)cups_printjob->printjob_object, buf, 0, NULL) == 0) { DEBUG_WARN("cupsPrintFile: %s", cupsLastErrorString()); } unlink(cups_printjob->printjob_object); xfree(cups_printjob->printjob_object); } #else cupsFinishDocument((http_t*)cups_printjob->printjob_object, printjob->printer->name); cups_printjob->printjob_id = 0; httpClose((http_t*)cups_printjob->printjob_object); #endif xfree(cups_printjob); ((rdpCupsPrinter*)printjob->printer)->printjob = NULL; } static rdpPrintJob* printer_cups_create_printjob(rdpPrinter* printer, uint32 id) { rdpCupsPrinter* cups_printer = (rdpCupsPrinter*)printer; rdpCupsPrintJob* cups_printjob; if (cups_printer->printjob != NULL) return NULL; cups_printjob = xnew(rdpCupsPrintJob); cups_printjob->printjob.id = id; cups_printjob->printjob.printer = printer; cups_printjob->printjob.Write = printer_cups_write_printjob; cups_printjob->printjob.Close = printer_cups_close_printjob; #ifndef _CUPS_API_1_4 cups_printjob->printjob_object = xstrdup(tmpnam(NULL)); #else { char buf[100]; cups_printjob->printjob_object = httpConnectEncrypt(cupsServer(), ippPort(), HTTP_ENCRYPT_IF_REQUESTED); if (cups_printjob->printjob_object == NULL) { DEBUG_WARN("httpConnectEncrypt: %s", cupsLastErrorString()); xfree(cups_printjob); return NULL; } printer_cups_get_printjob_name(buf, sizeof(buf)); cups_printjob->printjob_id = cupsCreateJob((http_t*)cups_printjob->printjob_object, printer->name, buf, 0, NULL); if (cups_printjob->printjob_id == 0) { DEBUG_WARN("cupsCreateJob: %s", cupsLastErrorString()); httpClose((http_t*)cups_printjob->printjob_object); xfree(cups_printjob); return NULL; } cupsStartDocument((http_t*)cups_printjob->printjob_object, printer->name, cups_printjob->printjob_id, buf, CUPS_FORMAT_AUTO, 1); } #endif cups_printer->printjob = cups_printjob; return (rdpPrintJob*)cups_printjob; } static rdpPrintJob* printer_cups_find_printjob(rdpPrinter* printer, uint32 id) { rdpCupsPrinter* cups_printer = (rdpCupsPrinter*)printer; if (cups_printer->printjob == NULL) return NULL; if (cups_printer->printjob->printjob.id != id) return NULL; return (rdpPrintJob*)cups_printer->printjob; } static void printer_cups_free_printer(rdpPrinter* printer) { rdpCupsPrinter* cups_printer = (rdpCupsPrinter*)printer; if (cups_printer->printjob) cups_printer->printjob->printjob.Close((rdpPrintJob*)cups_printer->printjob); xfree(printer->name); xfree(printer); } static rdpPrinter* printer_cups_new_printer(rdpCupsPrinterDriver* cups_driver, const char* name, boolean is_default) { rdpCupsPrinter* cups_printer; cups_printer = xnew(rdpCupsPrinter); cups_printer->printer.id = cups_driver->id_sequence++; cups_printer->printer.name = xstrdup(name); /* This is a generic PostScript printer driver developed by MS, so it should be good in most cases */ cups_printer->printer.driver = "MS Publisher Imagesetter"; cups_printer->printer.is_default = is_default; cups_printer->printer.CreatePrintJob = printer_cups_create_printjob; cups_printer->printer.FindPrintJob = printer_cups_find_printjob; cups_printer->printer.Free = printer_cups_free_printer; return (rdpPrinter*)cups_printer; } static rdpPrinter** printer_cups_enum_printers(rdpPrinterDriver* driver) { rdpPrinter** printers; int num_printers; cups_dest_t *dests; cups_dest_t *dest; int num_dests; int i; num_dests = cupsGetDests(&dests); printers = (rdpPrinter**)xzalloc(sizeof(rdpPrinter*) * (num_dests + 1)); num_printers = 0; for (i = 0, dest = dests; i < num_dests; i++, dest++) { if (dest->instance == NULL) { printers[num_printers++] = printer_cups_new_printer((rdpCupsPrinterDriver*)driver, dest->name, dest->is_default); } } cupsFreeDests(num_dests, dests); return printers; } static rdpPrinter* printer_cups_get_printer(rdpPrinterDriver* driver, const char* name) { rdpCupsPrinterDriver* cups_driver = (rdpCupsPrinterDriver*)driver; return printer_cups_new_printer(cups_driver, name, cups_driver->id_sequence == 1 ? true : false); } static rdpCupsPrinterDriver* cups_driver = NULL; rdpPrinterDriver* printer_cups_get_driver(void) { if (cups_driver == NULL) { cups_driver = xnew(rdpCupsPrinterDriver); cups_driver->driver.EnumPrinters = printer_cups_enum_printers; cups_driver->driver.GetPrinter = printer_cups_get_printer; cups_driver->id_sequence = 1; #ifdef _CUPS_API_1_4 DEBUG_SVC("using CUPS API 1.4"); #else DEBUG_SVC("using CUPS API 1.2"); #endif } return (rdpPrinterDriver*)cups_driver; } FreeRDP-1.0.2/channels/rdpdr/printer/printer_cups.h000066400000000000000000000014661207112532300222230ustar00rootroot00000000000000/** * FreeRDP: A Remote Desktop Protocol client. * Print Virtual Channel - CUPS driver * * Copyright 2010-2011 Vic Lee * * 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. */ #ifndef __PRINTER_CUPS_H #define __PRINTER_CUPS_H #include "printer_main.h" rdpPrinterDriver* printer_cups_get_driver(void); #endif FreeRDP-1.0.2/channels/rdpdr/printer/printer_main.c000066400000000000000000000200111207112532300221530ustar00rootroot00000000000000/** * FreeRDP: A Remote Desktop Protocol client. * Print Virtual Channel * * Copyright 2010-2011 Vic Lee * * 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. */ #include "config.h" #include #include #include #include #include #include #include #include #include "rdpdr_constants.h" #include "rdpdr_types.h" #ifdef WITH_CUPS #include "printer_cups.h" #endif #include "printer_main.h" typedef struct _PRINTER_DEVICE PRINTER_DEVICE; struct _PRINTER_DEVICE { DEVICE device; rdpPrinter* printer; LIST* irp_list; freerdp_thread* thread; }; static void printer_process_irp_create(PRINTER_DEVICE* printer_dev, IRP* irp) { rdpPrintJob* printjob = NULL; if (printer_dev->printer != NULL) printjob = printer_dev->printer->CreatePrintJob(printer_dev->printer, irp->devman->id_sequence++); if (printjob != NULL) { stream_write_uint32(irp->output, printjob->id); /* FileId */ DEBUG_SVC("printjob id: %d", printjob->id); } else { stream_write_uint32(irp->output, 0); /* FileId */ irp->IoStatus = STATUS_PRINT_QUEUE_FULL; DEBUG_WARN("error creating print job."); } irp->Complete(irp); } static void printer_process_irp_close(PRINTER_DEVICE* printer_dev, IRP* irp) { rdpPrintJob* printjob = NULL; if (printer_dev->printer != NULL) printjob = printer_dev->printer->FindPrintJob(printer_dev->printer, irp->FileId); if (printjob == NULL) { irp->IoStatus = STATUS_UNSUCCESSFUL; DEBUG_WARN("printjob id %d not found.", irp->FileId); } else { printjob->Close(printjob); DEBUG_SVC("printjob id %d closed.", irp->FileId); } stream_write_zero(irp->output, 4); /* Padding(4) */ irp->Complete(irp); } static void printer_process_irp_write(PRINTER_DEVICE* printer_dev, IRP* irp) { rdpPrintJob* printjob = NULL; uint32 Length; uint64 Offset; stream_read_uint32(irp->input, Length); stream_read_uint64(irp->input, Offset); stream_seek(irp->input, 20); /* Padding */ if (printer_dev->printer != NULL) printjob = printer_dev->printer->FindPrintJob(printer_dev->printer, irp->FileId); if (printjob == NULL) { irp->IoStatus = STATUS_UNSUCCESSFUL; Length = 0; DEBUG_WARN("printjob id %d not found.", irp->FileId); } else { printjob->Write(printjob, stream_get_tail(irp->input), Length); DEBUG_SVC("printjob id %d written %d bytes.", irp->FileId, Length); } stream_write_uint32(irp->output, Length); stream_write_uint8(irp->output, 0); /* Padding */ irp->Complete(irp); } static void printer_process_irp(PRINTER_DEVICE* printer_dev, IRP* irp) { switch (irp->MajorFunction) { case IRP_MJ_CREATE: printer_process_irp_create(printer_dev, irp); break; case IRP_MJ_CLOSE: printer_process_irp_close(printer_dev, irp); break; case IRP_MJ_WRITE: printer_process_irp_write(printer_dev, irp); break; default: DEBUG_WARN("MajorFunction 0x%X not supported", irp->MajorFunction); irp->IoStatus = STATUS_NOT_SUPPORTED; irp->Complete(irp); break; } } static void printer_process_irp_list(PRINTER_DEVICE* printer_dev) { IRP* irp; while (1) { if (freerdp_thread_is_stopped(printer_dev->thread)) break; freerdp_thread_lock(printer_dev->thread); irp = (IRP*)list_dequeue(printer_dev->irp_list); freerdp_thread_unlock(printer_dev->thread); if (irp == NULL) break; printer_process_irp(printer_dev, irp); } } static void* printer_thread_func(void* arg) { PRINTER_DEVICE* printer_dev = (PRINTER_DEVICE*)arg; while (1) { freerdp_thread_wait(printer_dev->thread); if (freerdp_thread_is_stopped(printer_dev->thread)) break; freerdp_thread_reset(printer_dev->thread); printer_process_irp_list(printer_dev); } freerdp_thread_quit(printer_dev->thread); return NULL; } static void printer_irp_request(DEVICE* device, IRP* irp) { PRINTER_DEVICE* printer_dev = (PRINTER_DEVICE*)device; freerdp_thread_lock(printer_dev->thread); list_enqueue(printer_dev->irp_list, irp); freerdp_thread_unlock(printer_dev->thread); freerdp_thread_signal(printer_dev->thread); } static void printer_free(DEVICE* device) { PRINTER_DEVICE* printer_dev = (PRINTER_DEVICE*)device; IRP* irp; freerdp_thread_stop(printer_dev->thread); freerdp_thread_free(printer_dev->thread); while ((irp = (IRP*)list_dequeue(printer_dev->irp_list)) != NULL) irp->Discard(irp); list_free(printer_dev->irp_list); if (printer_dev->printer) printer_dev->printer->Free(printer_dev->printer); xfree(printer_dev->device.name); xfree(printer_dev); } void printer_register(PDEVICE_SERVICE_ENTRY_POINTS pEntryPoints, rdpPrinter* printer) { PRINTER_DEVICE* printer_dev; char* port; UNICONV* uniconv; uint32 Flags; size_t DriverNameLen; char* DriverName; size_t PrintNameLen; char* PrintName; uint32 CachedFieldsLen; uint8* CachedPrinterConfigData; port = xmalloc(10); snprintf(port, 10, "PRN%d", printer->id); printer_dev = xnew(PRINTER_DEVICE); printer_dev->device.type = RDPDR_DTYP_PRINT; printer_dev->device.name = port; printer_dev->device.IRPRequest = printer_irp_request; printer_dev->device.Free = printer_free; printer_dev->printer = printer; CachedFieldsLen = 0; CachedPrinterConfigData = NULL; DEBUG_SVC("Printer %s registered", printer->name); Flags = 0; if (printer->is_default) Flags |= RDPDR_PRINTER_ANNOUNCE_FLAG_DEFAULTPRINTER; uniconv = freerdp_uniconv_new(); DriverName = freerdp_uniconv_out(uniconv, printer->driver, &DriverNameLen); PrintName = freerdp_uniconv_out(uniconv, printer->name, &PrintNameLen); freerdp_uniconv_free(uniconv); printer_dev->device.data = stream_new(28 + DriverNameLen + PrintNameLen + CachedFieldsLen); stream_write_uint32(printer_dev->device.data, Flags); stream_write_uint32(printer_dev->device.data, 0); /* CodePage, reserved */ stream_write_uint32(printer_dev->device.data, 0); /* PnPNameLen */ stream_write_uint32(printer_dev->device.data, DriverNameLen + 2); stream_write_uint32(printer_dev->device.data, PrintNameLen + 2); stream_write_uint32(printer_dev->device.data, CachedFieldsLen); stream_write(printer_dev->device.data, DriverName, DriverNameLen); stream_write_uint16(printer_dev->device.data, 0); stream_write(printer_dev->device.data, PrintName, PrintNameLen); stream_write_uint16(printer_dev->device.data, 0); if (CachedFieldsLen > 0) { stream_write(printer_dev->device.data, CachedPrinterConfigData, CachedFieldsLen); } xfree(DriverName); xfree(PrintName); printer_dev->irp_list = list_new(); printer_dev->thread = freerdp_thread_new(); pEntryPoints->RegisterDevice(pEntryPoints->devman, (DEVICE*)printer_dev); freerdp_thread_start(printer_dev->thread, printer_thread_func, printer_dev); } int DeviceServiceEntry(PDEVICE_SERVICE_ENTRY_POINTS pEntryPoints) { rdpPrinterDriver* driver = NULL; rdpPrinter** printers; rdpPrinter* printer; int i; char* name; char* driver_name; #ifdef WITH_CUPS driver = printer_cups_get_driver(); #endif if (driver == NULL) { DEBUG_WARN("no driver."); return 1; } name = (char*)pEntryPoints->plugin_data->data[1]; driver_name = (char*)pEntryPoints->plugin_data->data[2]; if (name && name[0]) { printer = driver->GetPrinter(driver, name); if (printer == NULL) { DEBUG_WARN("printer %s not found.", name); return 1; } if (driver_name && driver_name[0]) printer->driver = driver_name; printer_register(pEntryPoints, printer); } else { printers = driver->EnumPrinters(driver); for (i = 0; printers[i]; i++) { printer = printers[i]; printer_register(pEntryPoints, printer); } xfree(printers); } return 0; } FreeRDP-1.0.2/channels/rdpdr/printer/printer_main.h000066400000000000000000000044721207112532300221750ustar00rootroot00000000000000/** * FreeRDP: A Remote Desktop Protocol client. * Print Virtual Channel * * Copyright 2010-2011 Vic Lee * * 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. */ #ifndef __PRINTER_MAIN_H #define __PRINTER_MAIN_H #include "rdpdr_types.h" /* SERVER_PRINTER_CACHE_EVENT.cachedata */ #define RDPDR_ADD_PRINTER_EVENT 0x00000001 #define RDPDR_UPDATE_PRINTER_EVENT 0x00000002 #define RDPDR_DELETE_PRINTER_EVENT 0x00000003 #define RDPDR_RENAME_PRINTER_EVENT 0x00000004 /* DR_PRN_DEVICE_ANNOUNCE.Flags */ #define RDPDR_PRINTER_ANNOUNCE_FLAG_ASCII 0x00000001 #define RDPDR_PRINTER_ANNOUNCE_FLAG_DEFAULTPRINTER 0x00000002 #define RDPDR_PRINTER_ANNOUNCE_FLAG_NETWORKPRINTER 0x00000004 #define RDPDR_PRINTER_ANNOUNCE_FLAG_TSPRINTER 0x00000008 #define RDPDR_PRINTER_ANNOUNCE_FLAG_XPSFORMAT 0x00000010 typedef struct rdp_printer_driver rdpPrinterDriver; typedef struct rdp_printer rdpPrinter; typedef struct rdp_print_job rdpPrintJob; typedef rdpPrinter** (*pcEnumPrinters) (rdpPrinterDriver* driver); typedef rdpPrinter* (*pcGetPrinter) (rdpPrinterDriver* driver, const char* name); struct rdp_printer_driver { pcEnumPrinters EnumPrinters; pcGetPrinter GetPrinter; }; typedef rdpPrintJob* (*pcCreatePrintJob) (rdpPrinter* printer, uint32 id); typedef rdpPrintJob* (*pcFindPrintJob) (rdpPrinter* printer, uint32 id); typedef void (*pcFreePrinter) (rdpPrinter* printer); struct rdp_printer { int id; char* name; char* driver; boolean is_default; pcCreatePrintJob CreatePrintJob; pcFindPrintJob FindPrintJob; pcFreePrinter Free; }; typedef void (*pcWritePrintJob) (rdpPrintJob* printjob, uint8* data, int size); typedef void (*pcClosePrintJob) (rdpPrintJob* printjob); struct rdp_print_job { uint32 id; rdpPrinter* printer; pcWritePrintJob Write; pcClosePrintJob Close; }; #endif FreeRDP-1.0.2/channels/rdpdr/rdpdr_capabilities.c000066400000000000000000000136121207112532300216360ustar00rootroot00000000000000/** * FreeRDP: A Remote Desktop Protocol client. * File System Virtual Channel * * Copyright 2010-2011 Marc-Andre Moreau * Copyright 2010-2011 Vic Lee * * 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. */ #include "config.h" #include #include #include #include #include #include "rdpdr_types.h" #include "rdpdr_constants.h" #include "rdpdr_capabilities.h" /* Output device redirection capability set header */ static void rdpdr_write_capset_header(STREAM* data_out, uint16 capabilityType, uint16 capabilityLength, uint32 version) { stream_write_uint16(data_out, capabilityType); stream_write_uint16(data_out, capabilityLength); stream_write_uint32(data_out, version); } /* Output device direction general capability set */ static void rdpdr_write_general_capset(rdpdrPlugin* rdpdr, STREAM* data_out) { rdpdr_write_capset_header(data_out, CAP_GENERAL_TYPE, 44, GENERAL_CAPABILITY_VERSION_02); stream_write_uint32(data_out, 0); /* osType, ignored on receipt */ stream_write_uint32(data_out, 0); /* osVersion, unused and must be set to zero */ stream_write_uint16(data_out, 1); /* protocolMajorVersion, must be set to 1 */ stream_write_uint16(data_out, RDPDR_MINOR_RDP_VERSION_5_2); /* protocolMinorVersion */ stream_write_uint32(data_out, 0x0000FFFF); /* ioCode1 */ stream_write_uint32(data_out, 0); /* ioCode2, must be set to zero, reserved for future use */ stream_write_uint32(data_out, RDPDR_DEVICE_REMOVE_PDUS | RDPDR_CLIENT_DISPLAY_NAME_PDU | RDPDR_USER_LOGGEDON_PDU); /* extendedPDU */ stream_write_uint32(data_out, ENABLE_ASYNCIO); /* extraFlags1 */ stream_write_uint32(data_out, 0); /* extraFlags2, must be set to zero, reserved for future use */ stream_write_uint32(data_out, 0); /* SpecialTypeDeviceCap, number of special devices to be redirected before logon */ } /* Process device direction general capability set */ static void rdpdr_process_general_capset(rdpdrPlugin* rdpdr, STREAM* data_in) { uint16 capabilityLength; stream_read_uint16(data_in, capabilityLength); stream_seek(data_in, capabilityLength - 4); } /* Output printer direction capability set */ static void rdpdr_write_printer_capset(rdpdrPlugin* rdpdr, STREAM* data_out) { rdpdr_write_capset_header(data_out, CAP_PRINTER_TYPE, 8, PRINT_CAPABILITY_VERSION_01); } /* Process printer direction capability set */ static void rdpdr_process_printer_capset(rdpdrPlugin* rdpdr, STREAM* data_in) { uint16 capabilityLength; stream_read_uint16(data_in, capabilityLength); stream_seek(data_in, capabilityLength - 4); } /* Output port redirection capability set */ static void rdpdr_write_port_capset(rdpdrPlugin* rdpdr, STREAM* data_out) { rdpdr_write_capset_header(data_out, CAP_PORT_TYPE, 8, PORT_CAPABILITY_VERSION_01); } /* Process port redirection capability set */ static void rdpdr_process_port_capset(rdpdrPlugin* rdpdr, STREAM* data_in) { uint16 capabilityLength; stream_read_uint16(data_in, capabilityLength); stream_seek(data_in, capabilityLength - 4); } /* Output drive redirection capability set */ static void rdpdr_write_drive_capset(rdpdrPlugin* rdpdr, STREAM* data_out) { rdpdr_write_capset_header(data_out, CAP_DRIVE_TYPE, 8, DRIVE_CAPABILITY_VERSION_02); } /* Process drive redirection capability set */ static void rdpdr_process_drive_capset(rdpdrPlugin* rdpdr, STREAM* data_in) { uint16 capabilityLength; stream_read_uint16(data_in, capabilityLength); stream_seek(data_in, capabilityLength - 4); } /* Output smart card redirection capability set */ static void rdpdr_write_smartcard_capset(rdpdrPlugin* rdpdr, STREAM* data_out) { rdpdr_write_capset_header(data_out, CAP_SMARTCARD_TYPE, 8, SMARTCARD_CAPABILITY_VERSION_01); } /* Process smartcard redirection capability set */ static void rdpdr_process_smartcard_capset(rdpdrPlugin* rdpdr, STREAM* data_in) { uint16 capabilityLength; stream_read_uint16(data_in, capabilityLength); stream_seek(data_in, capabilityLength - 4); } void rdpdr_process_capability_request(rdpdrPlugin* rdpdr, STREAM* data_in) { uint16 i; uint16 numCapabilities; uint16 capabilityType; stream_read_uint16(data_in, numCapabilities); stream_seek(data_in, 2); /* pad (2 bytes) */ for(i = 0; i < numCapabilities; i++) { stream_read_uint16(data_in, capabilityType); switch (capabilityType) { case CAP_GENERAL_TYPE: rdpdr_process_general_capset(rdpdr, data_in); break; case CAP_PRINTER_TYPE: rdpdr_process_printer_capset(rdpdr, data_in); break; case CAP_PORT_TYPE: rdpdr_process_port_capset(rdpdr, data_in); break; case CAP_DRIVE_TYPE: rdpdr_process_drive_capset(rdpdr, data_in); break; case CAP_SMARTCARD_TYPE: rdpdr_process_smartcard_capset(rdpdr, data_in); break; default: DEBUG_WARN("Unknown capabilityType %d", capabilityType); break; } } } void rdpdr_send_capability_response(rdpdrPlugin* rdpdr) { STREAM* data_out; data_out = stream_new(256); stream_write_uint16(data_out, RDPDR_CTYP_CORE); stream_write_uint16(data_out, PAKID_CORE_CLIENT_CAPABILITY); stream_write_uint16(data_out, 5); /* numCapabilities */ stream_write_uint16(data_out, 0); /* pad */ rdpdr_write_general_capset(rdpdr, data_out); rdpdr_write_printer_capset(rdpdr, data_out); rdpdr_write_port_capset(rdpdr, data_out); rdpdr_write_drive_capset(rdpdr, data_out); rdpdr_write_smartcard_capset(rdpdr, data_out); svc_plugin_send((rdpSvcPlugin*)rdpdr, data_out); } FreeRDP-1.0.2/channels/rdpdr/rdpdr_capabilities.h000066400000000000000000000017561207112532300216510ustar00rootroot00000000000000/** * FreeRDP: A Remote Desktop Protocol client. * File System Virtual Channel * * Copyright 2010-2011 Marc-Andre Moreau * Copyright 2010-2011 Vic Lee * * 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. */ #ifndef __RDPDR_CAPABILITIES_H #define __RDPDR_CAPABILITIES_H #include "rdpdr_main.h" void rdpdr_process_capability_request(rdpdrPlugin* rdpdr, STREAM* data_in); void rdpdr_send_capability_response(rdpdrPlugin* rdpdr); #endif /* __RDPDR_CAPABILITIES_H */ FreeRDP-1.0.2/channels/rdpdr/rdpdr_constants.h000066400000000000000000000310671207112532300212320ustar00rootroot00000000000000/** * FreeRDP: A Remote Desktop Protocol client. * File System Virtual Channel * * Copyright 2010-2011 Marc-Andre Moreau * Copyright 2010-2011 Vic Lee * * 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. */ #ifndef __RDPDR_CONSTANTS_H #define __RDPDR_CONSTANTS_H /* RDPDR_HEADER.Component */ enum RDPDR_CTYP { RDPDR_CTYP_CORE = 0x4472, RDPDR_CTYP_PRN = 0x5052 }; /* RDPDR_HEADER.PacketId */ enum RDPDR_PAKID { PAKID_CORE_SERVER_ANNOUNCE = 0x496E, PAKID_CORE_CLIENTID_CONFIRM = 0x4343, PAKID_CORE_CLIENT_NAME = 0x434E, PAKID_CORE_DEVICELIST_ANNOUNCE = 0x4441, PAKID_CORE_DEVICE_REPLY = 0x6472, PAKID_CORE_DEVICE_IOREQUEST = 0x4952, PAKID_CORE_DEVICE_IOCOMPLETION = 0x4943, PAKID_CORE_SERVER_CAPABILITY = 0x5350, PAKID_CORE_CLIENT_CAPABILITY = 0x4350, PAKID_CORE_DEVICELIST_REMOVE = 0x444D, PAKID_CORE_USER_LOGGEDON = 0x554C, PAKID_PRN_CACHE_DATA = 0x5043, PAKID_PRN_USING_XPS = 0x5543 }; /* CAPABILITY_HEADER.CapabilityType */ enum RDPDR_CAP_TYPE { CAP_GENERAL_TYPE = 0x0001, CAP_PRINTER_TYPE = 0x0002, CAP_PORT_TYPE = 0x0003, CAP_DRIVE_TYPE = 0x0004, CAP_SMARTCARD_TYPE = 0x0005 }; /* CAPABILITY_HEADER.Version */ enum RDPDR_CAP_VERSION { GENERAL_CAPABILITY_VERSION_01 = 0x00000001, GENERAL_CAPABILITY_VERSION_02 = 0x00000002, PRINT_CAPABILITY_VERSION_01 = 0x00000001, PORT_CAPABILITY_VERSION_01 = 0x00000001, DRIVE_CAPABILITY_VERSION_01 = 0x00000001, DRIVE_CAPABILITY_VERSION_02 = 0x00000002, SMARTCARD_CAPABILITY_VERSION_01 = 0x00000001 }; /* DEVICE_ANNOUNCE.DeviceType */ enum RDPDR_DTYP { RDPDR_DTYP_SERIAL = 0x00000001, RDPDR_DTYP_PARALLEL = 0x00000002, RDPDR_DTYP_PRINT = 0x00000004, RDPDR_DTYP_FILESYSTEM = 0x00000008, RDPDR_DTYP_SMARTCARD = 0x00000020 }; /* DR_DEVICE_IOREQUEST.MajorFunction */ enum IRP_MJ { IRP_MJ_CREATE = 0x00000000, IRP_MJ_CLOSE = 0x00000002, IRP_MJ_READ = 0x00000003, IRP_MJ_WRITE = 0x00000004, IRP_MJ_DEVICE_CONTROL = 0x0000000E, IRP_MJ_QUERY_VOLUME_INFORMATION = 0x0000000A, IRP_MJ_SET_VOLUME_INFORMATION = 0x0000000B, IRP_MJ_QUERY_INFORMATION = 0x00000005, IRP_MJ_SET_INFORMATION = 0x00000006, IRP_MJ_DIRECTORY_CONTROL = 0x0000000C, IRP_MJ_LOCK_CONTROL = 0x00000011 }; /* DR_DEVICE_IOREQUEST.MinorFunction */ enum IRP_MN { IRP_MN_QUERY_DIRECTORY = 0x00000001, IRP_MN_NOTIFY_CHANGE_DIRECTORY = 0x00000002 }; /* DR_CREATE_REQ.CreateDisposition */ enum FILE_CREATE_DISPOSITION { FILE_SUPERSEDE = 0x00000000, FILE_OPEN = 0x00000001, FILE_CREATE = 0x00000002, FILE_OPEN_IF = 0x00000003, FILE_OVERWRITE = 0x00000004, FILE_OVERWRITE_IF = 0x00000005 }; /* DR_CREATE_REQ.CreateOptions [MS-SMB2] */ enum FILE_CREATE_OPTION { FILE_DIRECTORY_FILE = 0x00000001, FILE_NON_DIRECTORY_FILE = 0x00000040, FILE_COMPLETE_IF_OPLOCKED = 0x00000100, FILE_DELETE_ON_CLOSE = 0x00001000, FILE_OPEN_REPARSE_POINT = 0x00200000, FILE_OPEN_FOR_FREE_SPACE_QUERY = 0x00800000 }; /* DR_CREATE_REQ.DesiredAccess [MS-SMB2] */ enum FILE_ACCESS { FILE_READ_DATA = 0x00000001, FILE_WRITE_DATA = 0x00000002, FILE_APPEND_DATA = 0x00000004, FILE_READ_EA = 0x00000008, FILE_WRITE_EA = 0x00000010, FILE_EXECUTE = 0x00000020, FILE_READ_ATTRIBUTES = 0x00000080, FILE_WRITE_ATTRIBUTES = 0x00000100, DELETE = 0x00010000, READ_CONTROL = 0x00020000, WRITE_DAC = 0x00040000, WRITE_OWNER = 0x00080000, SYNCHRONIZE = 0x00100000, ACCESS_SYSTEM_SECURITY = 0x01000000, MAXIMUM_ALLOWED = 0x02000000, GENERIC_ALL = 0x10000000, GENERIC_EXECUTE = 0x20000000, GENERIC_WRITE = 0x40000000, GENERIC_READ = 0x80000000 }; /* DR_CREATE_RSP.Information */ /* DR_DRIVE_CREATE_RSP.DeviceCreateResponse */ enum FILE_RESPONSE { FILE_SUPERSEDED = 0x00000000, FILE_OPENED = 0x00000001, FILE_OVERWRITTEN = 0x00000003 }; /* DR_CORE_CLIENT_ANNOUNCE_RSP.VersionMinor */ enum RDPDR_MINOR_RDP_VERSION { RDPDR_MINOR_RDP_VERSION_5_0 = 0x0002, RDPDR_MINOR_RDP_VERSION_5_1 = 0x0005, RDPDR_MINOR_RDP_VERSION_5_2 = 0x000A, RDPDR_MINOR_RDP_VERSION_6_X = 0x000C }; /* DR_CORE_CLIENT_NAME_REQ.UnicodeFlag */ enum RDPDR_CLIENT_NAME_FLAG { RDPDR_CLIENT_NAME_UNICODE = 0x00000001, RDPDR_CLIENT_NAME_ASCII = 0x00000000 }; /* GENERAL_CAPS_SET.ioCode1 */ enum RDPDR_CAPS_IRP_MJ { RDPDR_IRP_MJ_CREATE = 0x00000001, RDPDR_IRP_MJ_CLEANUP = 0x00000002, RDPDR_IRP_MJ_CLOSE = 0x00000004, RDPDR_IRP_MJ_READ = 0x00000008, RDPDR_IRP_MJ_WRITE = 0x00000010, RDPDR_IRP_MJ_FLUSH_BUFFERS = 0x00000020, RDPDR_IRP_MJ_SHUTDOWN = 0x00000040, RDPDR_IRP_MJ_DEVICE_CONTROL = 0x00000080, RDPDR_IRP_MJ_QUERY_VOLUME_INFORMATION = 0x00000100, RDPDR_IRP_MJ_SET_VOLUME_INFORMATION = 0x00000200, RDPDR_IRP_MJ_QUERY_INFORMATION = 0x00000400, RDPDR_IRP_MJ_SET_INFORMATION = 0x00000800, RDPDR_IRP_MJ_DIRECTORY_CONTROL = 0x00001000, RDPDR_IRP_MJ_LOCK_CONTROL = 0x00002000, RDPDR_IRP_MJ_QUERY_SECURITY = 0x00004000, RDPDR_IRP_MJ_SET_SECURITY = 0x00008000 }; /* GENERAL_CAPS_SET.extendedPDU */ enum RDPDR_CAPS_PDU { RDPDR_DEVICE_REMOVE_PDUS = 0x00000001, RDPDR_CLIENT_DISPLAY_NAME_PDU = 0x00000002, RDPDR_USER_LOGGEDON_PDU = 0x00000004 }; /* GENERAL_CAPS_SET.extraFlags1 */ enum RDPDR_CAPS_FLAG { ENABLE_ASYNCIO = 0x00000001 }; /* DR_DRIVE_LOCK_REQ.Operation */ enum RDP_LOWIO_OP { RDP_LOWIO_OP_SHAREDLOCK = 0x00000002, RDP_LOWIO_OP_EXCLUSIVELOCK = 0x00000003, RDP_LOWIO_OP_UNLOCK = 0x00000004, RDP_LOWIO_OP_UNLOCK_MULTIPLE = 0x00000005 }; /* NTSTATUS values */ /* http://msdn.microsoft.com/en-us/library/cc704588.aspx */ enum NTSTATUS { STATUS_SUCCESS = 0x00000000, STATUS_TIMEOUT = 0x00000102, STATUS_PENDING = 0x00000103, STATUS_REPARSE = 0x00000104, STATUS_MORE_ENTRIES = 0x00000105, STATUS_NOT_ALL_ASSIGNED = 0x00000106, STATUS_OPLOCK_BREAK_IN_PROGRESS = 0x00000108, STATUS_VOLUME_MOUNTED = 0x00000109, STATUS_NOTIFY_CLEANUP = 0x0000010B, STATUS_NOTIFY_ENUM_DIR = 0x0000010C, STATUS_NO_QUOTAS_FOR_ACCOUNT = 0x0000010D, STATUS_FILE_LOCKED_WITH_ONLY_READERS = 0x0000012A, STATUS_FILE_LOCKED_WITH_WRITERS = 0x0000012B, STATUS_WAIT_FOR_OPLOCK = 0x00000367, STATUS_OBJECT_NAME_EXISTS = 0x40000000, STATUS_BAD_CURRENT_DIRECTORY = 0x40000007, STATUS_NO_MORE_FILES = 0x80000006, STATUS_DEVICE_PAPER_EMPTY = 0x8000000E, STATUS_DEVICE_POWERED_OFF = 0x8000000F, STATUS_DEVICE_OFF_LINE = 0x80000010, STATUS_DEVICE_BUSY = 0x80000011, STATUS_NO_MORE_ENTRIES = 0x8000001A, STATUS_UNSUCCESSFUL = 0xC0000001, STATUS_NOT_IMPLEMENTED = 0xC0000002, STATUS_INVALID_INFO_CLASS = 0xC0000003, STATUS_INVALID_HANDLE = 0xC0000008, STATUS_INVALID_PARAMETER = 0xC000000D, STATUS_NO_SUCH_DEVICE = 0xC000000E, STATUS_NO_SUCH_FILE = 0xC000000F, STATUS_INVALID_DEVICE_REQUEST = 0xC0000010, STATUS_END_OF_FILE = 0xC0000011, STATUS_NO_MEDIA_IN_DEVICE = 0xC0000013, STATUS_UNRECOGNIZED_MEDIA = 0xC0000014, STATUS_ACCESS_DENIED = 0xc0000022, STATUS_OBJECT_NAME_INVALID = 0xC0000033, STATUS_OBJECT_NAME_NOT_FOUND = 0xC0000034, STATUS_OBJECT_NAME_COLLISION = 0xc0000035, STATUS_PORT_DISCONNECTED = 0xC0000037, STATUS_OBJECT_PATH_INVALID = 0xC0000039, STATUS_OBJECT_PATH_NOT_FOUND = 0xC000003A, STATUS_INVALID_PORT_HANDLE = 0xC0000042, STATUS_DELETE_PENDING = 0xC0000056, STATUS_DISK_FULL = 0xC000007F, STATUS_DEVICE_NOT_READY = 0xC00000A3, STATUS_IO_TIMEOUT = 0xC00000B5, STATUS_FILE_IS_A_DIRECTORY = 0xC00000BA, STATUS_NOT_SUPPORTED = 0xC00000BB, STATUS_PRINT_QUEUE_FULL = 0xC00000C6, STATUS_PRINT_CANCELLED = 0xC00000C8, STATUS_DIRECTORY_NOT_EMPTY = 0xC0000101, STATUS_FILE_CORRUPT_ERROR = 0xC0000102, STATUS_NOT_A_DIRECTORY = 0xC0000103, STATUS_NAME_TOO_LONG = 0xC0000106, STATUS_CANCELLED = 0xC0000120, STATUS_CANNOT_DELETE = 0xC0000121, STATUS_FILE_DELETED = 0xC0000123, STATUS_FILE_CLOSED = 0xC0000128 }; enum RDPDR_PRINTER_ANNOUNCE_FLAG { RDPDR_PRINTER_ANNOUNCE_FLAG_ASCII = 0x00000001, RDPDR_PRINTER_ANNOUNCE_FLAG_DEFAULTPRINTER = 0x00000002, RDPDR_PRINTER_ANNOUNCE_FLAG_NETWORKPRINTER = 0x00000004, RDPDR_PRINTER_ANNOUNCE_FLAG_TSPRINTER = 0x00000008, RDPDR_PRINTER_ANNOUNCE_FLAG_XPSFORMAT = 0x00000010 }; /* [MS-FSCC] FileAttributes */ enum FILE_ATTRIBUTE { FILE_ATTRIBUTE_ARCHIVE = 0x00000020, FILE_ATTRIBUTE_COMPRESSED = 0x00000800, FILE_ATTRIBUTE_DIRECTORY = 0x00000010, FILE_ATTRIBUTE_ENCRYPTED = 0x00004000, FILE_ATTRIBUTE_HIDDEN = 0x00000002, FILE_ATTRIBUTE_NORMAL = 0x00000080, FILE_ATTRIBUTE_NOT_CONTENT_INDEXED = 0x00002000, FILE_ATTRIBUTE_OFFLINE = 0x00001000, FILE_ATTRIBUTE_READONLY = 0x00000001, FILE_ATTRIBUTE_REPARSE_POINT = 0x00000400, FILE_ATTRIBUTE_SPARSE_FILE = 0x00000200, FILE_ATTRIBUTE_SYSTEM = 0x00000004, FILE_ATTRIBUTE_TEMPORARY = 0x00000100 }; /* [MS-FSCC] FSCTL Structures */ enum FSCTL_STRUCTURE { FSCTL_CREATE_OR_GET_OBJECT_ID = 0x900c0, FSCTL_GET_REPARSE_POINT = 0x900a8, FSCTL_GET_RETRIEVAL_POINTERS = 0x90073, FSCTL_IS_PATHNAME_VALID = 0x9002c, FSCTL_LMR_SET_LINK_TRACKING_INFORMATION = 0x1400ec, FSCTL_PIPE_PEEK = 0x11400c, FSCTL_PIPE_TRANSCEIVE = 0x11c017, FSCTL_PIPE_WAIT = 0x110018, FSCTL_QUERY_FAT_BPB = 0x90058, FSCTL_QUERY_ALLOCATED_RANGES = 0x940cf, FSCTL_QUERY_ON_DISK_VOLUME_INFO = 0x9013c, FSCTL_QUERY_SPARING_INFO = 0x90138, FSCTL_READ_FILE_USN_DATA = 0x900eb, FSCTL_RECALL_FILE = 0x90117, FSCTL_SET_COMPRESSION = 0x9c040, FSCTL_SET_DEFECT_MANAGEMENT = 0x98134, FSCTL_SET_ENCRYPTION = 0x900D7, FSCTL_SET_OBJECT_ID = 0x90098, FSCTL_SET_OBJECT_ID_EXTENDED = 0x900bc, FSCTL_SET_REPARSE_POINT = 0x900a4, FSCTL_SET_SPARSE = 0x900c4, FSCTL_SET_ZERO_DATA = 0x980c8, FSCTL_SET_ZERO_ON_DEALLOCATION = 0x90194, FSCTL_SIS_COPYFILE = 0x90100, FSCTL_WRITE_USN_CLOSE_RECORD = 0x900ef }; /* [MS-FSCC] FileFsAttributeInformation.FileSystemAttributes */ enum FILE_FS_ATTRIBUTE_INFORMATION { FILE_SUPPORTS_USN_JOURNAL = 0x02000000, FILE_SUPPORTS_OPEN_BY_FILE_ID = 0x01000000, FILE_SUPPORTS_EXTENDED_ATTRIBUTES = 0x00800000, FILE_SUPPORTS_HARD_LINKS = 0x00400000, FILE_SUPPORTS_TRANSACTIONS = 0x00200000, FILE_SEQUENTIAL_WRITE_ONCE = 0x00100000, FILE_READ_ONLY_VOLUME = 0x00080000, FILE_NAMED_STREAMS = 0x00040000, FILE_SUPPORTS_ENCRYPTION = 0x00020000, FILE_SUPPORTS_OBJECT_IDS = 0x00010000, FILE_VOLUME_IS_COMPRESSED = 0x00008000, FILE_SUPPORTS_REMOTE_STORAGE = 0x00000100, FILE_SUPPORTS_REPARSE_POINTS = 0x00000080, FILE_SUPPORTS_SPARSE_FILES = 0x00000040, FILE_VOLUME_QUOTAS = 0x00000020, FILE_FILE_COMPRESSION = 0x00000010, FILE_PERSISTENT_ACLS = 0x00000008, FILE_UNICODE_ON_DISK = 0x00000004, FILE_CASE_PRESERVED_NAMES = 0x00000002, FILE_CASE_SENSITIVE_SEARCH = 0x00000001 }; /* [MS-FSCC] FileFsDeviceInformation.DeviceType */ enum FILE_FS_DEVICE_TYPE { FILE_DEVICE_CD_ROM = 0x00000002, FILE_DEVICE_DISK = 0x00000007 }; /* [MS-FSCC] FileFsDeviceInformation.Characteristics */ enum FILE_FS_DEVICE_FLAG { FILE_REMOVABLE_MEDIA = 0x00000001, FILE_READ_ONLY_DEVICE = 0x00000002, FILE_FLOPPY_DISKETTE = 0x00000004, FILE_WRITE_ONCE_MEDIA = 0x00000008, FILE_REMOTE_DEVICE = 0x00000010, FILE_DEVICE_IS_MOUNTED = 0x00000020, FILE_VIRTUAL_VOLUME = 0x00000040, FILE_DEVICE_SECURE_OPEN = 0x00000100 }; enum FILE_INFORMATION_CLASS { FileDirectoryInformation = 1, FileFullDirectoryInformation, FileBothDirectoryInformation, FileBasicInformation, FileStandardInformation, FileInternalInformation, FileEaInformation, FileAccessInformation, FileNameInformation, FileRenameInformation, FileLinkInformation, FileNamesInformation, FileDispositionInformation, FilePositionInformation, FileFullEaInformation, FileModeInformation, FileAlignmentInformation, FileAllInformation, FileAllocationInformation, FileEndOfFileInformation, FileAlternateNameInformation, FileStreamInformation, FilePipeInformation, FilePipeLocalInformation, FilePipeRemoteInformation, FileMailslotQueryInformation, FileMailslotSetInformation, FileCompressionInformation, FileObjectIdInformation, FileUnknownInformation1, FileMoveClusterInformation, FileQuotaInformation, FileReparsePointInformation, FileNetworkOpenInformation, FileAttributeTagInformation, FileTrackingInformation, FileIdBothDirectoryInformation, FileIdFullDirectoryInformation, FileValidDataLengthInformation, FileShortNameInformation }; enum FILE_FS_INFORMATION_CLASS { FileFsVolumeInformation = 1, FileFsLabelInformation, FileFsSizeInformation, FileFsDeviceInformation, FileFsAttributeInformation, FileFsControlInformation, FileFsFullSizeInformation, FileFsObjectIdInformation, FileFsDriverPathInformation, FileFsMaximumInformation }; #endif /* __RDPDR_CONSTANTS_H */ FreeRDP-1.0.2/channels/rdpdr/rdpdr_main.c000066400000000000000000000207621207112532300201350ustar00rootroot00000000000000/** * FreeRDP: A Remote Desktop Protocol client. * File System Virtual Channel * * Copyright 2010-2011 Marc-Andre Moreau * Copyright 2010-2011 Vic Lee * * 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. */ #include "config.h" #include #include #include #include #include #include #include #include #include #ifdef HAVE_UNISTD_H #include #endif #include "rdpdr_types.h" #include "rdpdr_constants.h" #include "rdpdr_capabilities.h" #include "devman.h" #include "irp.h" #include "rdpdr_main.h" static void rdpdr_process_connect(rdpSvcPlugin* plugin) { rdpdrPlugin* rdpdr = (rdpdrPlugin*) plugin; RDP_PLUGIN_DATA* data; rdpdr->devman = devman_new(plugin); data = (RDP_PLUGIN_DATA*) plugin->channel_entry_points.pExtendedData; while (data && data->size > 0) { if (strcmp((char*) data->data[0], "clientname") == 0) { strncpy(rdpdr->computerName, (char*) data->data[1], sizeof(rdpdr->computerName) - 1); DEBUG_SVC("computerName %s", rdpdr->computerName); } else { devman_load_device_service(rdpdr->devman, data); } data = (RDP_PLUGIN_DATA*) (((void*) data) + data->size); } } static void rdpdr_process_server_announce_request(rdpdrPlugin* rdpdr, STREAM* data_in) { stream_read_uint16(data_in, rdpdr->versionMajor); stream_read_uint16(data_in, rdpdr->versionMinor); stream_read_uint32(data_in, rdpdr->clientID); DEBUG_SVC("version %d.%d clientID %d", rdpdr->versionMajor, rdpdr->versionMinor, rdpdr->clientID); } static void rdpdr_send_client_announce_reply(rdpdrPlugin* rdpdr) { STREAM* data_out; data_out = stream_new(12); stream_write_uint16(data_out, RDPDR_CTYP_CORE); stream_write_uint16(data_out, PAKID_CORE_CLIENTID_CONFIRM); stream_write_uint16(data_out, rdpdr->versionMajor); stream_write_uint16(data_out, rdpdr->versionMinor); stream_write_uint32(data_out, rdpdr->clientID); svc_plugin_send((rdpSvcPlugin*) rdpdr, data_out); } static void rdpdr_send_client_name_request(rdpdrPlugin* rdpdr) { char* s; STREAM* data_out; UNICONV* uniconv; size_t computerNameLenW; uniconv = freerdp_uniconv_new(); if (!rdpdr->computerName[0]) gethostname(rdpdr->computerName, sizeof(rdpdr->computerName) - 1); s = freerdp_uniconv_out(uniconv, rdpdr->computerName, &computerNameLenW); data_out = stream_new(16 + computerNameLenW + 2); stream_write_uint16(data_out, RDPDR_CTYP_CORE); stream_write_uint16(data_out, PAKID_CORE_CLIENT_NAME); stream_write_uint32(data_out, 1); /* unicodeFlag, 0 for ASCII and 1 for Unicode */ stream_write_uint32(data_out, 0); /* codePage, must be set to zero */ stream_write_uint32(data_out, computerNameLenW + 2); /* computerNameLen, including null terminator */ stream_write(data_out, s, computerNameLenW); stream_write_uint16(data_out, 0); /* null terminator */ xfree(s); freerdp_uniconv_free(uniconv); svc_plugin_send((rdpSvcPlugin*) rdpdr, data_out); } static void rdpdr_process_server_clientid_confirm(rdpdrPlugin* rdpdr, STREAM* data_in) { uint16 versionMajor; uint16 versionMinor; uint32 clientID; stream_read_uint16(data_in, versionMajor); stream_read_uint16(data_in, versionMinor); stream_read_uint32(data_in, clientID); if (versionMajor != rdpdr->versionMajor || versionMinor != rdpdr->versionMinor) { DEBUG_WARN("unmatched version %d.%d", versionMajor, versionMinor); rdpdr->versionMajor = versionMajor; rdpdr->versionMinor = versionMinor; } if (clientID != rdpdr->clientID) { DEBUG_WARN("unmatched clientID %d", clientID); rdpdr->clientID = clientID; } } static void rdpdr_send_device_list_announce_request(rdpdrPlugin* rdpdr, boolean user_loggedon) { int i; int pos; uint8 c; uint32 count; int data_len; int count_pos; STREAM* data_out; DEVICE* device; LIST_ITEM* item; data_out = stream_new(256); stream_write_uint16(data_out, RDPDR_CTYP_CORE); stream_write_uint16(data_out, PAKID_CORE_DEVICELIST_ANNOUNCE); count_pos = stream_get_pos(data_out); count = 0; stream_seek_uint32(data_out); /* deviceCount */ for (item = rdpdr->devman->devices->head; item; item = item->next) { device = (DEVICE*) item->data; /** * 1. versionMinor 0x0005 doesn't send PAKID_CORE_USER_LOGGEDON * so all devices should be sent regardless of user_loggedon * 2. smartcard devices should be always sent * 3. other devices are sent only after user_loggedon */ if (rdpdr->versionMinor == 0x0005 || device->type == RDPDR_DTYP_SMARTCARD || user_loggedon) { data_len = (device->data == NULL ? 0 : stream_get_length(device->data)); stream_check_size(data_out, 20 + data_len); stream_write_uint32(data_out, device->type); /* deviceType */ stream_write_uint32(data_out, device->id); /* deviceID */ strncpy((char*) stream_get_tail(data_out), device->name, 8); for (i = 0; i < 8; i++) { stream_peek_uint8(data_out, c); if (c > 0x7F) stream_write_uint8(data_out, '_'); else stream_seek_uint8(data_out); } stream_write_uint32(data_out, data_len); if (data_len > 0) stream_write(data_out, stream_get_data(device->data), data_len); count++; printf("registered device #%d: %s (type=%d id=%d)\n", count, device->name, device->type, device->id); } } pos = stream_get_pos(data_out); stream_set_pos(data_out, count_pos); stream_write_uint32(data_out, count); stream_set_pos(data_out, pos); stream_seal(data_out); svc_plugin_send((rdpSvcPlugin*) rdpdr, data_out); } static boolean rdpdr_process_irp(rdpdrPlugin* rdpdr, STREAM* data_in) { IRP* irp; irp = irp_new(rdpdr->devman, data_in); if (irp == NULL) return false; IFCALL(irp->device->IRPRequest, irp->device, irp); return true; } static void rdpdr_process_receive(rdpSvcPlugin* plugin, STREAM* data_in) { rdpdrPlugin* rdpdr = (rdpdrPlugin*) plugin; uint16 component; uint16 packetID; uint32 deviceID; uint32 status; stream_read_uint16(data_in, component); stream_read_uint16(data_in, packetID); if (component == RDPDR_CTYP_CORE) { switch (packetID) { case PAKID_CORE_SERVER_ANNOUNCE: DEBUG_SVC("RDPDR_CTYP_CORE / PAKID_CORE_SERVER_ANNOUNCE"); rdpdr_process_server_announce_request(rdpdr, data_in); rdpdr_send_client_announce_reply(rdpdr); rdpdr_send_client_name_request(rdpdr); break; case PAKID_CORE_SERVER_CAPABILITY: DEBUG_SVC("RDPDR_CTYP_CORE / PAKID_CORE_SERVER_CAPABILITY"); rdpdr_process_capability_request(rdpdr, data_in); rdpdr_send_capability_response(rdpdr); break; case PAKID_CORE_CLIENTID_CONFIRM: DEBUG_SVC("RDPDR_CTYP_CORE / PAKID_CORE_CLIENTID_CONFIRM"); rdpdr_process_server_clientid_confirm(rdpdr, data_in); rdpdr_send_device_list_announce_request(rdpdr, false); break; case PAKID_CORE_USER_LOGGEDON: DEBUG_SVC("RDPDR_CTYP_CORE / PAKID_CORE_USER_LOGGEDON"); rdpdr_send_device_list_announce_request(rdpdr, true); break; case PAKID_CORE_DEVICE_REPLY: /* connect to a specific resource */ stream_read_uint32(data_in, deviceID); stream_read_uint32(data_in, status); DEBUG_SVC("RDPDR_CTYP_CORE / PAKID_CORE_DEVICE_REPLY (deviceID=%d status=0x%08X)", deviceID, status); break; case PAKID_CORE_DEVICE_IOREQUEST: DEBUG_SVC("RDPDR_CTYP_CORE / PAKID_CORE_DEVICE_IOREQUEST"); if (rdpdr_process_irp(rdpdr, data_in)) data_in = NULL; break; default: DEBUG_WARN("RDPDR_CTYP_CORE / unknown packetID: 0x%02X", packetID); break; } } else if (component == RDPDR_CTYP_PRN) { DEBUG_SVC("RDPDR_CTYP_PRN"); } else { DEBUG_WARN("RDPDR component: 0x%02X packetID: 0x%02X\n", component, packetID); } stream_free(data_in); } static void rdpdr_process_event(rdpSvcPlugin* plugin, RDP_EVENT* event) { freerdp_event_free(event); } static void rdpdr_process_terminate(rdpSvcPlugin* plugin) { rdpdrPlugin* rdpdr = (rdpdrPlugin*) plugin; devman_free(rdpdr->devman); xfree(plugin); } DEFINE_SVC_PLUGIN(rdpdr, "rdpdr", CHANNEL_OPTION_INITIALIZED | CHANNEL_OPTION_ENCRYPT_RDP | CHANNEL_OPTION_COMPRESS_RDP) FreeRDP-1.0.2/channels/rdpdr/rdpdr_main.h000066400000000000000000000020731207112532300201350ustar00rootroot00000000000000/** * FreeRDP: A Remote Desktop Protocol client. * File System Virtual Channel * * Copyright 2010-2011 Marc-Andre Moreau * Copyright 2010-2011 Vic Lee * * 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. */ #ifndef __RDPDR_MAIN_H #define __RDPDR_MAIN_H #include #include "rdpdr_types.h" typedef struct rdpdr_plugin rdpdrPlugin; struct rdpdr_plugin { rdpSvcPlugin plugin; DEVMAN* devman; uint16 versionMajor; uint16 versionMinor; uint16 clientID; char computerName[256]; }; #endif /* __RDPDR_MAIN_H */ FreeRDP-1.0.2/channels/rdpdr/rdpdr_types.h000066400000000000000000000040601207112532300203530ustar00rootroot00000000000000/** * FreeRDP: A Remote Desktop Protocol client. * File System Virtual Channel * * Copyright 2010-2011 Marc-Andre Moreau * Copyright 2010-2011 Vic Lee * * 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. */ #ifndef __RDPDR_TYPES_H #define __RDPDR_TYPES_H #include "config.h" #include #include #include typedef struct _DEVICE DEVICE; typedef struct _IRP IRP; typedef struct _DEVMAN DEVMAN; typedef void (*pcIRPRequest)(DEVICE* device, IRP* irp); typedef void (*pcFreeDevice)(DEVICE* device); struct _DEVICE { uint32 id; uint32 type; char* name; STREAM* data; pcIRPRequest IRPRequest; pcFreeDevice Free; }; typedef void (*pcIRPResponse)(IRP* irp); struct _IRP { DEVICE* device; DEVMAN* devman; uint32 FileId; uint32 CompletionId; uint32 MajorFunction; uint32 MinorFunction; STREAM* input; uint32 IoStatus; STREAM* output; pcIRPResponse Complete; pcIRPResponse Discard; }; struct _DEVMAN { rdpSvcPlugin* plugin; uint32 id_sequence; /* generate unique device id */ LIST* devices; }; typedef void (*pcRegisterDevice)(DEVMAN* devman, DEVICE* device); struct _DEVICE_SERVICE_ENTRY_POINTS { DEVMAN* devman; pcRegisterDevice RegisterDevice; pcRegisterDevice UnregisterDevice; RDP_PLUGIN_DATA* plugin_data; }; typedef struct _DEVICE_SERVICE_ENTRY_POINTS DEVICE_SERVICE_ENTRY_POINTS; typedef DEVICE_SERVICE_ENTRY_POINTS* PDEVICE_SERVICE_ENTRY_POINTS; typedef int (*PDEVICE_SERVICE_ENTRY)(PDEVICE_SERVICE_ENTRY_POINTS); #endif /* __RDPDR_TYPES_H */ FreeRDP-1.0.2/channels/rdpdr/serial/000077500000000000000000000000001207112532300171225ustar00rootroot00000000000000FreeRDP-1.0.2/channels/rdpdr/serial/CMakeLists.txt000066400000000000000000000021001207112532300216530ustar00rootroot00000000000000# FreeRDP: A Remote Desktop Protocol Client # FreeRDP cmake build script # # Copyright 2011 O.S. Systems Software Ltda. # Copyright 2011 Otavio Salvador # Copyright 2011 Marc-Andre Moreau # # 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(serial_SRCS serial_tty.c serial_tty.h serial_constants.h serial_main.c ) include_directories(..) add_library(serial ${serial_SRCS}) set_target_properties(serial PROPERTIES PREFIX "") target_link_libraries(serial freerdp-utils) install(TARGETS serial DESTINATION ${FREERDP_PLUGIN_PATH}) FreeRDP-1.0.2/channels/rdpdr/serial/serial_constants.h000066400000000000000000000105521207112532300226510ustar00rootroot00000000000000/** * FreeRDP: A Remote Desktop Protocol client. * Serial Port Device Service Virtual Channel * * Copyright 2011 O.S. Systems Software Ltda. * Copyright 2011 Eduardo Fiss Beloni * * 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. */ #ifndef __SERIAL_CONSTANTS_H #define __SERIAL_CONSTANTS_H /* http://www.codeproject.com/KB/system/chaiyasit_t.aspx */ #define SERIAL_TIMEOUT_MAX 4294967295u /* DR_CONTROL_REQ.IoControlCode */ enum DR_PORT_CONTROL_REQ { IOCTL_SERIAL_SET_BAUD_RATE = 0x001B0004, IOCTL_SERIAL_GET_BAUD_RATE = 0x001B0050, IOCTL_SERIAL_SET_LINE_CONTROL = 0x001B000C, IOCTL_SERIAL_GET_LINE_CONTROL = 0x001B0054, IOCTL_SERIAL_SET_TIMEOUTS = 0x001B001C, IOCTL_SERIAL_GET_TIMEOUTS = 0x001B0020, /* GET_CHARS and SET_CHARS are swapped in the RDP docs [MS-RDPESP] */ IOCTL_SERIAL_GET_CHARS = 0x001B0058, IOCTL_SERIAL_SET_CHARS = 0x001B005C, IOCTL_SERIAL_SET_DTR = 0x001B0024, IOCTL_SERIAL_CLR_DTR = 0x001B0028, IOCTL_SERIAL_RESET_DEVICE = 0x001B002C, IOCTL_SERIAL_SET_RTS = 0x001B0030, IOCTL_SERIAL_CLR_RTS = 0x001B0034, IOCTL_SERIAL_SET_XOFF = 0x001B0038, IOCTL_SERIAL_SET_XON = 0x001B003C, IOCTL_SERIAL_SET_BREAK_ON = 0x001B0010, IOCTL_SERIAL_SET_BREAK_OFF = 0x001B0014, IOCTL_SERIAL_SET_QUEUE_SIZE = 0x001B0008, IOCTL_SERIAL_GET_WAIT_MASK = 0x001B0040, IOCTL_SERIAL_SET_WAIT_MASK = 0x001B0044, IOCTL_SERIAL_WAIT_ON_MASK = 0x001B0048, IOCTL_SERIAL_IMMEDIATE_CHAR = 0x001B0018, IOCTL_SERIAL_PURGE = 0x001B004C, IOCTL_SERIAL_GET_HANDFLOW = 0x001B0060, IOCTL_SERIAL_SET_HANDFLOW = 0x001B0064, IOCTL_SERIAL_GET_MODEMSTATUS = 0x001B0068, IOCTL_SERIAL_GET_DTRRTS = 0x001B0078, /* according to [MS-RDPESP] it should be 0x001B0084, but servers send 0x001B006C */ IOCTL_SERIAL_GET_COMMSTATUS = 0x001B006C, IOCTL_SERIAL_GET_PROPERTIES = 0x001B0074, IOCTL_SERIAL_XOFF_COUNTER = 0x001B0070, IOCTL_SERIAL_LSRMST_INSERT = 0x001B007C, IOCTL_SERIAL_CONFIG_SIZE = 0x001B0080, IOCTL_SERIAL_GET_STATS = 0x001B008C, IOCTL_SERIAL_CLEAR_STATS = 0x001B0090, IOCTL_SERIAL_GET_MODEM_CONTROL = 0x001B0094, IOCTL_SERIAL_SET_MODEM_CONTROL = 0x001B0098, IOCTL_SERIAL_SET_FIFO_CONTROL = 0x001B009C, }; enum SERIAL_PURGE_MASK { SERIAL_PURGE_TXABORT = 0x00000001, SERIAL_PURGE_RXABORT = 0x00000002, SERIAL_PURGE_TXCLEAR = 0x00000004, SERIAL_PURGE_RXCLEAR = 0x00000008, }; enum SERIAL_WAIT_MASK { SERIAL_EV_RXCHAR = 0x0001, /* Any Character received */ SERIAL_EV_RXFLAG = 0x0002, /* Received certain character */ SERIAL_EV_TXEMPTY = 0x0004, /* Transmitt Queue Empty */ SERIAL_EV_CTS = 0x0008, /* CTS changed state */ SERIAL_EV_DSR = 0x0010, /* DSR changed state */ SERIAL_EV_RLSD = 0x0020, /* RLSD changed state */ SERIAL_EV_BREAK = 0x0040, /* BREAK received */ SERIAL_EV_ERR = 0x0080, /* Line status error occurred */ SERIAL_EV_RING = 0x0100, /* Ring signal detected */ SERIAL_EV_PERR = 0x0200, /* Printer error occured */ SERIAL_EV_RX80FULL = 0x0400,/* Receive buffer is 80 percent full */ SERIAL_EV_EVENT1 = 0x0800, /* Provider specific event 1 */ SERIAL_EV_EVENT2 = 0x1000, /* Provider specific event 2 */ }; enum SERIAL_MODEM_STATUS { SERIAL_MS_DTR = 0x01, SERIAL_MS_RTS = 0x02, SERIAL_MS_CTS = 0x10, SERIAL_MS_DSR = 0x20, SERIAL_MS_RNG = 0x40, SERIAL_MS_CAR = 0x80, }; enum SERIAL_HANDFLOW { SERIAL_DTR_CONTROL = 0x01, SERIAL_CTS_HANDSHAKE = 0x08, SERIAL_ERROR_ABORT = 0x80000000, }; enum SERIAL_FLOW_CONTROL { SERIAL_XON_HANDSHAKE = 0x01, SERIAL_XOFF_HANDSHAKE = 0x02, SERIAL_DSR_SENSITIVITY = 0x40, }; enum SERIAL_CHARS { SERIAL_CHAR_EOF = 0, SERIAL_CHAR_ERROR = 1, SERIAL_CHAR_BREAK = 2, SERIAL_CHAR_EVENT = 3, SERIAL_CHAR_XON = 4, SERIAL_CHAR_XOFF = 5, }; enum SERIAL_ABORT_IO { SERIAL_ABORT_IO_NONE = 0, SERIAL_ABORT_IO_WRITE = 1, SERIAL_ABORT_IO_READ = 2, }; enum SERIAL_STOP_BITS { SERIAL_STOP_BITS_1 = 0, SERIAL_STOP_BITS_2 = 2, }; enum SERIAL_PARITY { SERIAL_NO_PARITY = 0, SERIAL_ODD_PARITY = 1, SERIAL_EVEN_PARITY = 2, }; #endif FreeRDP-1.0.2/channels/rdpdr/serial/serial_main.c000066400000000000000000000374441207112532300215650ustar00rootroot00000000000000/** * FreeRDP: A Remote Desktop Protocol client. * Serial Port Device Service Virtual Channel * * Copyright 2011 O.S. Systems Software Ltda. * Copyright 2011 Eduardo Fiss Beloni * * 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. */ #include #include #include #include #include "config.h" #ifdef HAVE_SYS_MODEM_H #include #endif #ifdef HAVE_SYS_FILIO_H #include #endif #ifdef HAVE_SYS_STRTIO_H #include #endif #ifdef HAVE_UNISTD_H #include #endif #include "rdpdr_types.h" #include "rdpdr_constants.h" #include "devman.h" #include "serial_tty.h" #include "serial_constants.h" #include #include #include #include typedef struct _SERIAL_DEVICE SERIAL_DEVICE; struct _SERIAL_DEVICE { DEVICE device; char* path; SERIAL_TTY* tty; LIST* irp_list; LIST* pending_irps; freerdp_thread* thread; struct wait_obj* in_event; fd_set read_fds; fd_set write_fds; uint32 nfds; struct timeval tv; uint32 select_timeout; uint32 timeout_id; }; static void serial_abort_single_io(SERIAL_DEVICE* serial, uint32 file_id, uint32 abort_io, uint32 io_status); static void serial_check_for_events(SERIAL_DEVICE* serial); static void serial_handle_async_irp(SERIAL_DEVICE* serial, IRP* irp); static boolean serial_check_fds(SERIAL_DEVICE* serial); static void serial_process_irp_create(SERIAL_DEVICE* serial, IRP* irp) { SERIAL_TTY* tty; uint32 PathLength; uint32 FileId; char* path; UNICONV* uniconv; stream_seek(irp->input, 28); /* DesiredAccess(4) AllocationSize(8), FileAttributes(4) */ /* SharedAccess(4) CreateDisposition(4), CreateOptions(4) */ stream_read_uint32(irp->input, PathLength); uniconv = freerdp_uniconv_new(); path = freerdp_uniconv_in(uniconv, stream_get_tail(irp->input), PathLength); freerdp_uniconv_free(uniconv); FileId = irp->devman->id_sequence++; tty = serial_tty_new(serial->path, FileId); if (tty == NULL) { irp->IoStatus = STATUS_UNSUCCESSFUL; FileId = 0; DEBUG_WARN("failed to create %s", path); } else { serial->tty = tty; DEBUG_SVC("%s(%d) created.", serial->path, FileId); } stream_write_uint32(irp->output, FileId); stream_write_uint8(irp->output, 0); xfree(path); irp->Complete(irp); } static void serial_process_irp_close(SERIAL_DEVICE* serial, IRP* irp) { SERIAL_TTY* tty; tty = serial->tty; if (tty == NULL) { irp->IoStatus = STATUS_UNSUCCESSFUL; DEBUG_WARN("tty not valid."); } else { DEBUG_SVC("%s(%d) closed.", serial->path, tty->id); serial_tty_free(tty); serial->tty = NULL; } stream_write_zero(irp->output, 5); /* Padding(5) */ irp->Complete(irp); } static void serial_process_irp_read(SERIAL_DEVICE* serial, IRP* irp) { SERIAL_TTY* tty; uint32 Length; uint64 Offset; uint8* buffer = NULL; stream_read_uint32(irp->input, Length); stream_read_uint64(irp->input, Offset); DEBUG_SVC("length %u offset %llu", Length, Offset); tty = serial->tty; if (tty == NULL) { irp->IoStatus = STATUS_UNSUCCESSFUL; Length = 0; DEBUG_WARN("tty not valid."); } else { buffer = (uint8*)xmalloc(Length); if (!serial_tty_read(tty, buffer, &Length)) { irp->IoStatus = STATUS_UNSUCCESSFUL; xfree(buffer); buffer = NULL; Length = 0; DEBUG_WARN("read %s(%d) failed.", serial->path, tty->id); } else { DEBUG_SVC("read %llu-%llu from %d", Offset, Offset + Length, tty->id); } } stream_write_uint32(irp->output, Length); if (Length > 0) { stream_check_size(irp->output, Length); stream_write(irp->output, buffer, Length); } xfree(buffer); irp->Complete(irp); } static void serial_process_irp_write(SERIAL_DEVICE* serial, IRP* irp) { SERIAL_TTY* tty; uint32 Length; uint64 Offset; stream_read_uint32(irp->input, Length); stream_read_uint64(irp->input, Offset); stream_seek(irp->input, 20); /* Padding */ DEBUG_SVC("length %u offset %llu", Length, Offset); tty = serial->tty; if (tty == NULL) { irp->IoStatus = STATUS_UNSUCCESSFUL; Length = 0; DEBUG_WARN("tty not valid."); } else if (!serial_tty_write(tty, stream_get_tail(irp->input), Length)) { irp->IoStatus = STATUS_UNSUCCESSFUL; Length = 0; DEBUG_WARN("write %s(%d) failed.", serial->path, tty->id); } else { DEBUG_SVC("write %llu-%llu to %s(%d).", Offset, Offset + Length, serial->path, tty->id); } stream_write_uint32(irp->output, Length); stream_write_uint8(irp->output, 0); /* Padding */ irp->Complete(irp); } static void serial_process_irp_device_control(SERIAL_DEVICE* serial, IRP* irp) { SERIAL_TTY* tty; uint32 IoControlCode; uint32 InputBufferLength; uint32 OutputBufferLength; uint32 abort_io = SERIAL_ABORT_IO_NONE; DEBUG_SVC("[in] pending size %d", list_size(serial->pending_irps)); stream_read_uint32(irp->input, InputBufferLength); stream_read_uint32(irp->input, OutputBufferLength); stream_read_uint32(irp->input, IoControlCode); stream_seek(irp->input, 20); /* Padding */ tty = serial->tty; if (tty == NULL) { irp->IoStatus = STATUS_UNSUCCESSFUL; OutputBufferLength = 0; DEBUG_WARN("tty not valid."); } else { irp->IoStatus = serial_tty_control(tty, IoControlCode, irp->input, irp->output, &abort_io); } if (abort_io & SERIAL_ABORT_IO_WRITE) serial_abort_single_io(serial, tty->id, SERIAL_ABORT_IO_WRITE, STATUS_CANCELLED); if (abort_io & SERIAL_ABORT_IO_READ) serial_abort_single_io(serial, tty->id, SERIAL_ABORT_IO_READ, STATUS_CANCELLED); if (irp->IoStatus == STATUS_PENDING) list_enqueue(serial->pending_irps, irp); else irp->Complete(irp); } static void serial_process_irp(SERIAL_DEVICE* serial, IRP* irp) { DEBUG_SVC("MajorFunction %u", irp->MajorFunction); switch (irp->MajorFunction) { case IRP_MJ_CREATE: serial_process_irp_create(serial, irp); break; case IRP_MJ_CLOSE: serial_process_irp_close(serial, irp); break; case IRP_MJ_READ: serial_handle_async_irp(serial, irp); //serial_process_irp_read(serial, irp); break; case IRP_MJ_WRITE: serial_handle_async_irp(serial, irp); //serial_process_irp_write(serial, irp); break; case IRP_MJ_DEVICE_CONTROL: serial_process_irp_device_control(serial, irp); break; default: DEBUG_WARN("MajorFunction 0x%X not supported", irp->MajorFunction); irp->IoStatus = STATUS_NOT_SUPPORTED; irp->Complete(irp); break; } serial_check_for_events(serial); } static void serial_process_irp_list(SERIAL_DEVICE* serial) { IRP* irp; while (1) { if (freerdp_thread_is_stopped(serial->thread)) break; freerdp_thread_lock(serial->thread); irp = (IRP*)list_dequeue(serial->irp_list); freerdp_thread_unlock(serial->thread); if (irp == NULL) break; serial_process_irp(serial, irp); } } static void* serial_thread_func(void* arg) { SERIAL_DEVICE* serial = (SERIAL_DEVICE*)arg; while (1) { freerdp_thread_wait(serial->thread); serial->nfds = 1; FD_ZERO(&serial->read_fds); FD_ZERO(&serial->write_fds); serial->tv.tv_sec = 20; serial->tv.tv_usec = 0; serial->select_timeout = 0; if (freerdp_thread_is_stopped(serial->thread)) break; freerdp_thread_reset(serial->thread); serial_process_irp_list(serial); if (wait_obj_is_set(serial->in_event)) { if (serial_check_fds(serial)) wait_obj_clear(serial->in_event); } } freerdp_thread_quit(serial->thread); return NULL; } static void serial_irp_request(DEVICE* device, IRP* irp) { SERIAL_DEVICE* serial = (SERIAL_DEVICE*)device; freerdp_thread_lock(serial->thread); list_enqueue(serial->irp_list, irp); freerdp_thread_unlock(serial->thread); freerdp_thread_signal(serial->thread); } static void serial_free(DEVICE* device) { SERIAL_DEVICE* serial = (SERIAL_DEVICE*)device; IRP* irp; DEBUG_SVC("freeing device"); freerdp_thread_stop(serial->thread); freerdp_thread_free(serial->thread); while ((irp = (IRP*)list_dequeue(serial->irp_list)) != NULL) irp->Discard(irp); list_free(serial->irp_list); while ((irp = (IRP*)list_dequeue(serial->pending_irps)) != NULL) irp->Discard(irp); list_free(serial->pending_irps); xfree(serial); } int DeviceServiceEntry(PDEVICE_SERVICE_ENTRY_POINTS pEntryPoints) { SERIAL_DEVICE* serial; char* name; char* path; int i, len; name = (char*)pEntryPoints->plugin_data->data[1]; path = (char*)pEntryPoints->plugin_data->data[2]; if (name[0] && path[0]) { serial = xnew(SERIAL_DEVICE); serial->device.type = RDPDR_DTYP_SERIAL; serial->device.name = name; serial->device.IRPRequest = serial_irp_request; serial->device.Free = serial_free; len = strlen(name); serial->device.data = stream_new(len + 1); for (i = 0; i <= len; i++) stream_write_uint8(serial->device.data, name[i] < 0 ? '_' : name[i]); serial->path = path; serial->irp_list = list_new(); serial->pending_irps = list_new(); serial->thread = freerdp_thread_new(); serial->in_event = wait_obj_new(); pEntryPoints->RegisterDevice(pEntryPoints->devman, (DEVICE*)serial); freerdp_thread_start(serial->thread, serial_thread_func, serial); } return 0; } static void serial_abort_single_io(SERIAL_DEVICE* serial, uint32 file_id, uint32 abort_io, uint32 io_status) { IRP* irp = NULL; uint32 major; SERIAL_TTY* tty; DEBUG_SVC("[in] pending size %d", list_size(serial->pending_irps)); tty = serial->tty; switch (abort_io) { case SERIAL_ABORT_IO_NONE: major = 0; break; case SERIAL_ABORT_IO_READ: major = IRP_MJ_READ; break; case SERIAL_ABORT_IO_WRITE: major = IRP_MJ_WRITE; break; default: DEBUG_SVC("unexpected abort_io code %d", abort_io); return; } irp = (IRP*)list_peek(serial->pending_irps); while (irp) { if (irp->FileId != file_id || irp->MajorFunction != major) { irp = (IRP*)list_next(serial->pending_irps, irp); continue; } /* Process a SINGLE FileId and MajorFunction */ list_remove(serial->pending_irps, irp); irp->IoStatus = io_status; stream_write_uint32(irp->output, 0); irp->Complete(irp); wait_obj_set(serial->in_event); break; } DEBUG_SVC("[out] pending size %d", list_size(serial->pending_irps)); } static void serial_check_for_events(SERIAL_DEVICE* serial) { IRP* irp = NULL; IRP* prev; uint32 result = 0; SERIAL_TTY* tty; tty = serial->tty; DEBUG_SVC("[in] pending size %d", list_size(serial->pending_irps)); irp = (IRP*)list_peek(serial->pending_irps); while (irp) { prev = NULL; if (irp->MajorFunction == IRP_MJ_DEVICE_CONTROL) { if (serial_tty_get_event(tty, &result)) { DEBUG_SVC("got event result %u", result); irp->IoStatus = STATUS_SUCCESS; stream_write_uint32(irp->output, result); irp->Complete(irp); prev = irp; irp = (IRP*)list_next(serial->pending_irps, irp); list_remove(serial->pending_irps, prev); wait_obj_set(serial->in_event); } } if (!prev) irp = (IRP*)list_next(serial->pending_irps, irp); } DEBUG_SVC("[out] pending size %d", list_size(serial->pending_irps)); } void serial_get_timeouts(SERIAL_DEVICE* serial, IRP* irp, uint32* timeout, uint32* interval_timeout) { SERIAL_TTY* tty; uint32 Length; uint32 pos; pos = stream_get_pos(irp->input); stream_read_uint32(irp->input, Length); stream_set_pos(irp->input, pos); DEBUG_SVC("length read %u", Length); tty = serial->tty; *timeout = (tty->read_total_timeout_multiplier * Length) + tty->read_total_timeout_constant; *interval_timeout = tty->read_interval_timeout; DEBUG_SVC("timeouts %u %u", *timeout, *interval_timeout); } static void serial_handle_async_irp(SERIAL_DEVICE* serial, IRP* irp) { uint32 timeout = 0; uint32 itv_timeout = 0; SERIAL_TTY* tty; tty = serial->tty; switch (irp->MajorFunction) { case IRP_MJ_WRITE: DEBUG_SVC("handling IRP_MJ_WRITE"); break; case IRP_MJ_READ: DEBUG_SVC("handling IRP_MJ_READ"); serial_get_timeouts(serial, irp, &timeout, &itv_timeout); /* Check if io request timeout is smaller than current (but not 0). */ if (timeout && (serial->select_timeout == 0 || timeout < serial->select_timeout)) { serial->select_timeout = timeout; serial->tv.tv_sec = serial->select_timeout / 1000; serial->tv.tv_usec = (serial->select_timeout % 1000) * 1000; serial->timeout_id = tty->id; } if (itv_timeout && (serial->select_timeout == 0 || itv_timeout < serial->select_timeout)) { serial->select_timeout = itv_timeout; serial->tv.tv_sec = serial->select_timeout / 1000; serial->tv.tv_usec = (serial->select_timeout % 1000) * 1000; serial->timeout_id = tty->id; } DEBUG_SVC("select_timeout %u, tv_sec %lu tv_usec %lu, timeout_id %u", serial->select_timeout, serial->tv.tv_sec, serial->tv.tv_usec, serial->timeout_id); break; default: DEBUG_SVC("no need to handle %d", irp->MajorFunction); return; } irp->IoStatus = STATUS_PENDING; list_enqueue(serial->pending_irps, irp); wait_obj_set(serial->in_event); } static void __serial_check_fds(SERIAL_DEVICE* serial) { IRP* irp; IRP* prev; SERIAL_TTY* tty; uint32 result = 0; memset(&serial->tv, 0, sizeof(struct timeval)); tty = serial->tty; /* scan every pending */ irp = list_peek(serial->pending_irps); while (irp) { DEBUG_SVC("MajorFunction %u", irp->MajorFunction); switch (irp->MajorFunction) { case IRP_MJ_READ: if (FD_ISSET(tty->fd, &serial->read_fds)) { irp->IoStatus = STATUS_SUCCESS; serial_process_irp_read(serial, irp); } break; case IRP_MJ_WRITE: if (FD_ISSET(tty->fd, &serial->write_fds)) { irp->IoStatus = STATUS_SUCCESS; serial_process_irp_write(serial, irp); } break; case IRP_MJ_DEVICE_CONTROL: if (serial_tty_get_event(tty, &result)) { DEBUG_SVC("got event result %u", result); irp->IoStatus = STATUS_SUCCESS; stream_write_uint32(irp->output, result); irp->Complete(irp); } break; default: DEBUG_SVC("no request found"); break; } prev = irp; irp = (IRP*)list_next(serial->pending_irps, irp); if (prev->IoStatus == STATUS_SUCCESS) { list_remove(serial->pending_irps, prev); wait_obj_set(serial->in_event); } } } static void serial_set_fds(SERIAL_DEVICE* serial) { fd_set* fds; IRP* irp; SERIAL_TTY* tty; DEBUG_SVC("[in] pending size %d", list_size(serial->pending_irps)); tty = serial->tty; irp = (IRP*)list_peek(serial->pending_irps); while (irp) { fds = NULL; switch (irp->MajorFunction) { case IRP_MJ_WRITE: fds = &serial->write_fds; break; case IRP_MJ_READ: fds = &serial->read_fds; break; } if (fds && (tty->fd >= 0)) { FD_SET(tty->fd, fds); serial->nfds = MAX(serial->nfds, tty->fd); } irp = (IRP*)list_next(serial->pending_irps, irp); } } static boolean serial_check_fds(SERIAL_DEVICE* serial) { if (list_size(serial->pending_irps) == 0) return 1; serial_set_fds(serial); DEBUG_SVC("waiting %lu %lu", serial->tv.tv_sec, serial->tv.tv_usec); switch (select(serial->nfds + 1, &serial->read_fds, &serial->write_fds, NULL, &serial->tv)) { case -1: DEBUG_SVC("select has returned -1 with error: %s", strerror(errno)); return 0; case 0: if (serial->select_timeout) { serial_abort_single_io(serial, serial->timeout_id, SERIAL_ABORT_IO_NONE, STATUS_TIMEOUT); serial_abort_single_io(serial, serial->timeout_id, SERIAL_ABORT_IO_READ, STATUS_TIMEOUT); serial_abort_single_io(serial, serial->timeout_id, SERIAL_ABORT_IO_WRITE, STATUS_TIMEOUT); } DEBUG_SVC("select has timed out"); return 0; default: break; } __serial_check_fds(serial); return 1; } FreeRDP-1.0.2/channels/rdpdr/serial/serial_tty.c000066400000000000000000000526241207112532300214560ustar00rootroot00000000000000/** * FreeRDP: A Remote Desktop Protocol client. * Serial Port Device Service Virtual Channel * * Copyright 2011 O.S. Systems Software Ltda. * Copyright 2011 Eduardo Fiss Beloni * * 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. */ #include "config.h" #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include "rdpdr_constants.h" #include "rdpdr_types.h" #include "serial_tty.h" #include "serial_constants.h" #ifdef HAVE_SYS_MODEM_H #include #endif #ifdef HAVE_SYS_FILIO_H #include #endif #ifdef HAVE_SYS_STRTIO_H #include #endif #ifndef CRTSCTS #define CRTSCTS 0 #endif /* FIONREAD should really do the same thing as TIOCINQ, where it is * not available */ #if !defined(TIOCINQ) && defined(FIONREAD) #define TIOCINQ FIONREAD #endif #if !defined(TIOCOUTQ) && defined(FIONWRITE) #define TIOCOUTQ FIONWRITE #endif static uint32 tty_write_data(SERIAL_TTY* tty, uint8* data, int len); static void tty_set_termios(SERIAL_TTY* tty); static boolean tty_get_termios(SERIAL_TTY* tty); static int tty_get_error_status(); uint32 serial_tty_control(SERIAL_TTY* tty, uint32 IoControlCode, STREAM* input, STREAM* output, uint32* abort_io) { int purge_mask; uint32 result; uint32 modemstate; uint8 immediate; uint32 ret = STATUS_SUCCESS; uint32 length = 0; uint32 pos; DEBUG_SVC("in"); stream_seek(output, sizeof(uint32)); switch (IoControlCode) { case IOCTL_SERIAL_SET_BAUD_RATE: stream_read_uint32(input, tty->baud_rate); tty_set_termios(tty); DEBUG_SVC("SERIAL_SET_BAUD_RATE %d", tty->baud_rate); break; case IOCTL_SERIAL_GET_BAUD_RATE: length = 4; stream_write_uint32(output, tty->baud_rate); DEBUG_SVC("SERIAL_GET_BAUD_RATE %d", tty->baud_rate); break; case IOCTL_SERIAL_SET_QUEUE_SIZE: stream_read_uint32(input, tty->queue_in_size); stream_read_uint32(input, tty->queue_out_size); DEBUG_SVC("SERIAL_SET_QUEUE_SIZE in %d out %d", tty->queue_in_size, tty->queue_out_size); break; case IOCTL_SERIAL_SET_LINE_CONTROL: stream_read_uint8(input, tty->stop_bits); stream_read_uint8(input, tty->parity); stream_read_uint8(input, tty->word_length); tty_set_termios(tty); DEBUG_SVC("SERIAL_SET_LINE_CONTROL stop %d parity %d word %d", tty->stop_bits, tty->parity, tty->word_length); break; case IOCTL_SERIAL_GET_LINE_CONTROL: DEBUG_SVC("SERIAL_GET_LINE_CONTROL"); length = 3; stream_write_uint8(output, tty->stop_bits); stream_write_uint8(output, tty->parity); stream_write_uint8(output, tty->word_length); break; case IOCTL_SERIAL_IMMEDIATE_CHAR: DEBUG_SVC("SERIAL_IMMEDIATE_CHAR"); stream_read_uint8(input, immediate); tty_write_data(tty, &immediate, 1); break; case IOCTL_SERIAL_CONFIG_SIZE: DEBUG_SVC("SERIAL_CONFIG_SIZE"); length = 4; stream_write_uint32(output, 0); break; case IOCTL_SERIAL_GET_CHARS: DEBUG_SVC("SERIAL_GET_CHARS"); length = 6; stream_write(output, tty->chars, 6); break; case IOCTL_SERIAL_SET_CHARS: DEBUG_SVC("SERIAL_SET_CHARS"); stream_read(input, tty->chars, 6); tty_set_termios(tty); break; case IOCTL_SERIAL_GET_HANDFLOW: length = 16; tty_get_termios(tty); stream_write_uint32(output, tty->control); stream_write_uint32(output, tty->xonoff); stream_write_uint32(output, tty->onlimit); stream_write_uint32(output, tty->offlimit); DEBUG_SVC("IOCTL_SERIAL_GET_HANDFLOW %X %X %X %X", tty->control, tty->xonoff, tty->onlimit, tty->offlimit); break; case IOCTL_SERIAL_SET_HANDFLOW: stream_read_uint32(input, tty->control); stream_read_uint32(input, tty->xonoff); stream_read_uint32(input, tty->onlimit); stream_read_uint32(input, tty->offlimit); DEBUG_SVC("IOCTL_SERIAL_SET_HANDFLOW %X %X %X %X", tty->control, tty->xonoff, tty->onlimit, tty->offlimit); tty_set_termios(tty); break; case IOCTL_SERIAL_SET_TIMEOUTS: stream_read_uint32(input, tty->read_interval_timeout); stream_read_uint32(input, tty->read_total_timeout_multiplier); stream_read_uint32(input, tty->read_total_timeout_constant); stream_read_uint32(input, tty->write_total_timeout_multiplier); stream_read_uint32(input, tty->write_total_timeout_constant); /* http://www.codeproject.com/KB/system/chaiyasit_t.aspx, see 'ReadIntervalTimeout' section http://msdn.microsoft.com/en-us/library/ms885171.aspx */ if (tty->read_interval_timeout == SERIAL_TIMEOUT_MAX) { tty->read_interval_timeout = 0; tty->read_total_timeout_multiplier = 0; } DEBUG_SVC("SERIAL_SET_TIMEOUTS read timeout %d %d %d", tty->read_interval_timeout, tty->read_total_timeout_multiplier, tty->read_total_timeout_constant); break; case IOCTL_SERIAL_GET_TIMEOUTS: DEBUG_SVC("SERIAL_GET_TIMEOUTS read timeout %d %d %d", tty->read_interval_timeout, tty->read_total_timeout_multiplier, tty->read_total_timeout_constant); length = 20; stream_write_uint32(output, tty->read_interval_timeout); stream_write_uint32(output, tty->read_total_timeout_multiplier); stream_write_uint32(output, tty->read_total_timeout_constant); stream_write_uint32(output, tty->write_total_timeout_multiplier); stream_write_uint32(output, tty->write_total_timeout_constant); break; case IOCTL_SERIAL_GET_WAIT_MASK: DEBUG_SVC("SERIAL_GET_WAIT_MASK %X", tty->wait_mask); length = 4; stream_write_uint32(output, tty->wait_mask); break; case IOCTL_SERIAL_SET_WAIT_MASK: stream_read_uint32(input, tty->wait_mask); DEBUG_SVC("SERIAL_SET_WAIT_MASK %X", tty->wait_mask); break; case IOCTL_SERIAL_SET_DTR: DEBUG_SVC("SERIAL_SET_DTR"); ioctl(tty->fd, TIOCMGET, &result); result |= TIOCM_DTR; ioctl(tty->fd, TIOCMSET, &result); tty->dtr = 1; break; case IOCTL_SERIAL_CLR_DTR: DEBUG_SVC("SERIAL_CLR_DTR"); ioctl(tty->fd, TIOCMGET, &result); result &= ~TIOCM_DTR; ioctl(tty->fd, TIOCMSET, &result); tty->dtr = 0; break; case IOCTL_SERIAL_SET_RTS: DEBUG_SVC("SERIAL_SET_RTS"); ioctl(tty->fd, TIOCMGET, &result); result |= TIOCM_RTS; ioctl(tty->fd, TIOCMSET, &result); tty->rts = 1; break; case IOCTL_SERIAL_CLR_RTS: DEBUG_SVC("SERIAL_CLR_RTS"); ioctl(tty->fd, TIOCMGET, &result); result &= ~TIOCM_RTS; ioctl(tty->fd, TIOCMSET, &result); tty->rts = 0; break; case IOCTL_SERIAL_GET_MODEMSTATUS: modemstate = 0; #ifdef TIOCMGET ioctl(tty->fd, TIOCMGET, &result); if (result & TIOCM_CTS) modemstate |= SERIAL_MS_CTS; if (result & TIOCM_DSR) modemstate |= SERIAL_MS_DSR; if (result & TIOCM_RNG) modemstate |= SERIAL_MS_RNG; if (result & TIOCM_CAR) modemstate |= SERIAL_MS_CAR; if (result & TIOCM_DTR) modemstate |= SERIAL_MS_DTR; if (result & TIOCM_RTS) modemstate |= SERIAL_MS_RTS; #endif DEBUG_SVC("SERIAL_GET_MODEMSTATUS %X", modemstate); length = 4; stream_write_uint32(output, modemstate); break; case IOCTL_SERIAL_GET_COMMSTATUS: length = 18; stream_write_uint32(output, 0); /* Errors */ stream_write_uint32(output, 0); /* Hold reasons */ result = 0; #ifdef TIOCINQ ioctl(tty->fd, TIOCINQ, &result); #endif stream_write_uint32(output, result); /* Amount in in queue */ if (result) DEBUG_SVC("SERIAL_GET_COMMSTATUS in queue %d", result); result = 0; #ifdef TIOCOUTQ ioctl(tty->fd, TIOCOUTQ, &result); #endif stream_write_uint32(output, result); /* Amount in out queue */ DEBUG_SVC("SERIAL_GET_COMMSTATUS out queue %d", result); stream_write_uint8(output, 0); /* EofReceived */ stream_write_uint8(output, 0); /* WaitForImmediate */ break; case IOCTL_SERIAL_PURGE: stream_read_uint32(input, purge_mask); DEBUG_SVC("SERIAL_PURGE purge_mask %X", purge_mask); /* See http://msdn.microsoft.com/en-us/library/ms901431.aspx PURGE_TXCLEAR Clears the output buffer, if the driver has one. PURGE_RXCLEAR Clears the input buffer, if the driver has one. It clearly states to clear the *driver* buffer, not the port buffer */ #ifdef DEBUG_SVC if (purge_mask & SERIAL_PURGE_TXCLEAR) DEBUG_SVC("Ignoring SERIAL_PURGE_TXCLEAR"); if (purge_mask & SERIAL_PURGE_RXCLEAR) DEBUG_SVC("Ignoring SERIAL_PURGE_RXCLEAR"); #endif if (purge_mask & SERIAL_PURGE_TXABORT) *abort_io |= SERIAL_ABORT_IO_WRITE; if (purge_mask & SERIAL_PURGE_RXABORT) *abort_io |= SERIAL_ABORT_IO_READ; break; case IOCTL_SERIAL_WAIT_ON_MASK: DEBUG_SVC("SERIAL_WAIT_ON_MASK %X", tty->wait_mask); tty->event_pending = 1; length = 4; if (serial_tty_get_event(tty, &result)) { DEBUG_SVC("WAIT end event = %X", result); stream_write_uint32(output, result); break; } ret = STATUS_PENDING; break; case IOCTL_SERIAL_SET_BREAK_ON: DEBUG_SVC("SERIAL_SET_BREAK_ON"); tcsendbreak(tty->fd, 0); break; case IOCTL_SERIAL_RESET_DEVICE: DEBUG_SVC("SERIAL_RESET_DEVICE"); break; case IOCTL_SERIAL_SET_BREAK_OFF: DEBUG_SVC("SERIAL_SET_BREAK_OFF"); break; case IOCTL_SERIAL_SET_XOFF: DEBUG_SVC("SERIAL_SET_XOFF"); break; case IOCTL_SERIAL_SET_XON: DEBUG_SVC("SERIAL_SET_XON"); tcflow(tty->fd, TCION); break; default: DEBUG_SVC("NOT FOUND IoControlCode SERIAL IOCTL %d", IoControlCode); return STATUS_INVALID_PARAMETER; } /* Write OutputBufferLength */ pos = stream_get_pos(output); stream_set_pos(output, 16); stream_write_uint32(output, length); stream_set_pos(output, pos); return ret; } boolean serial_tty_read(SERIAL_TTY* tty, uint8* buffer, uint32* Length) { long timeout = 90; struct termios *ptermios; ssize_t r; DEBUG_SVC("in"); ptermios = tty->ptermios; /* Set timeouts kind of like the windows serial timeout parameters. Multiply timeout with requested read size */ if (tty->read_total_timeout_multiplier | tty->read_total_timeout_constant) { timeout = (tty->read_total_timeout_multiplier * (*Length) + tty->read_total_timeout_constant + 99) / 100; } else if (tty->read_interval_timeout) { timeout = (tty->read_interval_timeout * (*Length) + 99) / 100; } /* If a timeout is set, do a blocking read, which times out after some time. It will make FreeRDP less responsive, but it will improve serial performance, by not reading one character at a time. */ if (timeout == 0) { ptermios->c_cc[VTIME] = 0; ptermios->c_cc[VMIN] = 0; } else { ptermios->c_cc[VTIME] = timeout; ptermios->c_cc[VMIN] = 1; } tcsetattr(tty->fd, TCSANOW, ptermios); memset(buffer, 0, *Length); r = read(tty->fd, buffer, *Length); if (r < 0) return false; tty->event_txempty = r; *Length = r; return true; } boolean serial_tty_write(SERIAL_TTY* tty, uint8* buffer, uint32 Length) { ssize_t r; uint32 event_txempty = Length; DEBUG_SVC("in"); while (Length > 0) { r = write(tty->fd, buffer, Length); if (r < 0) return false; Length -= r; buffer += r; } tty->event_txempty = event_txempty; return true; } void serial_tty_free(SERIAL_TTY* tty) { DEBUG_SVC("in"); if (tty->fd >= 0) { tcsetattr(tty->fd, TCSANOW, tty->pold_termios); close(tty->fd); } xfree(tty->ptermios); xfree(tty->pold_termios); xfree(tty); } SERIAL_TTY* serial_tty_new(const char* path, uint32 id) { SERIAL_TTY* tty; tty = xnew(SERIAL_TTY); tty->id = id; tty->fd = open(path, O_RDWR | O_NOCTTY | O_NONBLOCK); if (tty->fd < 0) { perror("open"); DEBUG_WARN("failed to open device %s", path); return NULL; } else DEBUG_SVC("tty fd %d successfully opened", tty->fd); tty->ptermios = (struct termios*) malloc(sizeof(struct termios)); memset(tty->ptermios, 0, sizeof(struct termios)); tty->pold_termios = (struct termios*) malloc(sizeof(struct termios)); memset(tty->pold_termios, 0, sizeof(struct termios)); tcgetattr(tty->fd, tty->pold_termios); if (!tty_get_termios(tty)) { DEBUG_WARN("%s access denied", path); fflush(stdout); return NULL; } tty->ptermios->c_iflag &= ~(IGNBRK | BRKINT | PARMRK | ISTRIP | INLCR | IGNCR | ICRNL | IXON); tty->ptermios->c_iflag = IGNPAR | ICRNL; tty->ptermios->c_oflag &= ~OPOST; tty->ptermios->c_lflag &= ~(ECHO | ECHONL | ICANON | ISIG | IEXTEN); tty->ptermios->c_cflag &= ~(CSIZE | PARENB); tty->ptermios->c_cflag |= CLOCAL | CREAD | CS8; tcsetattr(tty->fd, TCSANOW, tty->ptermios); tty->event_txempty = 0; tty->event_cts = 0; tty->event_dsr = 0; tty->event_rlsd = 0; tty->event_pending = 0; /* all read and writes should be non-blocking */ if (fcntl(tty->fd, F_SETFL, O_NONBLOCK) == -1) { DEBUG_WARN("%s fcntl", path); perror("fcntl"); return NULL; } tty->read_total_timeout_constant = 5; return tty; } boolean serial_tty_get_event(SERIAL_TTY* tty, uint32* result) { int bytes; boolean ret = false; DEBUG_SVC("in"); *result = 0; #ifdef TIOCINQ /* When wait_mask is set to zero we ought to cancel it all For reference: http://msdn.microsoft.com/en-us/library/aa910487.aspx */ if (tty->wait_mask == 0) { tty->event_pending = 0; return true; } ioctl(tty->fd, TIOCINQ, &bytes); if (bytes > 0) { DEBUG_SVC("bytes %d", bytes); if (bytes > tty->event_rlsd) { tty->event_rlsd = bytes; if (tty->wait_mask & SERIAL_EV_RLSD) { DEBUG_SVC("SERIAL_EV_RLSD"); *result |= SERIAL_EV_RLSD; ret = true; } } if ((bytes > 1) && (tty->wait_mask & SERIAL_EV_RXFLAG)) { DEBUG_SVC("SERIAL_EV_RXFLAG bytes %d", bytes); *result |= SERIAL_EV_RXFLAG; ret = true; } if ((tty->wait_mask & SERIAL_EV_RXCHAR)) { DEBUG_SVC("SERIAL_EV_RXCHAR bytes %d", bytes); *result |= SERIAL_EV_RXCHAR; ret = true; } } else { tty->event_rlsd = 0; } #endif #ifdef TIOCOUTQ ioctl(tty->fd, TIOCOUTQ, &bytes); if ((bytes == 0) && (tty->event_txempty > 0) && (tty->wait_mask & SERIAL_EV_TXEMPTY)) { DEBUG_SVC("SERIAL_EV_TXEMPTY"); *result |= SERIAL_EV_TXEMPTY; ret = true; } tty->event_txempty = bytes; #endif ioctl(tty->fd, TIOCMGET, &bytes); if ((bytes & TIOCM_DSR) != tty->event_dsr) { tty->event_dsr = bytes & TIOCM_DSR; if (tty->wait_mask & SERIAL_EV_DSR) { DEBUG_SVC("SERIAL_EV_DSR %s", (bytes & TIOCM_DSR) ? "ON" : "OFF"); *result |= SERIAL_EV_DSR; ret = true; } } if ((bytes & TIOCM_CTS) != tty->event_cts) { tty->event_cts = bytes & TIOCM_CTS; if (tty->wait_mask & SERIAL_EV_CTS) { DEBUG_SVC("SERIAL_EV_CTS %s", (bytes & TIOCM_CTS) ? "ON" : "OFF"); *result |= SERIAL_EV_CTS; ret = true; } } if (ret) tty->event_pending = 0; return ret; } static boolean tty_get_termios(SERIAL_TTY* tty) { speed_t speed; struct termios *ptermios; ptermios = tty->ptermios; DEBUG_SVC("tcgetattr? %d", tcgetattr(tty->fd, ptermios) >= 0); if (tcgetattr(tty->fd, ptermios) < 0) return false; speed = cfgetispeed(ptermios); switch (speed) { #ifdef B75 case B75: tty->baud_rate = 75; break; #endif #ifdef B110 case B110: tty->baud_rate = 110; break; #endif #ifdef B134 case B134: tty->baud_rate = 134; break; #endif #ifdef B150 case B150: tty->baud_rate = 150; break; #endif #ifdef B300 case B300: tty->baud_rate = 300; break; #endif #ifdef B600 case B600: tty->baud_rate = 600; break; #endif #ifdef B1200 case B1200: tty->baud_rate = 1200; break; #endif #ifdef B1800 case B1800: tty->baud_rate = 1800; break; #endif #ifdef B2400 case B2400: tty->baud_rate = 2400; break; #endif #ifdef B4800 case B4800: tty->baud_rate = 4800; break; #endif #ifdef B9600 case B9600: tty->baud_rate = 9600; break; #endif #ifdef B19200 case B19200: tty->baud_rate = 19200; break; #endif #ifdef B38400 case B38400: tty->baud_rate = 38400; break; #endif #ifdef B57600 case B57600: tty->baud_rate = 57600; break; #endif #ifdef B115200 case B115200: tty->baud_rate = 115200; break; #endif #ifdef B230400 case B230400: tty->baud_rate = 230400; break; #endif #ifdef B460800 case B460800: tty->baud_rate = 460800; break; #endif default: tty->baud_rate = 9600; break; } speed = cfgetospeed(ptermios); tty->dtr = (speed == B0) ? 0 : 1; tty->stop_bits = (ptermios->c_cflag & CSTOPB) ? SERIAL_STOP_BITS_2 : SERIAL_STOP_BITS_1; tty->parity = (ptermios->c_cflag & PARENB) ? ((ptermios->c_cflag & PARODD) ? SERIAL_ODD_PARITY : SERIAL_EVEN_PARITY) : SERIAL_NO_PARITY; switch (ptermios->c_cflag & CSIZE) { case CS5: tty->word_length = 5; break; case CS6: tty->word_length = 6; break; case CS7: tty->word_length = 7; break; default: tty->word_length = 8; break; } if (ptermios->c_cflag & CRTSCTS) { tty->control = SERIAL_DTR_CONTROL | SERIAL_CTS_HANDSHAKE | SERIAL_ERROR_ABORT; } else { tty->control = SERIAL_DTR_CONTROL | SERIAL_ERROR_ABORT; } tty->xonoff = SERIAL_DSR_SENSITIVITY; if (ptermios->c_iflag & IXON) tty->xonoff |= SERIAL_XON_HANDSHAKE; if (ptermios->c_iflag & IXOFF) tty->xonoff |= SERIAL_XOFF_HANDSHAKE; tty->chars[SERIAL_CHAR_XON] = ptermios->c_cc[VSTART]; tty->chars[SERIAL_CHAR_XOFF] = ptermios->c_cc[VSTOP]; tty->chars[SERIAL_CHAR_EOF] = ptermios->c_cc[VEOF]; tty->chars[SERIAL_CHAR_BREAK] = ptermios->c_cc[VINTR]; tty->chars[SERIAL_CHAR_ERROR] = ptermios->c_cc[VKILL]; return true; } static void tty_set_termios(SERIAL_TTY* tty) { speed_t speed; struct termios *ptermios; DEBUG_SVC("in"); ptermios = tty->ptermios; switch (tty->baud_rate) { #ifdef B75 case 75: speed = B75; break; #endif #ifdef B110 case 110: speed = B110; break; #endif #ifdef B134 case 134: speed = B134; break; #endif #ifdef B150 case 150: speed = B150; break; #endif #ifdef B300 case 300: speed = B300; break; #endif #ifdef B600 case 600: speed = B600; break; #endif #ifdef B1200 case 1200: speed = B1200; break; #endif #ifdef B1800 case 1800: speed = B1800; break; #endif #ifdef B2400 case 2400: speed = B2400; break; #endif #ifdef B4800 case 4800: speed = B4800; break; #endif #ifdef B9600 case 9600: speed = B9600; break; #endif #ifdef B19200 case 19200: speed = B19200; break; #endif #ifdef B38400 case 38400: speed = B38400; break; #endif #ifdef B57600 case 57600: speed = B57600; break; #endif #ifdef B115200 case 115200: speed = B115200; break; #endif #ifdef B230400 case 230400: speed = B115200; break; #endif #ifdef B460800 case 460800: speed = B115200; break; #endif default: speed = B9600; break; } #ifdef CBAUD ptermios->c_cflag &= ~CBAUD; ptermios->c_cflag |= speed; #else /* on systems with separate ispeed and ospeed, we can remember the speed in ispeed while changing DTR with ospeed */ cfsetispeed(tty->ptermios, speed); cfsetospeed(tty->ptermios, tty->dtr ? speed : 0); #endif ptermios->c_cflag &= ~(CSTOPB | PARENB | PARODD | CSIZE | CRTSCTS); switch (tty->stop_bits) { case SERIAL_STOP_BITS_2: ptermios->c_cflag |= CSTOPB; break; default: ptermios->c_cflag &= ~CSTOPB; break; } switch (tty->parity) { case SERIAL_EVEN_PARITY: ptermios->c_cflag |= PARENB; break; case SERIAL_ODD_PARITY: ptermios->c_cflag |= PARENB | PARODD; break; case SERIAL_NO_PARITY: ptermios->c_cflag &= ~(PARENB | PARODD); break; } switch (tty->word_length) { case 5: ptermios->c_cflag |= CS5; break; case 6: ptermios->c_cflag |= CS6; break; case 7: ptermios->c_cflag |= CS7; break; default: ptermios->c_cflag |= CS8; break; } #if 0 if (tty->rts) ptermios->c_cflag |= CRTSCTS; else ptermios->c_cflag &= ~CRTSCTS; #endif if (tty->control & SERIAL_CTS_HANDSHAKE) { ptermios->c_cflag |= CRTSCTS; } else { ptermios->c_cflag &= ~CRTSCTS; } if (tty->xonoff & SERIAL_XON_HANDSHAKE) { ptermios->c_iflag |= IXON | IMAXBEL; } if (tty->xonoff & SERIAL_XOFF_HANDSHAKE) { ptermios->c_iflag |= IXOFF | IMAXBEL; } if ((tty->xonoff & (SERIAL_XOFF_HANDSHAKE | SERIAL_XON_HANDSHAKE)) == 0) { ptermios->c_iflag &= ~IXON; ptermios->c_iflag &= ~IXOFF; } ptermios->c_cc[VSTART] = tty->chars[SERIAL_CHAR_XON]; ptermios->c_cc[VSTOP] = tty->chars[SERIAL_CHAR_XOFF]; ptermios->c_cc[VEOF] = tty->chars[SERIAL_CHAR_EOF]; ptermios->c_cc[VINTR] = tty->chars[SERIAL_CHAR_BREAK]; ptermios->c_cc[VKILL] = tty->chars[SERIAL_CHAR_ERROR]; tcsetattr(tty->fd, TCSANOW, ptermios); } static uint32 tty_write_data(SERIAL_TTY* tty, uint8* data, int len) { ssize_t r; DEBUG_SVC("in"); r = write(tty->fd, data, len); if (r < 0) return tty_get_error_status(); tty->event_txempty = r; return STATUS_SUCCESS; } static int tty_get_error_status() { DEBUG_SVC("in errno %d", errno); switch (errno) { case EACCES: case ENOTDIR: case ENFILE: return STATUS_ACCESS_DENIED; case EISDIR: return STATUS_FILE_IS_A_DIRECTORY; case EEXIST: return STATUS_OBJECT_NAME_COLLISION; case EBADF: return STATUS_INVALID_HANDLE; default: return STATUS_NO_SUCH_FILE; } } FreeRDP-1.0.2/channels/rdpdr/serial/serial_tty.h000066400000000000000000000037161207112532300214610ustar00rootroot00000000000000/** * FreeRDP: A Remote Desktop Protocol client. * Serial Port Device Service Virtual Channel * * Copyright 2011 O.S. Systems Software Ltda. * Copyright 2011 Eduardo Fiss Beloni * * 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. */ #ifndef __SERIAL_TTY_H #define __SERIAL_TTY_H #include #include #include typedef struct _SERIAL_TTY SERIAL_TTY; struct _SERIAL_TTY { uint32 id; int fd; int dtr; int rts; uint32 control; uint32 xonoff; uint32 onlimit; uint32 offlimit; uint32 baud_rate; uint32 queue_in_size; uint32 queue_out_size; uint32 wait_mask; uint32 read_interval_timeout; uint32 read_total_timeout_multiplier; uint32 read_total_timeout_constant; uint32 write_total_timeout_multiplier; uint32 write_total_timeout_constant; uint8 stop_bits; uint8 parity; uint8 word_length; uint8 chars[6]; struct termios* ptermios; struct termios* pold_termios; int event_txempty; int event_cts; int event_dsr; int event_rlsd; int event_pending; }; SERIAL_TTY* serial_tty_new(const char* path, uint32 id); void serial_tty_free(SERIAL_TTY* tty); boolean serial_tty_read(SERIAL_TTY* tty, uint8* buffer, uint32* Length); boolean serial_tty_write(SERIAL_TTY* tty, uint8* buffer, uint32 Length); uint32 serial_tty_control(SERIAL_TTY* tty, uint32 IoControlCode, STREAM* input, STREAM* output, uint32* abort_io); boolean serial_tty_get_event(SERIAL_TTY* tty, uint32* result); #endif /* __SERIAL_TTY_H */ FreeRDP-1.0.2/channels/rdpdr/smartcard/000077500000000000000000000000001207112532300176235ustar00rootroot00000000000000FreeRDP-1.0.2/channels/rdpdr/smartcard/CMakeLists.txt000066400000000000000000000021651207112532300223670ustar00rootroot00000000000000# FreeRDP: A Remote Desktop Protocol Client # FreeRDP cmake build script # # Copyright 2011 O.S. Systems Software Ltda. # Copyright 2011 Otavio Salvador # Copyright 2011 Marc-Andre Moreau # # 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(SCARD_SRCS scard_main.c scard_operations.c ) include_directories(..) include_directories(${PCSC_INCLUDE_DIR}) add_library(scard ${SCARD_SRCS}) set_target_properties(scard PROPERTIES PREFIX "") target_link_libraries(scard freerdp-utils) target_link_libraries(scard ${PCSC_LIBRARIES}) install(TARGETS scard DESTINATION ${FREERDP_PLUGIN_PATH}) FreeRDP-1.0.2/channels/rdpdr/smartcard/scard_main.c000066400000000000000000000105151207112532300220710ustar00rootroot00000000000000/* FreeRDP: A Remote Desktop Protocol client. Redirected Smart Card Device Service Copyright 2011 O.S. Systems Software Ltda. Copyright 2011 Eduardo Fiss Beloni Copyright 2011 Anthony Tong 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. */ #include "config.h" #include #include #include #include #include #include #include "rdpdr_types.h" #include "rdpdr_constants.h" #include "scard_main.h" static void scard_free(DEVICE* dev) { SCARD_DEVICE* scard = (SCARD_DEVICE*)dev; IRP* irp; freerdp_thread_stop(scard->thread); freerdp_thread_free(scard->thread); while ((irp = (IRP*)list_dequeue(scard->irp_list)) != NULL) irp->Discard(irp); list_free(scard->irp_list); xfree(dev); return; } static void scard_process_irp(SCARD_DEVICE* scard, IRP* irp) { switch (irp->MajorFunction) { case IRP_MJ_DEVICE_CONTROL: scard_device_control(scard, irp); break; default: printf("MajorFunction 0x%X unexpected for smartcards.", irp->MajorFunction); DEBUG_WARN("Smartcard MajorFunction 0x%X not supported.", irp->MajorFunction); irp->IoStatus = STATUS_NOT_SUPPORTED; irp->Complete(irp); break; } } static void scard_process_irp_list(SCARD_DEVICE* scard) { IRP *irp; while (!freerdp_thread_is_stopped(scard->thread)) { freerdp_thread_lock(scard->thread); irp = (IRP *) list_dequeue(scard->irp_list); freerdp_thread_unlock(scard->thread); if (irp == NULL) break; scard_process_irp(scard, irp); } } struct scard_irp_thread_args { SCARD_DEVICE* scard; IRP* irp; freerdp_thread* thread; }; static void scard_process_irp_thread_func(struct scard_irp_thread_args* args) { scard_process_irp(args->scard, args->irp); freerdp_thread_free(args->thread); xfree(args); } static void * scard_thread_func(void* arg) { SCARD_DEVICE* scard = (SCARD_DEVICE*) arg; while (1) { freerdp_thread_wait(scard->thread); if (freerdp_thread_is_stopped(scard->thread)) break; freerdp_thread_reset(scard->thread); scard_process_irp_list(scard); } freerdp_thread_quit(scard->thread); return NULL; } static void scard_irp_request(DEVICE* device, IRP* irp) { SCARD_DEVICE* scard = (SCARD_DEVICE*)device; if (irp->MajorFunction == IRP_MJ_DEVICE_CONTROL && scard_async_op(irp)) { /* * certain potentially long running operations * get their own thread * TODO: revise this mechanism.. maybe worker pool */ struct scard_irp_thread_args *args = xmalloc(sizeof(struct scard_irp_thread_args)); args->thread = freerdp_thread_new(); args->scard = scard; args->irp = irp; freerdp_thread_start(args->thread, scard_process_irp_thread_func, args); return; } freerdp_thread_lock(scard->thread); list_enqueue(scard->irp_list, irp); freerdp_thread_unlock(scard->thread); freerdp_thread_signal(scard->thread); } int DeviceServiceEntry(PDEVICE_SERVICE_ENTRY_POINTS pEntryPoints) { SCARD_DEVICE* scard; char* name; char* path; int i, length; name = (char *)pEntryPoints->plugin_data->data[1]; path = (char *)pEntryPoints->plugin_data->data[2]; if (name) { /* TODO: check if server supports sc redirect (version 5.1) */ scard = xnew(SCARD_DEVICE); scard->device.type = RDPDR_DTYP_SMARTCARD; scard->device.name = "SCARD"; scard->device.IRPRequest = scard_irp_request; scard->device.Free = scard_free; length = strlen(scard->device.name); scard->device.data = stream_new(length + 1); for (i = 0; i <= length; i++) stream_write_uint8(scard->device.data, name[i] < 0 ? '_' : name[i]); scard->path = path; scard->irp_list = list_new(); scard->thread = freerdp_thread_new(); pEntryPoints->RegisterDevice(pEntryPoints->devman, (DEVICE *)scard); freerdp_thread_start(scard->thread, scard_thread_func, scard); } return 0; } FreeRDP-1.0.2/channels/rdpdr/smartcard/scard_main.h000066400000000000000000000024501207112532300220750ustar00rootroot00000000000000/* FreeRDP: A Remote Desktop Protocol client. Redirected Smart Card Device Service Copyright 2011 O.S. Systems Software Ltda. Copyright 2011 Eduardo Fiss Beloni 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. */ #ifndef __SCARD_MAIN_H #define __SCARD_MAIN_H #include #include "devman.h" #include "rdpdr_types.h" #include struct _SCARD_DEVICE { DEVICE device; char * name; char * path; LIST* irp_list; freerdp_thread* thread; }; typedef struct _SCARD_DEVICE SCARD_DEVICE; #ifdef WITH_DEBUG_SCARD #define DEBUG_SCARD(fmt, ...) DEBUG_CLASS(SCARD, fmt, ## __VA_ARGS__) #else #define DEBUG_SCARD(fmt, ...) DEBUG_NULL(fmt, ## __VA_ARGS__) #endif boolean scard_async_op(IRP*); void scard_device_control(SCARD_DEVICE*, IRP*); #endif FreeRDP-1.0.2/channels/rdpdr/smartcard/scard_operations.c000066400000000000000000001136221207112532300233330ustar00rootroot00000000000000/* FreeRDP: A Remote Desktop Protocol client. Redirected Smart Card Device Service Copyright (C) Alexi Volkov 2006 Copyright 2011 O.S. Systems Software Ltda. Copyright 2011 Anthony Tong 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. */ #include "config.h" #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include "rdpdr_types.h" #include "rdpdr_constants.h" #include "scard_main.h" /* [MS-RDPESC] 3.1.4 */ #define SCARD_IOCTL_ESTABLISH_CONTEXT 0x00090014 /* EstablishContext */ #define SCARD_IOCTL_RELEASE_CONTEXT 0x00090018 /* ReleaseContext */ #define SCARD_IOCTL_IS_VALID_CONTEXT 0x0009001C /* IsValidContext */ #define SCARD_IOCTL_LIST_READER_GROUPS 0x00090020 /* ListReaderGroups */ #define SCARD_IOCTL_LIST_READERS 0x00090028 /* ListReadersA */ #define SCARD_IOCTL_INTRODUCE_READER_GROUP 0x00090050 /* IntroduceReaderGroup */ #define SCARD_IOCTL_FORGET_READER_GROUP 0x00090058 /* ForgetReader */ #define SCARD_IOCTL_INTRODUCE_READER 0x00090060 /* IntroduceReader */ #define SCARD_IOCTL_FORGET_READER 0x00090068 /* IntroduceReader */ #define SCARD_IOCTL_ADD_READER_TO_GROUP 0x00090070 /* AddReaderToGroup */ #define SCARD_IOCTL_REMOVE_READER_FROM_GROUP 0x00090078 /* RemoveReaderFromGroup */ #define SCARD_IOCTL_GET_STATUS_CHANGE 0x000900A0 /* GetStatusChangeA */ #define SCARD_IOCTL_CANCEL 0x000900A8 /* Cancel */ #define SCARD_IOCTL_CONNECT 0x000900AC /* ConnectA */ #define SCARD_IOCTL_RECONNECT 0x000900B4 /* Reconnect */ #define SCARD_IOCTL_DISCONNECT 0x000900B8 /* Disconnect */ #define SCARD_IOCTL_BEGIN_TRANSACTION 0x000900BC /* BeginTransaction */ #define SCARD_IOCTL_END_TRANSACTION 0x000900C0 /* EndTransaction */ #define SCARD_IOCTL_STATE 0x000900C4 /* State */ #define SCARD_IOCTL_STATUS 0x000900C8 /* StatusA */ #define SCARD_IOCTL_TRANSMIT 0x000900D0 /* Transmit */ #define SCARD_IOCTL_CONTROL 0x000900D4 /* Control */ #define SCARD_IOCTL_GETATTRIB 0x000900D8 /* GetAttrib */ #define SCARD_IOCTL_SETATTRIB 0x000900DC /* SetAttrib */ #define SCARD_IOCTL_ACCESS_STARTED_EVENT 0x000900E0 /* SCardAccessStartedEvent */ #define SCARD_IOCTL_LOCATE_CARDS_BY_ATR 0x000900E8 /* LocateCardsByATR */ #define SCARD_INPUT_LINKED 0xFFFFFFFF /* Decode Win CTL_CODE values */ #define WIN_CTL_FUNCTION(ctl_code) ((ctl_code & 0x3FFC) >> 2) #define WIN_CTL_DEVICE_TYPE(ctl_code) (ctl_code >> 16) #define WIN_FILE_DEVICE_SMARTCARD 0x00000031 static uint32 sc_output_string(IRP* irp, char *src, boolean wide) { uint8* p; uint32 len; p = stream_get_tail(irp->output); len = strlen(src) + 1; if (wide) { int i; for (i = 0; i < len; i++ ) { p[2 * i] = src[i] < 0 ? '?' : src[i]; p[2 * i + 1] = '\0'; } len *= 2; } else { memcpy(p, src, len); } stream_seek(irp->output, len); return len; } static void sc_output_alignment(IRP *irp, uint32 seed) { uint32 size = stream_get_length(irp->output) - 20; uint32 add = (seed - (size % seed)) % seed; if (add > 0) stream_write_zero(irp->output, add); } static void sc_output_repos(IRP* irp, uint32 written) { uint32 add = (4 - (written % 4)) % 4; if (add > 0) stream_write_zero(irp->output, add); } static uint32 sc_output_return(IRP* irp, uint32 rv) { stream_write_zero(irp->output, 256); return rv; } static void sc_output_buffer_limit(IRP* irp, char *buffer, unsigned int length, unsigned int highLimit) { int header = (length < 0) ? (0) : ((length > highLimit) ? (highLimit) : (length)); stream_write_uint32(irp->output, header); if (length <= 0) { stream_write_uint32(irp->output, 0); } else { if (header < length) length = header; stream_write(irp->output, buffer, length); sc_output_repos(irp, length); } } static void sc_output_buffer(IRP* irp, char *buffer, unsigned int length) { sc_output_buffer_limit(irp, buffer, length, 0x7FFFFFFF); } static void sc_output_buffer_start_limit(IRP *irp, int length, int highLimit) { int header = (length < 0) ? (0) : ((length > highLimit) ? (highLimit) : (length)); stream_write_uint32(irp->output, header); stream_write_uint32(irp->output, 0x00000001); /* Magic DWORD - any non zero */ } static void sc_output_buffer_start(IRP *irp, int length) { sc_output_buffer_start_limit(irp, length, 0x7FFFFFFF); } static uint32 sc_input_string(IRP* irp, char **dest, uint32 dataLength, boolean wide) { char *buffer; int bufferSize; bufferSize = wide ? (2 * dataLength) : dataLength; buffer = xmalloc(bufferSize + 2); /* reserve 2 bytes for the '\0' */ stream_read(irp->input, buffer, bufferSize); if (wide) { int i; for (i = 0; i < dataLength; i++) { if ((buffer[2 * i] < 0) || (buffer[2 * i + 1] != 0)) buffer[i] = '?'; else buffer[i] = buffer[2 * i]; } } buffer[dataLength] = '\0'; *dest = buffer; return bufferSize; } static void sc_input_repos(IRP* irp, uint32 read) { uint32 add = 4 - (read % 4); if (add < 4 && add > 0) stream_seek(irp->input, add); } static void sc_input_reader_name(IRP* irp, char **dest, boolean wide) { uint32 dataLength; stream_seek(irp->input, 8); stream_read_uint32(irp->input, dataLength); DEBUG_SCARD("datalength %d", dataLength); sc_input_repos(irp, sc_input_string(irp, dest, dataLength, wide)); } static void sc_input_skip_linked(IRP* irp) { uint32 len; stream_read_uint32(irp->input, len); if (len > 0) { stream_seek(irp->input, len); sc_input_repos(irp, len); } } static uint32 sc_map_state(uint32 state) { /* is this mapping still needed? */ if (state & SCARD_SPECIFIC) state = 0x00000006; else if (state & SCARD_NEGOTIABLE) state = 0x00000006; else if (state & SCARD_POWERED) state = 0x00000004; else if (state & SCARD_SWALLOWED) state = 0x00000003; else if (state & SCARD_PRESENT) state = 0x00000002; else if (state & SCARD_ABSENT) state = 0x00000001; else state = 0x00000000; return state; } static uint32 handle_EstablishContext(IRP* irp) { uint32 len, rv; uint32 scope; SCARDCONTEXT hContext = -1; stream_seek(irp->input, 8); stream_read_uint32(irp->input, len); if (len != 8) return SCARD_F_INTERNAL_ERROR; stream_seek_uint32(irp->input); stream_read_uint32(irp->input, scope); rv = SCardEstablishContext(scope, NULL, NULL, &hContext); stream_write_uint32(irp->output, 4); // ? stream_write_uint32(irp->output, -1); // ? stream_write_uint32(irp->output, 4); stream_write_uint32(irp->output, hContext); /* TODO: store hContext in allowed context list */ return SCARD_S_SUCCESS; } static uint32 handle_ReleaseContext(IRP* irp) { uint32 len, rv; SCARDCONTEXT hContext = -1; stream_seek(irp->input, 8); stream_read_uint32(irp->input, len); stream_seek(irp->input, 0x10); stream_read_uint32(irp->input, hContext); rv = SCardReleaseContext(hContext); if (rv) DEBUG_SCARD("%s (0x%08x)", pcsc_stringify_error(rv), (unsigned) rv); else DEBUG_SCARD("success 0x%08lx", hContext); return rv; } static uint32 handle_IsValidContext(IRP* irp) { uint32 rv; SCARDCONTEXT hContext; stream_seek(irp->input, 0x1C); stream_read_uint32(irp->input, hContext); rv = SCardIsValidContext(hContext); if (rv) DEBUG_SCARD("Failure: %s (0x%08x)", pcsc_stringify_error(rv), (unsigned) rv); else DEBUG_SCARD("Success context: 0x%08x", (unsigned) hContext); stream_write_uint32(irp->output, rv); return rv; } static uint32 handle_ListReaders(IRP* irp, boolean wide) { uint32 len, rv; SCARDCONTEXT hContext; DWORD dwReaders; char *readerList = NULL, *walker; int elemLength, dataLength; int pos, poslen1, poslen2; stream_seek(irp->input, 8); stream_read_uint32(irp->input, len); stream_seek(irp->input, 0x1c); stream_read_uint32(irp->input, len); if (len != 4) return SCARD_F_INTERNAL_ERROR; stream_read_uint32(irp->input, hContext); /* ignore rest of [MS-RDPESC] 2.2.2.4 ListReaders_Call */ rv = SCARD_S_SUCCESS; #ifdef SCARD_AUTOALLOCATE dwReaders = SCARD_AUTOALLOCATE; rv = SCardListReaders(hContext, NULL, (LPSTR) &readerList, &dwReaders); #else rv = SCardListReaders(hContext, NULL, NULL, &dwReaders); readerList = xmalloc(dwReaders); rv = SCardListReaders(hContext, NULL, readerList, &dwReaders); #endif if (rv != SCARD_S_SUCCESS) { DEBUG_SCARD("Failure: %s (0x%08x)", pcsc_stringify_error(rv), (unsigned) rv); return rv; } /* DEBUG_SCARD("Success 0x%08x %d %d", (unsigned) hContext, (unsigned) cchReaders, (int) strlen(readerList));*/ poslen1 = stream_get_pos(irp->output); stream_seek_uint32(irp->output); stream_write_uint32(irp->output, 0x01760650); poslen2 = stream_get_pos(irp->output); stream_seek_uint32(irp->output); walker = readerList; dataLength = 0; while (1) { elemLength = strlen(walker); if (elemLength == 0) break; dataLength += sc_output_string(irp, walker, wide); walker += elemLength + 1; elemLength = strlen(walker); } dataLength += sc_output_string(irp, "\0", wide); pos = stream_get_pos(irp->output); stream_set_pos(irp->output, poslen1); stream_write_uint32(irp->output, dataLength); stream_set_pos(irp->output, poslen2); stream_write_uint32(irp->output, dataLength); stream_set_pos(irp->output, pos); sc_output_repos(irp, dataLength); sc_output_alignment(irp, 8); #ifdef SCARD_AUTOALLOCATE SCardFreeMemory(hContext, readerList); #else xfree(readerList); #endif return rv; } static uint32 handle_GetStatusChange(IRP* irp, boolean wide) { LONG rv; SCARDCONTEXT hContext; DWORD dwTimeout = 0; DWORD readerCount = 0; SCARD_READERSTATE *readerStates, *cur; int i; stream_seek(irp->input, 0x18); stream_read_uint32(irp->input, dwTimeout); stream_read_uint32(irp->input, readerCount); stream_seek(irp->input, 8); stream_read_uint32(irp->input, hContext); stream_seek(irp->input, 4); DEBUG_SCARD("context: 0x%08x, timeout: 0x%08x, count: %d", (unsigned) hContext, (unsigned) dwTimeout, (int) readerCount); if (readerCount > 0) { readerStates = xzalloc(readerCount * sizeof(SCARD_READERSTATE)); if (!readerStates) return sc_output_return(irp, SCARD_E_NO_MEMORY); for (i = 0; i < readerCount; i++) { cur = &readerStates[i]; stream_seek(irp->input, 4); /* * TODO: on-wire is little endian; need to either * convert to host endian or fix the headers to * request the order we want */ stream_read_uint32(irp->input, cur->dwCurrentState); stream_read_uint32(irp->input, cur->dwEventState); stream_read_uint32(irp->input, cur->cbAtr); stream_read(irp->input, cur->rgbAtr, 32); stream_seek(irp->input, 4); /* reset high bytes? */ cur->dwCurrentState &= 0x0000FFFF; cur->dwEventState &= 0x0000FFFF; cur->dwEventState = 0; } for (i = 0; i < readerCount; i++) { cur = &readerStates[i]; uint32 dataLength; stream_seek(irp->input, 8); stream_read_uint32(irp->input, dataLength); sc_input_repos(irp, sc_input_string(irp, (char **) &cur->szReader, dataLength, wide)); DEBUG_SCARD(" \"%s\"", cur->szReader ? cur->szReader : "NULL"); DEBUG_SCARD(" user: 0x%08x, state: 0x%08x, event: 0x%08x", (unsigned) cur->pvUserData, (unsigned) cur->dwCurrentState, (unsigned) cur->dwEventState); if (strcmp(cur->szReader, "\\\\?PnP?\\Notification") == 0) cur->dwCurrentState |= SCARD_STATE_IGNORE; } } else { readerStates = NULL; } rv = SCardGetStatusChange(hContext, (DWORD) dwTimeout, readerStates, (DWORD) readerCount); if (rv != SCARD_S_SUCCESS) DEBUG_SCARD("Failure: %s (0x%08x)", pcsc_stringify_error(rv), (unsigned) rv); else DEBUG_SCARD("Success"); stream_write_uint32(irp->output, readerCount); stream_write_uint32(irp->output, 0x00084dd8); stream_write_uint32(irp->output, readerCount); for (i = 0; i < readerCount; i++) { cur = &readerStates[i]; DEBUG_SCARD(" \"%s\"", cur->szReader ? cur->szReader : "NULL"); DEBUG_SCARD(" user: 0x%08x, state: 0x%08x, event: 0x%08x\n", (unsigned) cur->pvUserData, (unsigned) cur->dwCurrentState, (unsigned) cur->dwEventState); /* TODO: do byte conversions if necessary */ stream_write_uint32(irp->output, cur->dwCurrentState); stream_write_uint32(irp->output, cur->dwEventState); stream_write_uint32(irp->output, cur->cbAtr); stream_write(irp->output, cur->rgbAtr, 32); stream_write_zero(irp->output, 4); xfree((void *)cur->szReader); } sc_output_alignment(irp, 8); xfree(readerStates); return rv; } static uint32 handle_Cancel(IRP *irp) { LONG rv; SCARDCONTEXT hContext; stream_seek(irp->input, 0x1C); stream_read_uint32(irp->input, hContext); rv = SCardCancel(hContext); if (rv != SCARD_S_SUCCESS) DEBUG_SCARD("Failure: %s (0x%08x)\n", pcsc_stringify_error(rv), (unsigned) rv); else DEBUG_SCARD("Success context: 0x%08x %s\n", (unsigned) hContext, pcsc_stringify_error(rv)); sc_output_alignment(irp, 8); return rv; } static uint32 handle_Connect(IRP* irp, boolean wide) { LONG rv; SCARDCONTEXT hContext; char *readerName = NULL; DWORD dwShareMode = 0; DWORD dwPreferredProtocol = 0; DWORD dwActiveProtocol = 0; SCARDHANDLE hCard; stream_seek(irp->input, 0x1c); stream_read_uint32(irp->input, dwShareMode); stream_read_uint32(irp->input, dwPreferredProtocol); sc_input_reader_name(irp, &readerName, wide); stream_seek(irp->input, 4); stream_read_uint32(irp->input, hContext); DEBUG_SCARD("(context: 0x%08x, share: 0x%08x, proto: 0x%08x, reader: \"%s\")", (unsigned) hContext, (unsigned) dwShareMode, (unsigned) dwPreferredProtocol, readerName ? readerName : "NULL"); rv = SCardConnect(hContext, readerName, (DWORD) dwShareMode, (DWORD) dwPreferredProtocol, &hCard, (DWORD *) &dwActiveProtocol); if (rv != SCARD_S_SUCCESS) DEBUG_SCARD("Failure: %s 0x%08x", pcsc_stringify_error(rv), (unsigned) rv); else DEBUG_SCARD("Success 0x%08x", (unsigned) hCard); stream_write_uint32(irp->output, 0x00000000); stream_write_uint32(irp->output, 0x00000000); stream_write_uint32(irp->output, 0x00000004); stream_write_uint32(irp->output, 0x016Cff34); stream_write_uint32(irp->output, dwActiveProtocol); stream_write_uint32(irp->output, 0x00000004); stream_write_uint32(irp->output, hCard); stream_seek(irp->output, 28); sc_output_alignment(irp, 8); xfree(readerName); return rv; } static uint32 handle_Reconnect(IRP* irp) { LONG rv; SCARDCONTEXT hContext; SCARDHANDLE hCard; DWORD dwShareMode = 0; DWORD dwPreferredProtocol = 0; DWORD dwInitialization = 0; DWORD dwActiveProtocol = 0; stream_seek(irp->input, 0x20); stream_read_uint32(irp->input, dwShareMode); stream_read_uint32(irp->input, dwPreferredProtocol); stream_read_uint32(irp->input, dwInitialization); stream_seek(irp->input, 0x4); stream_read_uint32(irp->input, hContext); stream_seek(irp->input, 0x4); stream_read_uint32(irp->input, hCard); DEBUG_SCARD("(context: 0x%08x, hcard: 0x%08x, share: 0x%08x, proto: 0x%08x, init: 0x%08x)", (unsigned) hContext, (unsigned) hCard, (unsigned) dwShareMode, (unsigned) dwPreferredProtocol, (unsigned) dwInitialization); rv = SCardReconnect(hCard, (DWORD) dwShareMode, (DWORD) dwPreferredProtocol, (DWORD) dwInitialization, (LPDWORD) &dwActiveProtocol); if (rv != SCARD_S_SUCCESS) DEBUG_SCARD("Failure: %s (0x%08x)", pcsc_stringify_error(rv), (unsigned) rv); else DEBUG_SCARD("Success (proto: 0x%08x)", (unsigned) dwActiveProtocol); sc_output_alignment(irp, 8); stream_write_uint32(irp->output, dwActiveProtocol); /* reversed? */ return rv; } static uint32 handle_Disconnect(IRP* irp) { LONG rv; SCARDCONTEXT hContext; SCARDHANDLE hCard; DWORD dwDisposition = 0; stream_seek(irp->input, 0x20); stream_read_uint32(irp->input, dwDisposition); stream_seek(irp->input, 4); stream_read_uint32(irp->input, hContext); stream_seek(irp->input, 4); stream_read_uint32(irp->input, hCard); DEBUG_SCARD("(context: 0x%08x, hcard: 0x%08x, disposition: 0x%08x)", (unsigned) hContext, (unsigned) hCard, (unsigned) dwDisposition); rv = SCardDisconnect(hCard, (DWORD) dwDisposition); if (rv != SCARD_S_SUCCESS) DEBUG_SCARD("Failure: %s (0x%08x)", pcsc_stringify_error(rv), (unsigned) rv); else DEBUG_SCARD("Success"); sc_output_alignment(irp, 8); return rv; } static uint32 handle_BeginTransaction(IRP* irp) { LONG rv; SCARDCONTEXT hCard; stream_seek(irp->input, 0x30); stream_read_uint32(irp->input, hCard); rv = SCardBeginTransaction(hCard); if (rv != SCARD_S_SUCCESS) DEBUG_SCARD("Failure: %s (0x%08x)", pcsc_stringify_error(rv), (unsigned) rv); else DEBUG_SCARD("Success hcard: 0x%08x", (unsigned) hCard); sc_output_alignment(irp, 8); return rv; } static uint32 handle_EndTransaction(IRP* irp) { LONG rv; SCARDCONTEXT hCard; DWORD dwDisposition = 0; stream_seek(irp->input, 0x20); stream_read_uint32(irp->input, dwDisposition); stream_seek(irp->input, 0x0C); stream_read_uint32(irp->input, hCard); rv = SCardEndTransaction(hCard, dwDisposition); if (rv != SCARD_S_SUCCESS) DEBUG_SCARD("Failure: %s (0x%08x)", pcsc_stringify_error(rv), (unsigned) rv); else DEBUG_SCARD("Success hcard: 0x%08x", (unsigned) hCard); sc_output_alignment(irp, 8); return rv; } static uint32 handle_State(IRP* irp) { LONG rv; SCARDHANDLE hCard; DWORD state = 0, protocol = 0; DWORD readerLen; DWORD atrLen = MAX_ATR_SIZE; char * readerName; BYTE pbAtr[MAX_ATR_SIZE]; #ifdef WITH_DEBUG_SCARD int i; #endif stream_seek(irp->input, 0x24); stream_seek_uint32(irp->input); /* atrLen */ stream_seek(irp->input, 0x0c); stream_read_uint32(irp->input, hCard); stream_seek(irp->input, 0x04); #ifdef SCARD_AUTOALLOCATE readerLen = SCARD_AUTOALLOCATE; rv = SCardStatus(hCard, (LPSTR) &readerName, &readerLen, &state, &protocol, pbAtr, &atrLen); #else readerLen = 256; readerName = xmalloc(readerLen); rv = SCardStatus(hCard, (LPSTR) readerName, &readerLen, &state, &protocol, pbAtr, &atrLen); #endif if (rv != SCARD_S_SUCCESS) { DEBUG_SCARD("Failure: %s (0x%08x)", pcsc_stringify_error(rv), (unsigned) rv); return sc_output_return(irp, rv); } DEBUG_SCARD("Success (hcard: 0x%08x len: %d state: 0x%08x, proto: 0x%08x)", (unsigned) hCard, (int) atrLen, (unsigned) state, (unsigned) protocol); #ifdef WITH_DEBUG_SCARD printf(" ATR: "); for (i = 0; i < atrLen; i++) printf("%02x%c", pbAtr[i], (i == atrLen - 1) ? ' ' : ':'); printf("\n"); #endif state = sc_map_state(state); stream_write_uint32(irp->output, state); stream_write_uint32(irp->output, protocol); stream_write_uint32(irp->output, atrLen); stream_write_uint32(irp->output, 0x00000001); stream_write_uint32(irp->output, atrLen); stream_write(irp->output, pbAtr, atrLen); sc_output_repos(irp, atrLen); sc_output_alignment(irp, 8); #ifdef SCARD_AUTOALLOCATE xfree(readerName); #else xfree(readerName); #endif return rv; } static DWORD handle_Status(IRP *irp, boolean wide) { LONG rv; SCARDHANDLE hCard; DWORD state, protocol; DWORD readerLen = 0; DWORD atrLen = 0; char * readerName; BYTE pbAtr[MAX_ATR_SIZE]; uint32 dataLength; int pos, poslen1, poslen2; #ifdef WITH_DEBUG_SCARD int i; #endif stream_seek(irp->input, 0x24); stream_read_uint32(irp->input, readerLen); stream_read_uint32(irp->input, atrLen); stream_seek(irp->input, 0x0c); stream_read_uint32(irp->input, hCard); stream_seek(irp->input, 0x4); atrLen = MAX_ATR_SIZE; #ifdef SCARD_AUTOALLOCATE readerLen = SCARD_AUTOALLOCATE; rv = SCardStatus(hCard, (LPSTR) &readerName, &readerLen, &state, &protocol, pbAtr, &atrLen); #else readerLen = 256; readerName = xmalloc(readerLen); rv = SCardStatus(hCard, (LPSTR) readerName, &readerLen, &state, &protocol, pbAtr, &atrLen); #endif if (rv != SCARD_S_SUCCESS) { DEBUG_SCARD("Failure: %s (0x%08x)", pcsc_stringify_error(rv), (unsigned) rv); return sc_output_return(irp, rv); } DEBUG_SCARD("Success (state: 0x%08x, proto: 0x%08x)", (unsigned) state, (unsigned) protocol); DEBUG_SCARD(" Reader: \"%s\"", readerName ? readerName : "NULL"); #ifdef WITH_DEBUG_SCARD printf(" ATR: "); for (i = 0; i < atrLen; i++) printf("%02x%c", pbAtr[i], (i == atrLen - 1) ? ' ' : ':'); printf("\n"); #endif state = sc_map_state(state); poslen1 = stream_get_pos(irp->output); stream_write_uint32(irp->output, readerLen); stream_write_uint32(irp->output, 0x00020000); stream_write_uint32(irp->output, state); stream_write_uint32(irp->output, protocol); stream_write(irp->output, pbAtr, atrLen); if (atrLen < 32) stream_write_zero(irp->output, 32 - atrLen); stream_write_uint32(irp->output, atrLen); poslen2 = stream_get_pos(irp->output); stream_write_uint32(irp->output, readerLen); dataLength = sc_output_string(irp, readerName, wide); dataLength += sc_output_string(irp, "\0", wide); sc_output_repos(irp, dataLength); pos = stream_get_pos(irp->output); stream_set_pos(irp->output, poslen1); stream_write_uint32(irp->output,dataLength); stream_set_pos(irp->output, poslen2); stream_write_uint32(irp->output,dataLength); stream_set_pos(irp->output, pos); sc_output_alignment(irp, 8); #ifdef SCARD_AUTOALLOCATE /* SCardFreeMemory(NULL, readerName); */ free(readerName); #else xfree(readerName); #endif return rv; } static uint32 handle_Transmit(IRP* irp) { LONG rv; SCARDCONTEXT hCard; uint32 map[7], linkedLen; SCARD_IO_REQUEST pioSendPci, pioRecvPci, *pPioRecvPci; DWORD cbSendLength = 0, cbRecvLength = 0; BYTE *sendBuf = NULL, *recvBuf = NULL; stream_seek(irp->input, 0x14); stream_read_uint32(irp->input, map[0]); stream_seek(irp->input, 0x4); stream_read_uint32(irp->input, map[1]); stream_read_uint32(irp->input, pioSendPci.dwProtocol); stream_read_uint32(irp->input, pioSendPci.cbPciLength); stream_read_uint32(irp->input, map[2]); stream_read_uint32(irp->input, cbSendLength); stream_read_uint32(irp->input, map[3]); stream_read_uint32(irp->input, map[4]); stream_read_uint32(irp->input, map[5]); stream_read_uint32(irp->input, cbRecvLength); if (map[0] & SCARD_INPUT_LINKED) sc_input_skip_linked(irp); stream_seek(irp->input, 4); stream_read_uint32(irp->input, hCard); if (map[2] & SCARD_INPUT_LINKED) { /* sendPci */ stream_read_uint32(irp->input, linkedLen); stream_read_uint32(irp->input, pioSendPci.dwProtocol); stream_seek(irp->input, linkedLen - 4); sc_input_repos(irp, linkedLen); } pioSendPci.cbPciLength = sizeof(SCARD_IO_REQUEST); if (map[3] & SCARD_INPUT_LINKED) { /* send buffer */ stream_read_uint32(irp->input, linkedLen); sendBuf = xmalloc(linkedLen); stream_read(irp->input, sendBuf, linkedLen); sc_input_repos(irp, linkedLen); } if (cbRecvLength) recvBuf = xmalloc(cbRecvLength); if (map[4] & SCARD_INPUT_LINKED) { /* recvPci */ stream_read_uint32(irp->input, linkedLen); stream_read_uint32(irp->input, pioRecvPci.dwProtocol); stream_seek(irp->input, linkedLen - 4); sc_input_repos(irp, linkedLen); stream_read_uint32(irp->input, map[6]); if (map[6] & SCARD_INPUT_LINKED) { /* not sure what this is */ stream_read_uint32(irp->input, linkedLen); stream_seek(irp->input, linkedLen); sc_input_repos(irp, linkedLen); } pioRecvPci.cbPciLength = sizeof(SCARD_IO_REQUEST); pPioRecvPci = &pioRecvPci; } else { pPioRecvPci = NULL; } pPioRecvPci = NULL; DEBUG_SCARD("SCardTransmit(hcard: 0x%08lx, send: %d bytes, recv: %d bytes)", (long unsigned) hCard, (int) cbSendLength, (int) cbRecvLength); rv = SCardTransmit(hCard, &pioSendPci, sendBuf, cbSendLength, pPioRecvPci, recvBuf, &cbRecvLength); if (rv != SCARD_S_SUCCESS) { DEBUG_SCARD("Failure: %s (0x%08x)", pcsc_stringify_error(rv), (unsigned) rv); } else { DEBUG_SCARD("Success (%d bytes)", (int) cbRecvLength); stream_write_uint32(irp->output, 0); /* pioRecvPci 0x00; */ sc_output_buffer_start(irp, cbRecvLength); /* start of recvBuf output */ sc_output_buffer(irp, (char *) recvBuf, cbRecvLength); } sc_output_alignment(irp, 8); xfree(sendBuf); xfree(recvBuf); return rv; } static uint32 handle_Control(IRP* irp) { LONG rv; SCARDCONTEXT hContext; SCARDHANDLE hCard; uint32 map[3]; uint32 controlCode; uint32 controlFunction; BYTE *recvBuffer = NULL, *sendBuffer = NULL; uint32 recvLength; DWORD nBytesReturned; DWORD outBufferSize; stream_seek(irp->input, 0x14); stream_read_uint32(irp->input, map[0]); stream_seek(irp->input, 0x4); stream_read_uint32(irp->input, map[1]); stream_read_uint32(irp->input, controlCode); stream_read_uint32(irp->input, recvLength); stream_read_uint32(irp->input, map[2]); stream_seek(irp->input, 0x4); stream_read_uint32(irp->input, outBufferSize); stream_seek(irp->input, 0x4); stream_read_uint32(irp->input, hContext); stream_seek(irp->input, 0x4); stream_read_uint32(irp->input, hCard); /* Translate Windows SCARD_CTL_CODE's to corresponding local code */ if (WIN_CTL_DEVICE_TYPE(controlCode) == WIN_FILE_DEVICE_SMARTCARD) { controlFunction = WIN_CTL_FUNCTION(controlCode); controlCode = SCARD_CTL_CODE(controlFunction); } DEBUG_SCARD("controlCode: 0x%08x", (unsigned) controlCode); if (map[2] & SCARD_INPUT_LINKED) { /* read real input size */ stream_read_uint32(irp->input, recvLength); recvBuffer = xmalloc(recvLength); if (!recvBuffer) return sc_output_return(irp, SCARD_E_NO_MEMORY); stream_read(irp->input, recvBuffer, recvLength); } nBytesReturned = outBufferSize; sendBuffer = xmalloc(outBufferSize); if (!sendBuffer) return sc_output_return(irp, SCARD_E_NO_MEMORY); rv = SCardControl(hCard, (DWORD) controlCode, recvBuffer, (DWORD) recvLength, sendBuffer, (DWORD) outBufferSize, &nBytesReturned); if (rv != SCARD_S_SUCCESS) DEBUG_SCARD("Failure: %s (0x%08x)", pcsc_stringify_error(rv), (unsigned) rv); else DEBUG_SCARD("Success (out: %u bytes)", (unsigned) nBytesReturned); stream_write_uint32(irp->output, (uint32) nBytesReturned); stream_write_uint32(irp->output, 0x00000004); stream_write_uint32(irp->output, nBytesReturned); if (nBytesReturned > 0) { stream_write(irp->output, sendBuffer, nBytesReturned); sc_output_repos(irp, nBytesReturned); } sc_output_alignment(irp, 8); xfree(recvBuffer); xfree(sendBuffer); return rv; } static uint32 handle_GetAttrib(IRP* irp) { LONG rv; SCARDHANDLE hCard; DWORD dwAttrId = 0, dwAttrLen = 0; DWORD attrLen = 0; uint8* pbAttr = NULL; stream_seek(irp->input, 0x20); stream_read_uint32(irp->input, dwAttrId); stream_seek(irp->input, 0x4); stream_read_uint32(irp->input, dwAttrLen); stream_seek(irp->input, 0xC); stream_read_uint32(irp->input, hCard); DEBUG_SCARD("hcard: 0x%08x, attrib: 0x%08x (%d bytes)\n", (unsigned) hCard, (unsigned) dwAttrId, (int) dwAttrLen); #ifdef SCARD_AUTOALLOCATE if(dwAttrLen == 0) { attrLen = 0; } else { attrLen = SCARD_AUTOALLOCATE; } #endif rv = SCardGetAttrib(hCard, dwAttrId, attrLen == 0 ? NULL : (uint8*) &pbAttr, &attrLen); if( rv != SCARD_S_SUCCESS ) { #ifdef SCARD_AUTOALLOCATE if(dwAttrLen == 0) { attrLen = 0; } else { attrLen = SCARD_AUTOALLOCATE; } #endif } if(dwAttrId == SCARD_ATTR_DEVICE_FRIENDLY_NAME_A && rv == SCARD_E_UNSUPPORTED_FEATURE) { rv = SCardGetAttrib(hCard, SCARD_ATTR_DEVICE_FRIENDLY_NAME_W, attrLen == 0 ? NULL : (uint8*) &pbAttr, &attrLen); if( rv != SCARD_S_SUCCESS ) { #ifdef SCARD_AUTOALLOCATE if(dwAttrLen == 0) { attrLen = 0; } else { attrLen = SCARD_AUTOALLOCATE; } #endif } } if(dwAttrId == SCARD_ATTR_DEVICE_FRIENDLY_NAME_W && rv == SCARD_E_UNSUPPORTED_FEATURE) { rv = SCardGetAttrib(hCard, SCARD_ATTR_DEVICE_FRIENDLY_NAME_A, attrLen == 0 ? NULL : (uint8*) &pbAttr, &attrLen); if( rv != SCARD_S_SUCCESS ) { #ifdef SCARD_AUTOALLOCATE if(dwAttrLen == 0) { attrLen = 0; } else { attrLen = SCARD_AUTOALLOCATE; } #endif } } if(attrLen > dwAttrLen && pbAttr != NULL) { rv = SCARD_E_INSUFFICIENT_BUFFER; } dwAttrLen = attrLen; if (rv != SCARD_S_SUCCESS) { DEBUG_SCARD("Failure: %s (0x%08x)", pcsc_stringify_error(rv), (unsigned int) rv); free(pbAttr); return sc_output_return(irp, rv); } else { DEBUG_SCARD("Success (%d bytes)", (int) dwAttrLen); stream_write_uint32(irp->output, dwAttrLen); stream_write_uint32(irp->output, 0x00000200); stream_write_uint32(irp->output, dwAttrLen); if (!pbAttr) { stream_write_zero(irp->output, dwAttrLen); } else { stream_write(irp->output, pbAttr, dwAttrLen); } sc_output_repos(irp, dwAttrLen); /* align to multiple of 4 */ stream_write_uint32(irp->output, 0); } sc_output_alignment(irp, 8); xfree(pbAttr); return rv; } static uint32 handle_AccessStartedEvent(IRP* irp) { stream_write_zero(irp->output, 8); return SCARD_S_SUCCESS; } void scard_error(SCARD_DEVICE* scard, IRP* irp, uint32 ntstatus) { /* [MS-RDPESC] 3.1.4.4 */ printf("scard processing error %x\n", ntstatus); stream_set_pos(irp->output, 0); /* CHECKME */ irp->IoStatus = ntstatus; irp->Complete(irp); } /* http://msdn.microsoft.com/en-gb/library/ms938473.aspx */ typedef struct _SERVER_SCARD_ATRMASK { uint32 cbAtr; uint8 rgbAtr[36]; uint8 rgbMask[36]; } SERVER_SCARD_ATRMASK; static uint32 handle_LocateCardsByATR(IRP* irp, boolean wide) { LONG rv; int i, j, k; SCARDCONTEXT hContext; uint32 atrMaskCount = 0; uint32 readerCount = 0; SCARD_READERSTATE* cur = NULL; SCARD_READERSTATE* rsCur = NULL; SCARD_READERSTATE* readerStates = NULL; SERVER_SCARD_ATRMASK* curAtr = NULL; SERVER_SCARD_ATRMASK* pAtrMasks = NULL; stream_seek(irp->input, 0x2C); stream_read_uint32(irp->input, hContext); stream_read_uint32(irp->input, atrMaskCount); pAtrMasks = xmalloc(atrMaskCount * sizeof(SERVER_SCARD_ATRMASK)); if (!pAtrMasks) return sc_output_return(irp, SCARD_E_NO_MEMORY); for (i = 0; i < atrMaskCount; i++) { stream_read_uint32(irp->input, pAtrMasks[i].cbAtr); stream_read(irp->input, pAtrMasks[i].rgbAtr, 36); stream_read(irp->input, pAtrMasks[i].rgbMask, 36); } stream_read_uint32(irp->input, readerCount); readerStates = xzalloc(readerCount * sizeof(SCARD_READERSTATE)); if (!readerStates) return sc_output_return(irp, SCARD_E_NO_MEMORY); for (i = 0; i < readerCount; i++) { cur = &readerStates[i]; stream_seek(irp->input, 4); /* * TODO: on-wire is little endian; need to either * convert to host endian or fix the headers to * request the order we want */ stream_read_uint32(irp->input, cur->dwCurrentState); stream_read_uint32(irp->input, cur->dwEventState); stream_read_uint32(irp->input, cur->cbAtr); stream_read(irp->input, cur->rgbAtr, 32); stream_seek(irp->input, 4); /* reset high bytes? */ cur->dwCurrentState &= 0x0000FFFF; cur->dwEventState &= 0x0000FFFF; cur->dwEventState = 0; } for (i = 0; i < readerCount; i++) { cur = &readerStates[i]; uint32 dataLength; stream_seek(irp->input, 8); stream_read_uint32(irp->input, dataLength); sc_input_repos(irp, sc_input_string(irp, (char **) &cur->szReader, dataLength, wide)); DEBUG_SCARD(" \"%s\"", cur->szReader ? cur->szReader : "NULL"); DEBUG_SCARD(" user: 0x%08x, state: 0x%08x, event: 0x%08x", (unsigned) cur->pvUserData, (unsigned) cur->dwCurrentState, (unsigned) cur->dwEventState); if (strcmp(cur->szReader, "\\\\?PnP?\\Notification") == 0) cur->dwCurrentState |= SCARD_STATE_IGNORE; } rv = SCardGetStatusChange(hContext, 0x00000001, readerStates, readerCount); if (rv != SCARD_S_SUCCESS) { DEBUG_SCARD("Failure: %s (0x%08x)", pcsc_stringify_error(rv), (unsigned) rv); return sc_output_return(irp, rv); } DEBUG_SCARD("Success"); for (i = 0, curAtr = pAtrMasks; i < atrMaskCount; i++, curAtr++) { for (j = 0, rsCur = readerStates; j < readerCount; j++, rsCur++) { boolean equal = 1; for (k = 0; k < cur->cbAtr; k++) { if ((curAtr->rgbAtr[k] & curAtr->rgbMask[k]) != (rsCur->rgbAtr[k] & curAtr->rgbMask[k])) { equal = 0; break; } } if (equal) { rsCur->dwEventState |= 0x00000040; /* SCARD_STATE_ATRMATCH 0x00000040 */ } } } stream_write_uint32(irp->output, readerCount); stream_write_uint32(irp->output, 0x00084dd8); stream_write_uint32(irp->output, readerCount); for (i = 0, rsCur = readerStates; i < readerCount; i++, rsCur++) { stream_write_uint32(irp->output, cur->dwCurrentState); stream_write_uint32(irp->output, cur->dwEventState); stream_write_uint32(irp->output, cur->cbAtr); stream_write(irp->output, cur->rgbAtr, 32); stream_write_zero(irp->output, 4); xfree((void*) cur->szReader); } sc_output_alignment(irp, 8); free(readerStates); return rv; } boolean scard_async_op(IRP* irp) { uint32 ioctl_code; /* peek ahead */ stream_seek(irp->input, 8); stream_read_uint32(irp->input, ioctl_code); stream_rewind(irp->input, 12); switch (ioctl_code) { /* non-blocking events */ case SCARD_IOCTL_ACCESS_STARTED_EVENT: case SCARD_IOCTL_ESTABLISH_CONTEXT: case SCARD_IOCTL_RELEASE_CONTEXT: case SCARD_IOCTL_IS_VALID_CONTEXT: return false; break; /* async events */ case SCARD_IOCTL_GET_STATUS_CHANGE: case SCARD_IOCTL_GET_STATUS_CHANGE + 4: case SCARD_IOCTL_TRANSMIT: case SCARD_IOCTL_STATUS: case SCARD_IOCTL_STATUS + 4: return true; break; default: break; } /* default to async */ return true; } void scard_device_control(SCARD_DEVICE* scard, IRP* irp) { uint32 output_len, input_len, ioctl_code; uint32 stream_len, result; uint32 pos, pad_len; uint32 irp_len; uint32 irp_result_pos, output_len_pos, result_pos; stream_read_uint32(irp->input, output_len); stream_read_uint32(irp->input, input_len); stream_read_uint32(irp->input, ioctl_code); stream_seek(irp->input, 20); /* padding */ // stream_seek(irp->input, 4); /* TODO: parse len, le, v1 */ // stream_seek(irp->input, 4); /* 0xcccccccc */ // stream_seek(irp->input, 4); /* rpce len */ /* [MS-RDPESC] 3.2.5.1 Sending Outgoing Messages */ stream_extend(irp->output, 2048); irp_result_pos = stream_get_pos(irp->output); stream_write_uint32(irp->output, 0x00081001); /* len 8, LE, v1 */ /* [MS-RPCE] 2.2.6.1 */ stream_write_uint32(irp->output, 0x00081001); /* len 8, LE, v1 */ stream_write_uint32(irp->output, 0xcccccccc); /* filler */ output_len_pos = stream_get_pos(irp->output); stream_seek(irp->output, 4); /* size */ stream_write_uint32(irp->output, 0x0); /* filler */ result_pos = stream_get_pos(irp->output); stream_seek(irp->output, 4); /* result */ /* body */ switch (ioctl_code) { case SCARD_IOCTL_ESTABLISH_CONTEXT: result = handle_EstablishContext(irp); break; case SCARD_IOCTL_IS_VALID_CONTEXT: result = handle_IsValidContext(irp); break; case SCARD_IOCTL_RELEASE_CONTEXT: result = handle_ReleaseContext(irp); break; case SCARD_IOCTL_LIST_READERS: result = handle_ListReaders(irp, 0); break; case SCARD_IOCTL_LIST_READERS + 4: result = handle_ListReaders(irp, 1); break; case SCARD_IOCTL_LIST_READER_GROUPS: case SCARD_IOCTL_LIST_READER_GROUPS + 4: /* typically not used unless list_readers fail */ result = SCARD_F_INTERNAL_ERROR; break; case SCARD_IOCTL_GET_STATUS_CHANGE: result = handle_GetStatusChange(irp, 0); break; case SCARD_IOCTL_GET_STATUS_CHANGE + 4: result = handle_GetStatusChange(irp, 1); break; case SCARD_IOCTL_CANCEL: result = handle_Cancel(irp); break; case SCARD_IOCTL_CONNECT: result = handle_Connect(irp, 0); break; case SCARD_IOCTL_CONNECT + 4: result = handle_Connect(irp, 1); break; case SCARD_IOCTL_RECONNECT: result = handle_Reconnect(irp); break; case SCARD_IOCTL_DISCONNECT: result = handle_Disconnect(irp); break; case SCARD_IOCTL_BEGIN_TRANSACTION: result = handle_BeginTransaction(irp); break; case SCARD_IOCTL_END_TRANSACTION: result = handle_EndTransaction(irp); break; case SCARD_IOCTL_STATE: result = handle_State(irp); break; case SCARD_IOCTL_STATUS: result = handle_Status(irp, 0); break; case SCARD_IOCTL_STATUS + 4: result = handle_Status(irp, 1); break; case SCARD_IOCTL_TRANSMIT: result = handle_Transmit(irp); break; case SCARD_IOCTL_CONTROL: result = handle_Control(irp); break; case SCARD_IOCTL_GETATTRIB: result = handle_GetAttrib(irp); break; case SCARD_IOCTL_ACCESS_STARTED_EVENT: result = handle_AccessStartedEvent(irp); break; case SCARD_IOCTL_LOCATE_CARDS_BY_ATR: result = handle_LocateCardsByATR(irp, 0); break; case SCARD_IOCTL_LOCATE_CARDS_BY_ATR + 4: result = handle_LocateCardsByATR(irp, 1); break; default: result = 0xc0000001; printf("scard unknown ioctl 0x%x\n", ioctl_code); break; } /* look for NTSTATUS errors */ if ((result & 0xc0000000) == 0xc0000000) return scard_error(scard, irp, result); /* per Ludovic Rousseau, map different usage of this particular * error code between pcsc-lite & windows */ if (result == 0x8010001F) result = 0x80100022; /* handle response packet */ pos = stream_get_pos(irp->output); stream_len = pos - irp_result_pos - 4; stream_set_pos(irp->output, output_len_pos); stream_write_uint32(irp->output, stream_len - 24); stream_set_pos(irp->output, result_pos); stream_write_uint32(irp->output, result); stream_set_pos(irp->output, pos); /* pad stream to 16 byte align */ pad_len = stream_len % 16; stream_write_zero(irp->output, pad_len); pos = stream_get_pos(irp->output); irp_len = stream_len + pad_len; stream_set_pos(irp->output, irp_result_pos); stream_write_uint32(irp->output, irp_len); stream_set_pos(irp->output, pos); #ifdef WITH_DEBUG_SCARD freerdp_hexdump(stream_get_data(irp->output), stream_get_length(irp->output)); #endif irp->IoStatus = 0; irp->Complete(irp); } FreeRDP-1.0.2/channels/rdpsnd/000077500000000000000000000000001207112532300160225ustar00rootroot00000000000000FreeRDP-1.0.2/channels/rdpsnd/CMakeLists.txt000066400000000000000000000021541207112532300205640ustar00rootroot00000000000000# FreeRDP: A Remote Desktop Protocol Client # FreeRDP cmake build script # # Copyright 2011 O.S. Systems Software Ltda. # Copyright 2011 Otavio Salvador # Copyright 2011 Marc-Andre Moreau # # 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(RDPSND_SRCS rdpsnd_main.c rdpsnd_main.h ) add_library(rdpsnd ${RDPSND_SRCS}) set_target_properties(rdpsnd PROPERTIES PREFIX "") target_link_libraries(rdpsnd freerdp-utils) install(TARGETS rdpsnd DESTINATION ${FREERDP_PLUGIN_PATH}) if(WITH_ALSA) add_subdirectory(alsa) endif() if(WITH_PULSEAUDIO) add_subdirectory(pulse) endif() FreeRDP-1.0.2/channels/rdpsnd/alsa/000077500000000000000000000000001207112532300167425ustar00rootroot00000000000000FreeRDP-1.0.2/channels/rdpsnd/alsa/CMakeLists.txt000066400000000000000000000022151207112532300215020ustar00rootroot00000000000000# FreeRDP: A Remote Desktop Protocol Client # FreeRDP cmake build script # # Copyright 2011 O.S. Systems Software Ltda. # Copyright 2011 Otavio Salvador # Copyright 2011 Marc-Andre Moreau # # 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(RDPSND_ALSA_SRCS rdpsnd_alsa.c ) include_directories(..) include_directories(${ALSA_INCLUDE_DIRS}) add_library(rdpsnd_alsa ${RDPSND_ALSA_SRCS}) set_target_properties(rdpsnd_alsa PROPERTIES PREFIX "") target_link_libraries(rdpsnd_alsa freerdp-utils) target_link_libraries(rdpsnd_alsa ${ALSA_LIBRARIES}) install(TARGETS rdpsnd_alsa DESTINATION ${FREERDP_PLUGIN_PATH}) FreeRDP-1.0.2/channels/rdpsnd/alsa/rdpsnd_alsa.c000066400000000000000000000220201207112532300213740ustar00rootroot00000000000000/** * FreeRDP: A Remote Desktop Protocol client. * Audio Output Virtual Channel * * Copyright 2009-2011 Jay Sorg * Copyright 2010-2011 Vic Lee * * 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. */ #include #include #include #include #include #include #include #include #include "rdpsnd_main.h" typedef struct rdpsnd_alsa_plugin rdpsndAlsaPlugin; struct rdpsnd_alsa_plugin { rdpsndDevicePlugin device; char* device_name; snd_pcm_t* out_handle; uint32 source_rate; uint32 actual_rate; snd_pcm_format_t format; uint32 source_channels; uint32 actual_channels; int bytes_per_channel; int wformat; int block_size; int latency; ADPCM adpcm; }; static void rdpsnd_alsa_set_params(rdpsndAlsaPlugin* alsa) { snd_pcm_hw_params_t* hw_params; snd_pcm_sw_params_t* sw_params; int error; snd_pcm_uframes_t frames; snd_pcm_uframes_t start_threshold; snd_pcm_drop(alsa->out_handle); error = snd_pcm_hw_params_malloc(&hw_params); if (error < 0) { DEBUG_WARN("snd_pcm_hw_params_malloc failed"); return; } snd_pcm_hw_params_any(alsa->out_handle, hw_params); snd_pcm_hw_params_set_access(alsa->out_handle, hw_params, SND_PCM_ACCESS_RW_INTERLEAVED); snd_pcm_hw_params_set_format(alsa->out_handle, hw_params, alsa->format); snd_pcm_hw_params_set_rate_near(alsa->out_handle, hw_params, &alsa->actual_rate, NULL); snd_pcm_hw_params_set_channels_near(alsa->out_handle, hw_params, &alsa->actual_channels); if (alsa->latency < 0) frames = alsa->actual_rate * 4; /* Default to 4-second buffer */ else frames = alsa->latency * alsa->actual_rate * 2 / 1000; /* Double of the latency */ if (frames < alsa->actual_rate / 2) frames = alsa->actual_rate / 2; /* Minimum 0.5-second buffer */ snd_pcm_hw_params_set_buffer_size_near(alsa->out_handle, hw_params, &frames); snd_pcm_hw_params(alsa->out_handle, hw_params); snd_pcm_hw_params_free(hw_params); error = snd_pcm_sw_params_malloc(&sw_params); if (error < 0) { DEBUG_WARN("snd_pcm_sw_params_malloc failed"); return; } snd_pcm_sw_params_current(alsa->out_handle, sw_params); if (alsa->latency == 0) start_threshold = 0; else start_threshold = frames / 2; snd_pcm_sw_params_set_start_threshold(alsa->out_handle, sw_params, start_threshold); snd_pcm_sw_params(alsa->out_handle, sw_params); snd_pcm_sw_params_free(sw_params); snd_pcm_prepare(alsa->out_handle); DEBUG_SVC("hardware buffer %d frames, playback buffer %.2g seconds", (int)frames, (double)frames / 2.0 / (double)alsa->actual_rate); if ((alsa->actual_rate != alsa->source_rate) || (alsa->actual_channels != alsa->source_channels)) { DEBUG_SVC("actual rate %d / channel %d is different from source rate %d / channel %d, resampling required.", alsa->actual_rate, alsa->actual_channels, alsa->source_rate, alsa->source_channels); } } static void rdpsnd_alsa_set_format(rdpsndDevicePlugin* device, rdpsndFormat* format, int latency) { rdpsndAlsaPlugin* alsa = (rdpsndAlsaPlugin*)device; if (format != NULL) { alsa->source_rate = format->nSamplesPerSec; alsa->actual_rate = format->nSamplesPerSec; alsa->source_channels = format->nChannels; alsa->actual_channels = format->nChannels; switch (format->wFormatTag) { case 1: /* PCM */ switch (format->wBitsPerSample) { case 8: alsa->format = SND_PCM_FORMAT_S8; alsa->bytes_per_channel = 1; break; case 16: alsa->format = SND_PCM_FORMAT_S16_LE; alsa->bytes_per_channel = 2; break; } break; case 0x11: /* IMA ADPCM */ alsa->format = SND_PCM_FORMAT_S16_LE; alsa->bytes_per_channel = 2; break; } alsa->wformat = format->wFormatTag; alsa->block_size = format->nBlockAlign; } alsa->latency = latency; rdpsnd_alsa_set_params(alsa); } static void rdpsnd_alsa_open(rdpsndDevicePlugin* device, rdpsndFormat* format, int latency) { rdpsndAlsaPlugin* alsa = (rdpsndAlsaPlugin*)device; int error; if (alsa->out_handle != 0) return; DEBUG_SVC("opening"); error = snd_pcm_open(&alsa->out_handle, alsa->device_name, SND_PCM_STREAM_PLAYBACK, 0); if (error < 0) { DEBUG_WARN("snd_pcm_open failed"); } else { memset(&alsa->adpcm, 0, sizeof(ADPCM)); rdpsnd_alsa_set_format(device, format, latency); } } static void rdpsnd_alsa_close(rdpsndDevicePlugin* device) { rdpsndAlsaPlugin* alsa = (rdpsndAlsaPlugin*)device; if (alsa->out_handle != 0) { DEBUG_SVC("close"); snd_pcm_drain(alsa->out_handle); snd_pcm_close(alsa->out_handle); alsa->out_handle = 0; } } static void rdpsnd_alsa_free(rdpsndDevicePlugin* device) { rdpsndAlsaPlugin* alsa = (rdpsndAlsaPlugin*)device; rdpsnd_alsa_close(device); xfree(alsa->device_name); xfree(alsa); } static boolean rdpsnd_alsa_format_supported(rdpsndDevicePlugin* device, rdpsndFormat* format) { switch (format->wFormatTag) { case 1: /* PCM */ if (format->cbSize == 0 && format->nSamplesPerSec <= 48000 && (format->wBitsPerSample == 8 || format->wBitsPerSample == 16) && (format->nChannels == 1 || format->nChannels == 2)) { return true; } break; case 0x11: /* IMA ADPCM */ if (format->nSamplesPerSec <= 48000 && format->wBitsPerSample == 4 && (format->nChannels == 1 || format->nChannels == 2)) { return true; } break; } return false; } static void rdpsnd_alsa_set_volume(rdpsndDevicePlugin* device, uint32 value) { } static void rdpsnd_alsa_play(rdpsndDevicePlugin* device, uint8* data, int size) { rdpsndAlsaPlugin* alsa = (rdpsndAlsaPlugin*)device; uint8* decoded_data; int decoded_size; uint8* src; uint8* resampled_data; int len; int error; int frames; int rbytes_per_frame; int sbytes_per_frame; uint8* pindex; uint8* end; if (alsa->out_handle == 0) return; if (alsa->wformat == 0x11) { decoded_data = dsp_decode_ima_adpcm(&alsa->adpcm, data, size, alsa->source_channels, alsa->block_size, &decoded_size); size = decoded_size; src = decoded_data; } else { decoded_data = NULL; src = data; } sbytes_per_frame = alsa->source_channels * alsa->bytes_per_channel; rbytes_per_frame = alsa->actual_channels * alsa->bytes_per_channel; if ((size % sbytes_per_frame) != 0) { DEBUG_WARN("error len mod"); return; } if ((alsa->source_rate == alsa->actual_rate) && (alsa->source_channels == alsa->actual_channels)) { resampled_data = NULL; } else { resampled_data = dsp_resample(src, alsa->bytes_per_channel, alsa->source_channels, alsa->source_rate, size / sbytes_per_frame, alsa->actual_channels, alsa->actual_rate, &frames); DEBUG_SVC("resampled %d frames at %d to %d frames at %d", size / sbytes_per_frame, alsa->source_rate, frames, alsa->actual_rate); size = frames * rbytes_per_frame; src = resampled_data; } pindex = src; end = pindex + size; while (pindex < end) { len = end - pindex; frames = len / rbytes_per_frame; error = snd_pcm_writei(alsa->out_handle, pindex, frames); if (error == -EPIPE) { snd_pcm_recover(alsa->out_handle, error, 0); error = 0; } else if (error < 0) { DEBUG_WARN("error %d", error); snd_pcm_close(alsa->out_handle); alsa->out_handle = 0; rdpsnd_alsa_open(device, NULL, alsa->latency); break; } pindex += error * rbytes_per_frame; } if (resampled_data) xfree(resampled_data); if (decoded_data) xfree(decoded_data); } static void rdpsnd_alsa_start(rdpsndDevicePlugin* device) { rdpsndAlsaPlugin* alsa = (rdpsndAlsaPlugin*)device; if (alsa->out_handle == 0) return; snd_pcm_start(alsa->out_handle); } int FreeRDPRdpsndDeviceEntry(PFREERDP_RDPSND_DEVICE_ENTRY_POINTS pEntryPoints) { rdpsndAlsaPlugin* alsa; RDP_PLUGIN_DATA* data; alsa = xnew(rdpsndAlsaPlugin); alsa->device.Open = rdpsnd_alsa_open; alsa->device.FormatSupported = rdpsnd_alsa_format_supported; alsa->device.SetFormat = rdpsnd_alsa_set_format; alsa->device.SetVolume = rdpsnd_alsa_set_volume; alsa->device.Play = rdpsnd_alsa_play; alsa->device.Start = rdpsnd_alsa_start; alsa->device.Close = rdpsnd_alsa_close; alsa->device.Free = rdpsnd_alsa_free; data = pEntryPoints->plugin_data; if (data && strcmp((char*)data->data[0], "alsa") == 0) { alsa->device_name = xstrdup((char*)data->data[1]); } if (alsa->device_name == NULL) { alsa->device_name = xstrdup("default"); } alsa->out_handle = 0; alsa->source_rate = 22050; alsa->actual_rate = 22050; alsa->format = SND_PCM_FORMAT_S16_LE; alsa->source_channels = 2; alsa->actual_channels = 2; alsa->bytes_per_channel = 2; pEntryPoints->pRegisterRdpsndDevice(pEntryPoints->rdpsnd, (rdpsndDevicePlugin*)alsa); return 0; } FreeRDP-1.0.2/channels/rdpsnd/pulse/000077500000000000000000000000001207112532300171525ustar00rootroot00000000000000FreeRDP-1.0.2/channels/rdpsnd/pulse/CMakeLists.txt000066400000000000000000000022321207112532300217110ustar00rootroot00000000000000# FreeRDP: A Remote Desktop Protocol Client # FreeRDP cmake build script # # Copyright 2011 O.S. Systems Software Ltda. # Copyright 2011 Otavio Salvador # Copyright 2011 Marc-Andre Moreau # # 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(RDPSND_PULSE_SRCS rdpsnd_pulse.c ) include_directories(..) include_directories(${PULSE_INCLUDE_DIRS}) add_library(rdpsnd_pulse ${RDPSND_PULSE_SRCS}) set_target_properties(rdpsnd_pulse PROPERTIES PREFIX "") target_link_libraries(rdpsnd_pulse freerdp-utils) target_link_libraries(rdpsnd_pulse ${PULSEAUDIO_LIBRARY}) install(TARGETS rdpsnd_pulse DESTINATION ${FREERDP_PLUGIN_PATH}) FreeRDP-1.0.2/channels/rdpsnd/pulse/rdpsnd_pulse.c000066400000000000000000000306251207112532300220260ustar00rootroot00000000000000/** * FreeRDP: A Remote Desktop Protocol client. * Audio Output Virtual Channel * * Copyright 2011 Vic Lee * * 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. */ #include #include #include #include #include #include #include #include #include "rdpsnd_main.h" typedef struct rdpsnd_pulse_plugin rdpsndPulsePlugin; struct rdpsnd_pulse_plugin { rdpsndDevicePlugin device; char* device_name; pa_threaded_mainloop *mainloop; pa_context *context; pa_sample_spec sample_spec; pa_stream *stream; int format; int block_size; int latency; ADPCM adpcm; }; static void rdpsnd_pulse_context_state_callback(pa_context* context, void* userdata) { rdpsndPulsePlugin* pulse = (rdpsndPulsePlugin*)userdata; pa_context_state_t state; state = pa_context_get_state(context); switch (state) { case PA_CONTEXT_READY: DEBUG_SVC("PA_CONTEXT_READY"); pa_threaded_mainloop_signal(pulse->mainloop, 0); break; case PA_CONTEXT_FAILED: case PA_CONTEXT_TERMINATED: DEBUG_SVC("PA_CONTEXT_FAILED/PA_CONTEXT_TERMINATED %d", (int)state); pa_threaded_mainloop_signal(pulse->mainloop, 0); break; default: DEBUG_SVC("state %d", (int)state); break; } } static boolean rdpsnd_pulse_connect(rdpsndDevicePlugin* device) { rdpsndPulsePlugin* pulse = (rdpsndPulsePlugin*)device; pa_context_state_t state; if (!pulse->context) return false; if (pa_context_connect(pulse->context, NULL, 0, NULL)) { DEBUG_WARN("pa_context_connect failed (%d)", pa_context_errno(pulse->context)); return false; } pa_threaded_mainloop_lock(pulse->mainloop); if (pa_threaded_mainloop_start(pulse->mainloop) < 0) { pa_threaded_mainloop_unlock(pulse->mainloop); DEBUG_WARN("pa_threaded_mainloop_start failed (%d)", pa_context_errno(pulse->context)); return false; } for (;;) { state = pa_context_get_state(pulse->context); if (state == PA_CONTEXT_READY) break; if (!PA_CONTEXT_IS_GOOD(state)) { DEBUG_WARN("bad context state (%d)", pa_context_errno(pulse->context)); break; } pa_threaded_mainloop_wait(pulse->mainloop); } pa_threaded_mainloop_unlock(pulse->mainloop); if (state == PA_CONTEXT_READY) { DEBUG_SVC("connected"); return true; } else { pa_context_disconnect(pulse->context); return false; } } static void rdpsnd_pulse_stream_success_callback(pa_stream* stream, int success, void* userdata) { rdpsndPulsePlugin* pulse = (rdpsndPulsePlugin*)userdata; pa_threaded_mainloop_signal(pulse->mainloop, 0); } static void rdpsnd_pulse_wait_for_operation(rdpsndPulsePlugin* pulse, pa_operation* operation) { if (operation == NULL) return; while (pa_operation_get_state(operation) == PA_OPERATION_RUNNING) { pa_threaded_mainloop_wait(pulse->mainloop); } pa_operation_unref(operation); } static void rdpsnd_pulse_stream_state_callback(pa_stream* stream, void* userdata) { rdpsndPulsePlugin* pulse = (rdpsndPulsePlugin*)userdata; pa_stream_state_t state; state = pa_stream_get_state(stream); switch (state) { case PA_STREAM_READY: DEBUG_SVC("PA_STREAM_READY"); pa_threaded_mainloop_signal(pulse->mainloop, 0); break; case PA_STREAM_FAILED: case PA_STREAM_TERMINATED: DEBUG_SVC("state %d", (int)state); pa_threaded_mainloop_signal(pulse->mainloop, 0); break; default: DEBUG_SVC("state %d", (int)state); break; } } static void rdpsnd_pulse_stream_request_callback(pa_stream* stream, size_t length, void* userdata) { rdpsndPulsePlugin* pulse = (rdpsndPulsePlugin*)userdata; pa_threaded_mainloop_signal(pulse->mainloop, 0); } static void rdpsnd_pulse_close(rdpsndDevicePlugin* device) { rdpsndPulsePlugin* pulse = (rdpsndPulsePlugin*)device; if (!pulse->context || !pulse->stream) return; pa_threaded_mainloop_lock(pulse->mainloop); rdpsnd_pulse_wait_for_operation(pulse, pa_stream_drain(pulse->stream, rdpsnd_pulse_stream_success_callback, pulse)); pa_stream_disconnect(pulse->stream); pa_stream_unref(pulse->stream); pulse->stream = NULL; pa_threaded_mainloop_unlock(pulse->mainloop); } static void rdpsnd_pulse_set_format_spec(rdpsndPulsePlugin* pulse, rdpsndFormat* format) { pa_sample_spec sample_spec = { 0 }; if (!pulse->context) return; sample_spec.rate = format->nSamplesPerSec; sample_spec.channels = format->nChannels; switch (format->wFormatTag) { case 1: /* PCM */ switch (format->wBitsPerSample) { case 8: sample_spec.format = PA_SAMPLE_U8; break; case 16: sample_spec.format = PA_SAMPLE_S16LE; break; } break; case 6: /* A-LAW */ sample_spec.format = PA_SAMPLE_ALAW; break; case 7: /* U-LAW */ sample_spec.format = PA_SAMPLE_ULAW; break; case 0x11: /* IMA ADPCM */ sample_spec.format = PA_SAMPLE_S16LE; break; } pulse->sample_spec = sample_spec; pulse->format = format->wFormatTag; pulse->block_size = format->nBlockAlign; } static void rdpsnd_pulse_open(rdpsndDevicePlugin* device, rdpsndFormat* format, int latency) { rdpsndPulsePlugin* pulse = (rdpsndPulsePlugin*)device; pa_stream_state_t state; pa_stream_flags_t flags; pa_buffer_attr buffer_attr = { 0 }; char ss[PA_SAMPLE_SPEC_SNPRINT_MAX]; if (!pulse->context || pulse->stream) { DEBUG_WARN("pulse stream has been created."); return; } rdpsnd_pulse_set_format_spec(pulse, format); pulse->latency = latency; if (pa_sample_spec_valid(&pulse->sample_spec) == 0) { pa_sample_spec_snprint(ss, sizeof(ss), &pulse->sample_spec); DEBUG_WARN("Invalid sample spec %s", ss); return; } pa_threaded_mainloop_lock(pulse->mainloop); pulse->stream = pa_stream_new(pulse->context, "freerdp", &pulse->sample_spec, NULL); if (!pulse->stream) { pa_threaded_mainloop_unlock(pulse->mainloop); DEBUG_WARN("pa_stream_new failed (%d)", pa_context_errno(pulse->context)); return; } /* install essential callbacks */ pa_stream_set_state_callback(pulse->stream, rdpsnd_pulse_stream_state_callback, pulse); pa_stream_set_write_callback(pulse->stream, rdpsnd_pulse_stream_request_callback, pulse); flags = PA_STREAM_INTERPOLATE_TIMING | PA_STREAM_AUTO_TIMING_UPDATE; if (pulse->latency > 0) { buffer_attr.maxlength = pa_usec_to_bytes(pulse->latency * 2 * 1000, &pulse->sample_spec); buffer_attr.tlength = pa_usec_to_bytes(pulse->latency * 1000, &pulse->sample_spec); buffer_attr.prebuf = (uint32_t) -1; buffer_attr.minreq = (uint32_t) -1; buffer_attr.fragsize = (uint32_t) -1; flags |= PA_STREAM_ADJUST_LATENCY; } if (pa_stream_connect_playback(pulse->stream, pulse->device_name, pulse->latency > 0 ? &buffer_attr : NULL, flags, NULL, NULL) < 0) { pa_threaded_mainloop_unlock(pulse->mainloop); DEBUG_WARN("pa_stream_connect_playback failed (%d)", pa_context_errno(pulse->context)); return; } for (;;) { state = pa_stream_get_state(pulse->stream); if (state == PA_STREAM_READY) break; if (!PA_STREAM_IS_GOOD(state)) { DEBUG_WARN("bad stream state (%d)", pa_context_errno(pulse->context)); break; } pa_threaded_mainloop_wait(pulse->mainloop); } pa_threaded_mainloop_unlock(pulse->mainloop); if (state == PA_STREAM_READY) { memset(&pulse->adpcm, 0, sizeof(ADPCM)); DEBUG_SVC("connected"); } else { rdpsnd_pulse_close(device); } } static void rdpsnd_pulse_free(rdpsndDevicePlugin* device) { rdpsndPulsePlugin* pulse = (rdpsndPulsePlugin*)device; if (!pulse) return; rdpsnd_pulse_close(device); if (pulse->mainloop) { pa_threaded_mainloop_stop(pulse->mainloop); } if (pulse->context) { pa_context_disconnect(pulse->context); pa_context_unref(pulse->context); pulse->context = NULL; } if (pulse->mainloop) { pa_threaded_mainloop_free(pulse->mainloop); pulse->mainloop = NULL; } xfree(pulse->device_name); xfree(pulse); } static boolean rdpsnd_pulse_format_supported(rdpsndDevicePlugin* device, rdpsndFormat* format) { rdpsndPulsePlugin* pulse = (rdpsndPulsePlugin*)device; if (!pulse->context) return false; switch (format->wFormatTag) { case 1: /* PCM */ if (format->cbSize == 0 && (format->nSamplesPerSec <= PA_RATE_MAX) && (format->wBitsPerSample == 8 || format->wBitsPerSample == 16) && (format->nChannels >= 1 && format->nChannels <= PA_CHANNELS_MAX)) { return true; } break; case 6: /* A-LAW */ case 7: /* U-LAW */ if (format->cbSize == 0 && (format->nSamplesPerSec <= PA_RATE_MAX) && (format->wBitsPerSample == 8) && (format->nChannels >= 1 && format->nChannels <= PA_CHANNELS_MAX)) { return true; } break; case 0x11: /* IMA ADPCM */ if ((format->nSamplesPerSec <= PA_RATE_MAX) && (format->wBitsPerSample == 4) && (format->nChannels == 1 || format->nChannels == 2)) { return true; } break; } return false; } static void rdpsnd_pulse_set_format(rdpsndDevicePlugin* device, rdpsndFormat* format, int latency) { rdpsndPulsePlugin* pulse = (rdpsndPulsePlugin*)device; if (pulse->stream) { pa_threaded_mainloop_lock(pulse->mainloop); pa_stream_disconnect(pulse->stream); pa_stream_unref(pulse->stream); pulse->stream = NULL; pa_threaded_mainloop_unlock(pulse->mainloop); } rdpsnd_pulse_open(device, format, latency); } static void rdpsnd_pulse_set_volume(rdpsndDevicePlugin* device, uint32 value) { } static void rdpsnd_pulse_play(rdpsndDevicePlugin* device, uint8* data, int size) { rdpsndPulsePlugin* pulse = (rdpsndPulsePlugin*)device; int len; int ret; uint8* decoded_data; uint8* src; int decoded_size; if (!pulse->stream) return; if (pulse->format == 0x11) { decoded_data = dsp_decode_ima_adpcm(&pulse->adpcm, data, size, pulse->sample_spec.channels, pulse->block_size, &decoded_size); size = decoded_size; src = decoded_data; } else { decoded_data = NULL; src = data; } pa_threaded_mainloop_lock(pulse->mainloop); while (size > 0) { while ((len = pa_stream_writable_size(pulse->stream)) == 0) { pa_threaded_mainloop_wait(pulse->mainloop); } if (len < 0) break; if (len > size) len = size; ret = pa_stream_write(pulse->stream, src, len, NULL, 0LL, PA_SEEK_RELATIVE); if (ret < 0) { DEBUG_WARN("pa_stream_write failed (%d)", pa_context_errno(pulse->context)); break; } src += len; size -= len; } pa_threaded_mainloop_unlock(pulse->mainloop); if (decoded_data) xfree(decoded_data); } static void rdpsnd_pulse_start(rdpsndDevicePlugin* device) { rdpsndPulsePlugin* pulse = (rdpsndPulsePlugin*)device; if (!pulse->stream) return; pa_stream_trigger(pulse->stream, NULL, NULL); } int FreeRDPRdpsndDeviceEntry(PFREERDP_RDPSND_DEVICE_ENTRY_POINTS pEntryPoints) { rdpsndPulsePlugin* pulse; RDP_PLUGIN_DATA* data; pulse = xnew(rdpsndPulsePlugin); pulse->device.Open = rdpsnd_pulse_open; pulse->device.FormatSupported = rdpsnd_pulse_format_supported; pulse->device.SetFormat = rdpsnd_pulse_set_format; pulse->device.SetVolume = rdpsnd_pulse_set_volume; pulse->device.Play = rdpsnd_pulse_play; pulse->device.Start = rdpsnd_pulse_start; pulse->device.Close = rdpsnd_pulse_close; pulse->device.Free = rdpsnd_pulse_free; data = pEntryPoints->plugin_data; if (data && strcmp((char*)data->data[0], "pulse") == 0) { if(strlen((char*)data->data[1]) > 0) pulse->device_name = xstrdup((char*)data->data[1]); else pulse->device_name = NULL; } pulse->mainloop = pa_threaded_mainloop_new(); if (!pulse->mainloop) { DEBUG_WARN("pa_threaded_mainloop_new failed"); rdpsnd_pulse_free((rdpsndDevicePlugin*)pulse); return 1; } pulse->context = pa_context_new(pa_threaded_mainloop_get_api(pulse->mainloop), "freerdp"); if (!pulse->context) { DEBUG_WARN("pa_context_new failed"); rdpsnd_pulse_free((rdpsndDevicePlugin*)pulse); return 1; } pa_context_set_state_callback(pulse->context, rdpsnd_pulse_context_state_callback, pulse); if (!rdpsnd_pulse_connect((rdpsndDevicePlugin*)pulse)) { DEBUG_WARN("rdpsnd_pulse_connect failed"); rdpsnd_pulse_free((rdpsndDevicePlugin*)pulse); return 1; } pEntryPoints->pRegisterRdpsndDevice(pEntryPoints->rdpsnd, (rdpsndDevicePlugin*)pulse); return 0; } FreeRDP-1.0.2/channels/rdpsnd/rdpsnd_main.c000066400000000000000000000356511207112532300204760ustar00rootroot00000000000000/** * FreeRDP: A Remote Desktop Protocol client. * Audio Output Virtual Channel * * Copyright 2009-2011 Jay Sorg * Copyright 2010-2011 Vic Lee * * 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. */ #ifndef _WIN32 #include #endif #include #include #include #include #include #include #include #include #include #include #include "rdpsnd_main.h" #define SNDC_CLOSE 1 #define SNDC_WAVE 2 #define SNDC_SETVOLUME 3 #define SNDC_SETPITCH 4 #define SNDC_WAVECONFIRM 5 #define SNDC_TRAINING 6 #define SNDC_FORMATS 7 #define SNDC_CRYPTKEY 8 #define SNDC_WAVEENCRYPT 9 #define SNDC_UDPWAVE 10 #define SNDC_UDPWAVELAST 11 #define SNDC_QUALITYMODE 12 #define TSSNDCAPS_ALIVE 1 #define TSSNDCAPS_VOLUME 2 #define TSSNDCAPS_PITCH 4 #define DYNAMIC_QUALITY 0x0000 #define MEDIUM_QUALITY 0x0001 #define HIGH_QUALITY 0x0002 struct rdpsnd_plugin { rdpSvcPlugin plugin; LIST* data_out_list; uint8 cBlockNo; rdpsndFormat* supported_formats; int n_supported_formats; int current_format; boolean expectingWave; uint8 waveData[4]; uint16 waveDataSize; uint32 wTimeStamp; /* server timestamp */ uint32 wave_timestamp; /* client timestamp */ boolean is_open; uint32 close_timestamp; uint16 fixed_format; uint16 fixed_channel; uint32 fixed_rate; int latency; /* Device plugin */ rdpsndDevicePlugin* device; }; struct data_out_item { STREAM* data_out; uint32 out_timestamp; }; /* get time in milliseconds */ static uint32 get_mstime(void) { struct timeval tp; gettimeofday(&tp, 0); return (tp.tv_sec * 1000) + (tp.tv_usec / 1000); } /* process the linked list of data that has queued to be sent */ static void rdpsnd_process_interval(rdpSvcPlugin* plugin) { rdpsndPlugin* rdpsnd = (rdpsndPlugin*)plugin; struct data_out_item* item; uint32 cur_time; while (rdpsnd->data_out_list->head) { item = (struct data_out_item*)rdpsnd->data_out_list->head->data; cur_time = get_mstime(); if (cur_time <= item->out_timestamp) break; item = (struct data_out_item*)list_dequeue(rdpsnd->data_out_list); svc_plugin_send(plugin, item->data_out); xfree(item); DEBUG_SVC("processed data_out"); } if (rdpsnd->is_open && rdpsnd->close_timestamp > 0) { cur_time = get_mstime(); if (cur_time > rdpsnd->close_timestamp) { if (rdpsnd->device) IFCALL(rdpsnd->device->Close, rdpsnd->device); rdpsnd->is_open = false; rdpsnd->close_timestamp = 0; DEBUG_SVC("processed close"); } } if (rdpsnd->data_out_list->head == NULL && !rdpsnd->is_open) { rdpsnd->plugin.interval_ms = 0; } } static void rdpsnd_free_supported_formats(rdpsndPlugin* rdpsnd) { uint16 i; for (i = 0; i < rdpsnd->n_supported_formats; i++) xfree(rdpsnd->supported_formats[i].data); xfree(rdpsnd->supported_formats); rdpsnd->supported_formats = NULL; rdpsnd->n_supported_formats = 0; } /* receives a list of server supported formats and returns a list of client supported formats */ static void rdpsnd_process_message_formats(rdpsndPlugin* rdpsnd, STREAM* data_in) { uint16 wNumberOfFormats; uint16 nFormat; uint16 wVersion; STREAM* data_out; rdpsndFormat* out_formats; uint16 n_out_formats; rdpsndFormat* format; uint8* format_mark; uint8* data_mark; int pos; rdpsnd_free_supported_formats(rdpsnd); stream_seek_uint32(data_in); /* dwFlags */ stream_seek_uint32(data_in); /* dwVolume */ stream_seek_uint32(data_in); /* dwPitch */ stream_seek_uint16(data_in); /* wDGramPort */ stream_read_uint16(data_in, wNumberOfFormats); stream_read_uint8(data_in, rdpsnd->cBlockNo); /* cLastBlockConfirmed */ stream_read_uint16(data_in, wVersion); stream_seek_uint8(data_in); /* bPad */ DEBUG_SVC("wNumberOfFormats %d wVersion %d", wNumberOfFormats, wVersion); if (wNumberOfFormats < 1) { DEBUG_WARN("wNumberOfFormats is 0"); return; } out_formats = (rdpsndFormat*)xzalloc(wNumberOfFormats * sizeof(rdpsndFormat)); n_out_formats = 0; data_out = stream_new(24); stream_write_uint8(data_out, SNDC_FORMATS); /* msgType */ stream_write_uint8(data_out, 0); /* bPad */ stream_seek_uint16(data_out); /* BodySize */ stream_write_uint32(data_out, TSSNDCAPS_ALIVE); /* dwFlags */ stream_write_uint32(data_out, 0); /* dwVolume */ stream_write_uint32(data_out, 0); /* dwPitch */ stream_write_uint16_be(data_out, 0); /* wDGramPort */ stream_seek_uint16(data_out); /* wNumberOfFormats */ stream_write_uint8(data_out, 0); /* cLastBlockConfirmed */ stream_write_uint16(data_out, 6); /* wVersion */ stream_write_uint8(data_out, 0); /* bPad */ for (nFormat = 0; nFormat < wNumberOfFormats; nFormat++) { stream_get_mark(data_in, format_mark); format = &out_formats[n_out_formats]; stream_read_uint16(data_in, format->wFormatTag); stream_read_uint16(data_in, format->nChannels); stream_read_uint32(data_in, format->nSamplesPerSec); stream_seek_uint32(data_in); /* nAvgBytesPerSec */ stream_read_uint16(data_in, format->nBlockAlign); stream_read_uint16(data_in, format->wBitsPerSample); stream_read_uint16(data_in, format->cbSize); stream_get_mark(data_in, data_mark); stream_seek(data_in, format->cbSize); format->data = NULL; DEBUG_SVC("wFormatTag=%d nChannels=%d nSamplesPerSec=%d nBlockAlign=%d wBitsPerSample=%d", format->wFormatTag, format->nChannels, format->nSamplesPerSec, format->nBlockAlign, format->wBitsPerSample); if (rdpsnd->fixed_format > 0 && rdpsnd->fixed_format != format->wFormatTag) continue; if (rdpsnd->fixed_channel > 0 && rdpsnd->fixed_channel != format->nChannels) continue; if (rdpsnd->fixed_rate > 0 && rdpsnd->fixed_rate != format->nSamplesPerSec) continue; if (rdpsnd->device && rdpsnd->device->FormatSupported(rdpsnd->device, format)) { DEBUG_SVC("format supported."); stream_check_size(data_out, 18 + format->cbSize); stream_write(data_out, format_mark, 18 + format->cbSize); if (format->cbSize > 0) { format->data = xmalloc(format->cbSize); memcpy(format->data, data_mark, format->cbSize); } n_out_formats++; } } rdpsnd->n_supported_formats = n_out_formats; if (n_out_formats > 0) { rdpsnd->supported_formats = out_formats; } else { xfree(out_formats); DEBUG_WARN("no formats supported"); } pos = stream_get_pos(data_out); stream_set_pos(data_out, 2); stream_write_uint16(data_out, pos - 4); stream_set_pos(data_out, 18); stream_write_uint16(data_out, n_out_formats); stream_set_pos(data_out, pos); svc_plugin_send((rdpSvcPlugin*)rdpsnd, data_out); if (wVersion >= 6) { data_out = stream_new(8); stream_write_uint8(data_out, SNDC_QUALITYMODE); /* msgType */ stream_write_uint8(data_out, 0); /* bPad */ stream_write_uint16(data_out, 4); /* BodySize */ stream_write_uint16(data_out, HIGH_QUALITY); /* wQualityMode */ stream_write_uint16(data_out, 0); /* Reserved */ svc_plugin_send((rdpSvcPlugin*)rdpsnd, data_out); } } /* server is getting a feel of the round trip time */ static void rdpsnd_process_message_training(rdpsndPlugin* rdpsnd, STREAM* data_in) { uint16 wTimeStamp; uint16 wPackSize; STREAM* data_out; stream_read_uint16(data_in, wTimeStamp); stream_read_uint16(data_in, wPackSize); data_out = stream_new(8); stream_write_uint8(data_out, SNDC_TRAINING); /* msgType */ stream_write_uint8(data_out, 0); /* bPad */ stream_write_uint16(data_out, 4); /* BodySize */ stream_write_uint16(data_out, wTimeStamp); stream_write_uint16(data_out, wPackSize); svc_plugin_send((rdpSvcPlugin*)rdpsnd, data_out); } static void rdpsnd_process_message_wave_info(rdpsndPlugin* rdpsnd, STREAM* data_in, uint16 BodySize) { uint16 wFormatNo; stream_read_uint16(data_in, rdpsnd->wTimeStamp); stream_read_uint16(data_in, wFormatNo); stream_read_uint8(data_in, rdpsnd->cBlockNo); stream_seek(data_in, 3); /* bPad */ stream_read(data_in, rdpsnd->waveData, 4); rdpsnd->waveDataSize = BodySize - 8; rdpsnd->wave_timestamp = get_mstime(); rdpsnd->expectingWave = true; DEBUG_SVC("waveDataSize %d wFormatNo %d", rdpsnd->waveDataSize, wFormatNo); rdpsnd->close_timestamp = 0; if (!rdpsnd->is_open) { rdpsnd->current_format = wFormatNo; rdpsnd->is_open = true; if (rdpsnd->device) IFCALL(rdpsnd->device->Open, rdpsnd->device, &rdpsnd->supported_formats[wFormatNo], rdpsnd->latency); } else if (wFormatNo != rdpsnd->current_format) { rdpsnd->current_format = wFormatNo; if (rdpsnd->device) IFCALL(rdpsnd->device->SetFormat, rdpsnd->device, &rdpsnd->supported_formats[wFormatNo], rdpsnd->latency); } } /* header is not removed from data in this function */ static void rdpsnd_process_message_wave(rdpsndPlugin* rdpsnd, STREAM* data_in) { uint16 wTimeStamp; uint32 delay_ms; uint32 process_ms; struct data_out_item* item; rdpsnd->expectingWave = 0; memcpy(stream_get_head(data_in), rdpsnd->waveData, 4); if (stream_get_size(data_in) != rdpsnd->waveDataSize) { DEBUG_WARN("size error"); return; } if (rdpsnd->device) IFCALL(rdpsnd->device->Play, rdpsnd->device, stream_get_head(data_in), stream_get_size(data_in)); process_ms = get_mstime() - rdpsnd->wave_timestamp; delay_ms = 250; wTimeStamp = rdpsnd->wTimeStamp + delay_ms; DEBUG_SVC("data_size %d delay_ms %u process_ms %u", stream_get_size(data_in), delay_ms, process_ms); item = xnew(struct data_out_item); item->data_out = stream_new(8); stream_write_uint8(item->data_out, SNDC_WAVECONFIRM); stream_write_uint8(item->data_out, 0); stream_write_uint16(item->data_out, 4); stream_write_uint16(item->data_out, wTimeStamp); stream_write_uint8(item->data_out, rdpsnd->cBlockNo); /* cConfirmedBlockNo */ stream_write_uint8(item->data_out, 0); /* bPad */ item->out_timestamp = rdpsnd->wave_timestamp + delay_ms; list_enqueue(rdpsnd->data_out_list, item); rdpsnd->plugin.interval_ms = 10; } static void rdpsnd_process_message_close(rdpsndPlugin* rdpsnd) { DEBUG_SVC("server closes."); if (rdpsnd->device) IFCALL(rdpsnd->device->Start, rdpsnd->device); rdpsnd->close_timestamp = get_mstime() + 2000; rdpsnd->plugin.interval_ms = 10; } static void rdpsnd_process_message_setvolume(rdpsndPlugin* rdpsnd, STREAM* data_in) { uint32 dwVolume; stream_read_uint32(data_in, dwVolume); DEBUG_SVC("dwVolume 0x%X", dwVolume); if (rdpsnd->device) IFCALL(rdpsnd->device->SetVolume, rdpsnd->device, dwVolume); } static void rdpsnd_process_receive(rdpSvcPlugin* plugin, STREAM* data_in) { rdpsndPlugin* rdpsnd = (rdpsndPlugin*)plugin; uint8 msgType; uint16 BodySize; if (rdpsnd->expectingWave) { rdpsnd_process_message_wave(rdpsnd, data_in); stream_free(data_in); return; } stream_read_uint8(data_in, msgType); /* msgType */ stream_seek_uint8(data_in); /* bPad */ stream_read_uint16(data_in, BodySize); DEBUG_SVC("msgType %d BodySize %d", msgType, BodySize); switch (msgType) { case SNDC_FORMATS: rdpsnd_process_message_formats(rdpsnd, data_in); break; case SNDC_TRAINING: rdpsnd_process_message_training(rdpsnd, data_in); break; case SNDC_WAVE: rdpsnd_process_message_wave_info(rdpsnd, data_in, BodySize); break; case SNDC_CLOSE: rdpsnd_process_message_close(rdpsnd); break; case SNDC_SETVOLUME: rdpsnd_process_message_setvolume(rdpsnd, data_in); break; default: DEBUG_WARN("unknown msgType %d", msgType); break; } stream_free(data_in); } static void rdpsnd_register_device_plugin(rdpsndPlugin* rdpsnd, rdpsndDevicePlugin* device) { if (rdpsnd->device) { DEBUG_WARN("existing device, abort."); return; } rdpsnd->device = device; } static boolean rdpsnd_load_device_plugin(rdpsndPlugin* rdpsnd, const char* name, RDP_PLUGIN_DATA* data) { FREERDP_RDPSND_DEVICE_ENTRY_POINTS entryPoints; PFREERDP_RDPSND_DEVICE_ENTRY entry; char* fullname; if (strrchr(name, '.') != NULL) entry = (PFREERDP_RDPSND_DEVICE_ENTRY)freerdp_load_plugin(name, RDPSND_DEVICE_EXPORT_FUNC_NAME); else { fullname = xzalloc(strlen(name) + 8); strcpy(fullname, "rdpsnd_"); strcat(fullname, name); entry = (PFREERDP_RDPSND_DEVICE_ENTRY)freerdp_load_plugin(fullname, RDPSND_DEVICE_EXPORT_FUNC_NAME); xfree(fullname); } if (entry == NULL) { return false; } entryPoints.rdpsnd = rdpsnd; entryPoints.pRegisterRdpsndDevice = rdpsnd_register_device_plugin; entryPoints.plugin_data = data; if (entry(&entryPoints) != 0) { DEBUG_WARN("%s entry returns error.", name); return false; } return true; } static void rdpsnd_process_plugin_data(rdpsndPlugin* rdpsnd, RDP_PLUGIN_DATA* data) { if (strcmp((char*)data->data[0], "format") == 0) { rdpsnd->fixed_format = atoi(data->data[1]); } else if (strcmp((char*)data->data[0], "rate") == 0) { rdpsnd->fixed_rate = atoi(data->data[1]); } else if (strcmp((char*)data->data[0], "channel") == 0) { rdpsnd->fixed_channel = atoi(data->data[1]); } else if (strcmp((char*)data->data[0], "latency") == 0) { rdpsnd->latency = atoi(data->data[1]); } else { rdpsnd_load_device_plugin(rdpsnd, (char*)data->data[0], data); } } static void rdpsnd_process_connect(rdpSvcPlugin* plugin) { rdpsndPlugin* rdpsnd = (rdpsndPlugin*)plugin; RDP_PLUGIN_DATA* data; RDP_PLUGIN_DATA default_data[2] = { { 0 }, { 0 } }; DEBUG_SVC("connecting"); plugin->interval_callback = rdpsnd_process_interval; rdpsnd->data_out_list = list_new(); rdpsnd->latency = -1; data = (RDP_PLUGIN_DATA*)plugin->channel_entry_points.pExtendedData; while (data && data->size > 0) { rdpsnd_process_plugin_data(rdpsnd, data); data = (RDP_PLUGIN_DATA*) (((void*) data) + data->size); } if (rdpsnd->device == NULL) { default_data[0].size = sizeof(RDP_PLUGIN_DATA); default_data[0].data[0] = "pulse"; default_data[0].data[1] = ""; if (!rdpsnd_load_device_plugin(rdpsnd, "pulse", default_data)) { default_data[0].data[0] = "alsa"; default_data[0].data[1] = "default"; rdpsnd_load_device_plugin(rdpsnd, "alsa", default_data); } } if (rdpsnd->device == NULL) { DEBUG_WARN("no sound device."); } } static void rdpsnd_process_event(rdpSvcPlugin* plugin, RDP_EVENT* event) { freerdp_event_free(event); } static void rdpsnd_process_terminate(rdpSvcPlugin* plugin) { rdpsndPlugin* rdpsnd = (rdpsndPlugin*)plugin; struct data_out_item* item; if (rdpsnd->device) IFCALL(rdpsnd->device->Free, rdpsnd->device); while ((item = list_dequeue(rdpsnd->data_out_list)) != NULL) { stream_free(item->data_out); xfree(item); } list_free(rdpsnd->data_out_list); rdpsnd_free_supported_formats(rdpsnd); xfree(plugin); } DEFINE_SVC_PLUGIN(rdpsnd, "rdpsnd", CHANNEL_OPTION_INITIALIZED | CHANNEL_OPTION_ENCRYPT_RDP) FreeRDP-1.0.2/channels/rdpsnd/rdpsnd_main.h000066400000000000000000000045511207112532300204760ustar00rootroot00000000000000/** * FreeRDP: A Remote Desktop Protocol client. * Audio Output Virtual Channel * * Copyright 2010-2011 Vic Lee * * 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. */ #ifndef __RDPSND_MAIN_H #define __RDPSND_MAIN_H typedef struct rdpsnd_plugin rdpsndPlugin; typedef struct rdpsnd_format rdpsndFormat; struct rdpsnd_format { uint16 wFormatTag; uint16 nChannels; uint32 nSamplesPerSec; uint16 nBlockAlign; uint16 wBitsPerSample; uint16 cbSize; uint8* data; }; typedef struct rdpsnd_device_plugin rdpsndDevicePlugin; typedef boolean (*pcFormatSupported) (rdpsndDevicePlugin* device, rdpsndFormat* format); typedef void (*pcOpen) (rdpsndDevicePlugin* device, rdpsndFormat* format, int latency); typedef void (*pcSetFormat) (rdpsndDevicePlugin* device, rdpsndFormat* format, int latency); typedef void (*pcSetVolume) (rdpsndDevicePlugin* device, uint32 value); typedef void (*pcPlay) (rdpsndDevicePlugin* device, uint8* data, int size); typedef void (*pcStart) (rdpsndDevicePlugin* device); typedef void (*pcClose) (rdpsndDevicePlugin* device); typedef void (*pcFree) (rdpsndDevicePlugin* device); struct rdpsnd_device_plugin { pcFormatSupported FormatSupported; pcOpen Open; pcSetFormat SetFormat; pcSetVolume SetVolume; pcPlay Play; pcStart Start; pcClose Close; pcFree Free; }; #define RDPSND_DEVICE_EXPORT_FUNC_NAME "FreeRDPRdpsndDeviceEntry" typedef void (*PREGISTERRDPSNDDEVICE)(rdpsndPlugin* rdpsnd, rdpsndDevicePlugin* device); struct _FREERDP_RDPSND_DEVICE_ENTRY_POINTS { rdpsndPlugin* rdpsnd; PREGISTERRDPSNDDEVICE pRegisterRdpsndDevice; RDP_PLUGIN_DATA* plugin_data; }; typedef struct _FREERDP_RDPSND_DEVICE_ENTRY_POINTS FREERDP_RDPSND_DEVICE_ENTRY_POINTS; typedef FREERDP_RDPSND_DEVICE_ENTRY_POINTS* PFREERDP_RDPSND_DEVICE_ENTRY_POINTS; typedef int (*PFREERDP_RDPSND_DEVICE_ENTRY)(PFREERDP_RDPSND_DEVICE_ENTRY_POINTS pEntryPoints); #endif /* __RDPSND_MAIN_H */ FreeRDP-1.0.2/client/000077500000000000000000000000001207112532300142135ustar00rootroot00000000000000FreeRDP-1.0.2/client/CMakeLists.txt000066400000000000000000000021771207112532300167620ustar00rootroot00000000000000# FreeRDP: A Remote Desktop Protocol Client # FreeRDP Client User Interfaces # # Copyright 2011 O.S. Systems Software Ltda. # Copyright 2011 Otavio Salvador # Copyright 2011 Marc-Andre Moreau # # 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. # User Interfaces if(NOT WIN32) # Build Test Client add_subdirectory(test) # Build X11 Client find_suggested_package(X11) if(WITH_X11) add_subdirectory(X11) endif() # Build DirectFB Client find_optional_package(DirectFB) if(WITH_DIRECTFB) add_subdirectory(DirectFB) endif() else() # Build Windows Client add_subdirectory(Windows) endif() FreeRDP-1.0.2/client/DirectFB/000077500000000000000000000000001207112532300156355ustar00rootroot00000000000000FreeRDP-1.0.2/client/DirectFB/CMakeLists.txt000066400000000000000000000024031207112532300203740ustar00rootroot00000000000000# FreeRDP: A Remote Desktop Protocol Client # FreeRDP DirectFB Client # # Copyright 2011 O.S. Systems Software Ltda. # Copyright 2011 Otavio Salvador # Copyright 2011 Marc-Andre Moreau # # 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. include_directories(${DIRECTFB_INCLUDE_DIRS}) add_executable(dfreerdp df_event.c df_event.h df_graphics.c df_graphics.c dfreerdp.c dfreerdp.h) target_link_libraries(dfreerdp freerdp-core) target_link_libraries(dfreerdp freerdp-gdi) target_link_libraries(dfreerdp freerdp-kbd) target_link_libraries(dfreerdp freerdp-channels) target_link_libraries(dfreerdp freerdp-utils) target_link_libraries(dfreerdp ${DIRECTFB_LIBRARIES}) install(TARGETS dfreerdp DESTINATION ${CMAKE_INSTALL_BINDIR}) FreeRDP-1.0.2/client/DirectFB/df_event.c000066400000000000000000000213341207112532300175760ustar00rootroot00000000000000/** * FreeRDP: A Remote Desktop Protocol Client * DirectFB Event Handling * * Copyright 2011 Marc-Andre Moreau * * 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. */ #include #include #include "df_event.h" static uint8 keymap[256]; static uint8 functionmap[128]; void df_keyboard_init() { memset(keymap, 0, sizeof(keymap)); /* Map DirectFB keycodes to Virtual Key Codes */ keymap[DIKI_A - DIKI_UNKNOWN] = VK_KEY_A; keymap[DIKI_B - DIKI_UNKNOWN] = VK_KEY_B; keymap[DIKI_C - DIKI_UNKNOWN] = VK_KEY_C; keymap[DIKI_D - DIKI_UNKNOWN] = VK_KEY_D; keymap[DIKI_E - DIKI_UNKNOWN] = VK_KEY_E; keymap[DIKI_F - DIKI_UNKNOWN] = VK_KEY_F; keymap[DIKI_G - DIKI_UNKNOWN] = VK_KEY_G; keymap[DIKI_H - DIKI_UNKNOWN] = VK_KEY_H; keymap[DIKI_I - DIKI_UNKNOWN] = VK_KEY_I; keymap[DIKI_J - DIKI_UNKNOWN] = VK_KEY_J; keymap[DIKI_K - DIKI_UNKNOWN] = VK_KEY_K; keymap[DIKI_L - DIKI_UNKNOWN] = VK_KEY_L; keymap[DIKI_M - DIKI_UNKNOWN] = VK_KEY_M; keymap[DIKI_N - DIKI_UNKNOWN] = VK_KEY_N; keymap[DIKI_O - DIKI_UNKNOWN] = VK_KEY_O; keymap[DIKI_P - DIKI_UNKNOWN] = VK_KEY_P; keymap[DIKI_Q - DIKI_UNKNOWN] = VK_KEY_Q; keymap[DIKI_R - DIKI_UNKNOWN] = VK_KEY_R; keymap[DIKI_S - DIKI_UNKNOWN] = VK_KEY_S; keymap[DIKI_T - DIKI_UNKNOWN] = VK_KEY_T; keymap[DIKI_U - DIKI_UNKNOWN] = VK_KEY_U; keymap[DIKI_V - DIKI_UNKNOWN] = VK_KEY_V; keymap[DIKI_W - DIKI_UNKNOWN] = VK_KEY_W; keymap[DIKI_X - DIKI_UNKNOWN] = VK_KEY_X; keymap[DIKI_Y - DIKI_UNKNOWN] = VK_KEY_Y; keymap[DIKI_Z - DIKI_UNKNOWN] = VK_KEY_Z; keymap[DIKI_0 - DIKI_UNKNOWN] = VK_KEY_0; keymap[DIKI_1 - DIKI_UNKNOWN] = VK_KEY_1; keymap[DIKI_2 - DIKI_UNKNOWN] = VK_KEY_2; keymap[DIKI_3 - DIKI_UNKNOWN] = VK_KEY_3; keymap[DIKI_4 - DIKI_UNKNOWN] = VK_KEY_4; keymap[DIKI_5 - DIKI_UNKNOWN] = VK_KEY_5; keymap[DIKI_6 - DIKI_UNKNOWN] = VK_KEY_6; keymap[DIKI_7 - DIKI_UNKNOWN] = VK_KEY_7; keymap[DIKI_8 - DIKI_UNKNOWN] = VK_KEY_8; keymap[DIKI_9 - DIKI_UNKNOWN] = VK_KEY_9; keymap[DIKI_F1 - DIKI_UNKNOWN] = VK_F1; keymap[DIKI_F2 - DIKI_UNKNOWN] = VK_F2; keymap[DIKI_F3 - DIKI_UNKNOWN] = VK_F3; keymap[DIKI_F4 - DIKI_UNKNOWN] = VK_F4; keymap[DIKI_F5 - DIKI_UNKNOWN] = VK_F5; keymap[DIKI_F6 - DIKI_UNKNOWN] = VK_F6; keymap[DIKI_F7 - DIKI_UNKNOWN] = VK_F7; keymap[DIKI_F8 - DIKI_UNKNOWN] = VK_F8; keymap[DIKI_F9 - DIKI_UNKNOWN] = VK_F9; keymap[DIKI_F10 - DIKI_UNKNOWN] = VK_F10; keymap[DIKI_F11 - DIKI_UNKNOWN] = VK_F11; keymap[DIKI_F12 - DIKI_UNKNOWN] = VK_F12; keymap[DIKI_COMMA - DIKI_UNKNOWN] = VK_OEM_COMMA; keymap[DIKI_PERIOD - DIKI_UNKNOWN] = VK_OEM_PERIOD; keymap[DIKI_MINUS_SIGN - DIKI_UNKNOWN] = VK_OEM_MINUS; keymap[DIKI_EQUALS_SIGN - DIKI_UNKNOWN] = VK_OEM_PLUS; keymap[DIKI_ESCAPE - DIKI_UNKNOWN] = VK_ESCAPE; keymap[DIKI_LEFT - DIKI_UNKNOWN] = VK_LEFT; keymap[DIKI_RIGHT - DIKI_UNKNOWN] = VK_RIGHT; keymap[DIKI_UP - DIKI_UNKNOWN] = VK_UP; keymap[DIKI_DOWN - DIKI_UNKNOWN] = VK_DOWN; keymap[DIKI_CONTROL_L - DIKI_UNKNOWN] = VK_LCONTROL; keymap[DIKI_CONTROL_R - DIKI_UNKNOWN] = VK_RCONTROL; keymap[DIKI_SHIFT_L - DIKI_UNKNOWN] = VK_LSHIFT; keymap[DIKI_SHIFT_R - DIKI_UNKNOWN] = VK_RSHIFT; keymap[DIKI_ALT_L - DIKI_UNKNOWN] = VK_LMENU; keymap[DIKI_ALT_R - DIKI_UNKNOWN] = VK_RMENU; keymap[DIKI_TAB - DIKI_UNKNOWN] = VK_TAB; keymap[DIKI_ENTER - DIKI_UNKNOWN] = VK_RETURN; keymap[DIKI_SPACE - DIKI_UNKNOWN] = VK_SPACE; keymap[DIKI_BACKSPACE - DIKI_UNKNOWN] = VK_BACK; keymap[DIKI_INSERT - DIKI_UNKNOWN] = VK_INSERT; keymap[DIKI_DELETE - DIKI_UNKNOWN] = VK_DELETE; keymap[DIKI_HOME - DIKI_UNKNOWN] = VK_HOME; keymap[DIKI_END - DIKI_UNKNOWN] = VK_END; keymap[DIKI_PAGE_UP - DIKI_UNKNOWN] = VK_PRIOR; keymap[DIKI_PAGE_DOWN - DIKI_UNKNOWN] = VK_NEXT; keymap[DIKI_CAPS_LOCK - DIKI_UNKNOWN] = VK_CAPITAL; keymap[DIKI_NUM_LOCK - DIKI_UNKNOWN] = VK_NUMLOCK; keymap[DIKI_SCROLL_LOCK - DIKI_UNKNOWN] = VK_SCROLL; keymap[DIKI_PRINT - DIKI_UNKNOWN] = VK_PRINT; keymap[DIKI_PAUSE - DIKI_UNKNOWN] = VK_PAUSE; keymap[DIKI_KP_DIV - DIKI_UNKNOWN] = VK_DIVIDE; keymap[DIKI_KP_MULT - DIKI_UNKNOWN] = VK_MULTIPLY; keymap[DIKI_KP_MINUS - DIKI_UNKNOWN] = VK_SUBTRACT; keymap[DIKI_KP_PLUS - DIKI_UNKNOWN] = VK_ADD; keymap[DIKI_KP_ENTER - DIKI_UNKNOWN] = VK_RETURN; keymap[DIKI_KP_DECIMAL - DIKI_UNKNOWN] = VK_DECIMAL; keymap[DIKI_QUOTE_LEFT - DIKI_UNKNOWN] = VK_OEM_3; keymap[DIKI_BRACKET_LEFT - DIKI_UNKNOWN] = VK_OEM_4; keymap[DIKI_BRACKET_RIGHT - DIKI_UNKNOWN] = VK_OEM_6; keymap[DIKI_BACKSLASH - DIKI_UNKNOWN] = VK_OEM_5; keymap[DIKI_SEMICOLON - DIKI_UNKNOWN] = VK_OEM_1; keymap[DIKI_QUOTE_RIGHT - DIKI_UNKNOWN] = VK_OEM_7; keymap[DIKI_COMMA - DIKI_UNKNOWN] = VK_OEM_COMMA; keymap[DIKI_PERIOD - DIKI_UNKNOWN] = VK_OEM_PERIOD; keymap[DIKI_SLASH - DIKI_UNKNOWN] = VK_OEM_2; keymap[DIKI_LESS_SIGN - DIKI_UNKNOWN] = 0; keymap[DIKI_KP_0 - DIKI_UNKNOWN] = VK_NUMPAD0; keymap[DIKI_KP_1 - DIKI_UNKNOWN] = VK_NUMPAD1; keymap[DIKI_KP_2 - DIKI_UNKNOWN] = VK_NUMPAD2; keymap[DIKI_KP_3 - DIKI_UNKNOWN] = VK_NUMPAD3; keymap[DIKI_KP_4 - DIKI_UNKNOWN] = VK_NUMPAD4; keymap[DIKI_KP_5 - DIKI_UNKNOWN] = VK_NUMPAD5; keymap[DIKI_KP_6 - DIKI_UNKNOWN] = VK_NUMPAD6; keymap[DIKI_KP_7 - DIKI_UNKNOWN] = VK_NUMPAD7; keymap[DIKI_KP_8 - DIKI_UNKNOWN] = VK_NUMPAD8; keymap[DIKI_KP_9 - DIKI_UNKNOWN] = VK_NUMPAD9; keymap[DIKI_META_L - DIKI_UNKNOWN] = VK_LWIN; keymap[DIKI_META_R - DIKI_UNKNOWN] = VK_RWIN; keymap[DIKI_SUPER_L - DIKI_UNKNOWN] = VK_APPS; memset(functionmap, 0, sizeof(functionmap)); functionmap[DFB_FUNCTION_KEY(23) - DFB_FUNCTION_KEY(0)] = VK_HANGUL; functionmap[DFB_FUNCTION_KEY(24) - DFB_FUNCTION_KEY(0)] = VK_HANJA; } void df_send_mouse_button_event(rdpInput* input, boolean down, uint32 button, uint16 x, uint16 y) { uint16 flags; flags = (down) ? PTR_FLAGS_DOWN : 0; if (button == DIBI_LEFT) flags |= PTR_FLAGS_BUTTON1; else if (button == DIBI_RIGHT) flags |= PTR_FLAGS_BUTTON2; else if (button == DIBI_MIDDLE) flags |= PTR_FLAGS_BUTTON3; if (flags != 0) input->MouseEvent(input, flags, x, y); } void df_send_mouse_motion_event(rdpInput* input, uint16 x, uint16 y) { input->MouseEvent(input, PTR_FLAGS_MOVE, x, y); } void df_send_mouse_wheel_event(rdpInput* input, sint16 axisrel, uint16 x, uint16 y) { uint16 flags = PTR_FLAGS_WHEEL; if (axisrel < 0) flags |= 0x0078; else flags |= PTR_FLAGS_WHEEL_NEGATIVE | 0x0088; input->MouseEvent(input, flags, x, y); } void df_send_keyboard_event(rdpInput* input, boolean down, uint8 keycode, uint8 function) { uint16 flags; uint8 vkcode; uint8 scancode; boolean extended; if (keycode) vkcode = keymap[keycode]; else if (function) vkcode = functionmap[function]; else return; scancode = freerdp_kbd_get_scancode_by_virtualkey(vkcode, &extended); flags = (extended) ? KBD_FLAGS_EXTENDED : 0; flags |= (down) ? KBD_FLAGS_DOWN : KBD_FLAGS_RELEASE; input->KeyboardEvent(input, flags, scancode); } boolean df_event_process(freerdp* instance, DFBEvent* event) { int flags; rdpGdi* gdi; dfInfo* dfi; int pointer_x; int pointer_y; DFBInputEvent* input_event; gdi = instance->context->gdi; dfi = ((dfContext*) instance->context)->dfi; dfi->layer->GetCursorPosition(dfi->layer, &pointer_x, &pointer_y); if (event->clazz == DFEC_INPUT) { flags = 0; input_event = (DFBInputEvent*) event; switch (input_event->type) { case DIET_AXISMOTION: if (pointer_x > (gdi->width - 1)) pointer_x = gdi->width - 1; if (pointer_y > (gdi->height - 1)) pointer_y = gdi->height - 1; if (input_event->axis == DIAI_Z) { df_send_mouse_wheel_event(instance->input, input_event->axisrel, pointer_x, pointer_y); } else { df_send_mouse_motion_event(instance->input, pointer_x, pointer_y); } break; case DIET_BUTTONPRESS: df_send_mouse_button_event(instance->input, true, input_event->button, pointer_x, pointer_y); break; case DIET_BUTTONRELEASE: df_send_mouse_button_event(instance->input, false, input_event->button, pointer_x, pointer_y); break; case DIET_KEYPRESS: df_send_keyboard_event(instance->input, true, input_event->key_id - DIKI_UNKNOWN, input_event->key_symbol - DFB_FUNCTION_KEY(0)); break; case DIET_KEYRELEASE: df_send_keyboard_event(instance->input, false, input_event->key_id - DIKI_UNKNOWN, input_event->key_symbol - DFB_FUNCTION_KEY(0)); break; case DIET_UNKNOWN: break; } } return true; } FreeRDP-1.0.2/client/DirectFB/df_event.h000066400000000000000000000015671207112532300176110ustar00rootroot00000000000000/** * FreeRDP: A Remote Desktop Protocol Client * DirectFB Event Handling * * Copyright 2011 Marc-Andre Moreau * * 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. */ #ifndef __DF_EVENT_H #define __DF_EVENT_H #include "dfreerdp.h" void df_keyboard_init(); boolean df_event_process(freerdp* instance, DFBEvent* event); #endif /* __DF_EVENT_H */ FreeRDP-1.0.2/client/DirectFB/df_graphics.c000066400000000000000000000057751207112532300202700ustar00rootroot00000000000000/** * FreeRDP: A Remote Desktop Protocol Client * DirectFB Graphical Objects * * Copyright 2011 Marc-Andre Moreau * * 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. */ #include #include "df_graphics.h" /* Pointer Class */ void df_Pointer_New(rdpContext* context, rdpPointer* pointer) { dfInfo* dfi; DFBResult result; dfPointer* df_pointer; DFBSurfaceDescription dsc; dfi = ((dfContext*) context)->dfi; df_pointer = (dfPointer*) pointer; dsc.flags = DSDESC_CAPS | DSDESC_WIDTH | DSDESC_HEIGHT | DSDESC_PIXELFORMAT; dsc.caps = DSCAPS_SYSTEMONLY; dsc.width = pointer->width; dsc.height = pointer->height; dsc.pixelformat = DSPF_ARGB; result = dfi->dfb->CreateSurface(dfi->dfb, &dsc, &(df_pointer->surface)); if (result == DFB_OK) { int pitch; uint8* point = NULL; df_pointer->xhot = pointer->xPos; df_pointer->yhot = pointer->yPos; result = df_pointer->surface->Lock(df_pointer->surface, DSLF_WRITE, (void**) &point, &pitch); if (result != DFB_OK) { DirectFBErrorFatal("Error while creating pointer surface", result); return; } if ((pointer->andMaskData != 0) && (pointer->xorMaskData != 0)) { freerdp_alpha_cursor_convert(point, pointer->xorMaskData, pointer->andMaskData, pointer->width, pointer->height, pointer->xorBpp, dfi->clrconv); } if (pointer->xorBpp > 24) { freerdp_image_swap_color_order(point, pointer->width, pointer->height); } df_pointer->surface->Unlock(df_pointer->surface); } } void df_Pointer_Free(rdpContext* context, rdpPointer* pointer) { dfPointer* df_pointer = (dfPointer*) pointer; df_pointer->surface->Release(df_pointer->surface); } void df_Pointer_Set(rdpContext* context, rdpPointer* pointer) { dfInfo* dfi; DFBResult result; dfPointer* df_pointer; dfi = ((dfContext*) context)->dfi; df_pointer = (dfPointer*) pointer; dfi->layer->SetCooperativeLevel(dfi->layer, DLSCL_ADMINISTRATIVE); result = dfi->layer->SetCursorShape(dfi->layer, df_pointer->surface, df_pointer->xhot, df_pointer->yhot); if (result != DFB_OK) { DirectFBErrorFatal("SetCursorShape Error", result); return; } dfi->layer->SetCooperativeLevel(dfi->layer, DLSCL_SHARED); } /* Graphics Module */ void df_register_graphics(rdpGraphics* graphics) { rdpPointer* pointer; pointer = xnew(rdpPointer); pointer->size = sizeof(dfPointer); pointer->New = df_Pointer_New; pointer->Free = df_Pointer_Free; pointer->Set = df_Pointer_Set; graphics_register_pointer(graphics, pointer); xfree(pointer); } FreeRDP-1.0.2/client/DirectFB/df_graphics.h000066400000000000000000000015361207112532300202640ustar00rootroot00000000000000/** * FreeRDP: A Remote Desktop Protocol Client * DirectFB Graphical Objects * * Copyright 2011 Marc-Andre Moreau * * 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. */ #ifndef __DF_GRAPHICS_H #define __DF_GRAPHICS_H #include "dfreerdp.h" void df_register_graphics(rdpGraphics* graphics); #endif /* __DF_GRAPHICS_H */ FreeRDP-1.0.2/client/DirectFB/dfreerdp.c000066400000000000000000000275631207112532300176110ustar00rootroot00000000000000/** * FreeRDP: A Remote Desktop Protocol Client * DirectFB Client * * Copyright 2011 Marc-Andre Moreau * * 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. */ #include #include #include #include #include #include #include #include #include #include "df_event.h" #include "df_graphics.h" #include "dfreerdp.h" static freerdp_sem g_sem; static int g_thread_count = 0; struct thread_data { freerdp* instance; }; void df_context_new(freerdp* instance, rdpContext* context) { context->channels = freerdp_channels_new(); } void df_context_free(freerdp* instance, rdpContext* context) { } void df_begin_paint(rdpContext* context) { rdpGdi* gdi = context->gdi; gdi->primary->hdc->hwnd->invalid->null = 1; } void df_end_paint(rdpContext* context) { rdpGdi* gdi; dfInfo* dfi; gdi = context->gdi; dfi = ((dfContext*) context)->dfi; if (gdi->primary->hdc->hwnd->invalid->null) return; #if 1 dfi->update_rect.x = gdi->primary->hdc->hwnd->invalid->x; dfi->update_rect.y = gdi->primary->hdc->hwnd->invalid->y; dfi->update_rect.w = gdi->primary->hdc->hwnd->invalid->w; dfi->update_rect.h = gdi->primary->hdc->hwnd->invalid->h; #else dfi->update_rect.x = 0; dfi->update_rect.y = 0; dfi->update_rect.w = gdi->width; dfi->update_rect.h = gdi->height; #endif dfi->primary->Blit(dfi->primary, dfi->surface, &(dfi->update_rect), dfi->update_rect.x, dfi->update_rect.y); } boolean df_get_fds(freerdp* instance, void** rfds, int* rcount, void** wfds, int* wcount) { dfInfo* dfi; dfi = ((dfContext*) instance->context)->dfi; rfds[*rcount] = (void*)(long)(dfi->read_fds); (*rcount)++; return true; } boolean df_check_fds(freerdp* instance, fd_set* set) { dfInfo* dfi; dfi = ((dfContext*) instance->context)->dfi; if (!FD_ISSET(dfi->read_fds, set)) return true; if (read(dfi->read_fds, &(dfi->event), sizeof(dfi->event)) > 0) df_event_process(instance, &(dfi->event)); return true; } boolean df_pre_connect(freerdp* instance) { dfInfo* dfi; boolean bitmap_cache; dfContext* context; rdpSettings* settings; dfi = (dfInfo*) xzalloc(sizeof(dfInfo)); context = ((dfContext*) instance->context); context->dfi = dfi; settings = instance->settings; bitmap_cache = settings->bitmap_cache; settings->order_support[NEG_DSTBLT_INDEX] = true; settings->order_support[NEG_PATBLT_INDEX] = true; settings->order_support[NEG_SCRBLT_INDEX] = true; settings->order_support[NEG_OPAQUE_RECT_INDEX] = true; settings->order_support[NEG_DRAWNINEGRID_INDEX] = false; settings->order_support[NEG_MULTIDSTBLT_INDEX] = false; settings->order_support[NEG_MULTIPATBLT_INDEX] = false; settings->order_support[NEG_MULTISCRBLT_INDEX] = false; settings->order_support[NEG_MULTIOPAQUERECT_INDEX] = true; settings->order_support[NEG_MULTI_DRAWNINEGRID_INDEX] = false; settings->order_support[NEG_LINETO_INDEX] = true; settings->order_support[NEG_POLYLINE_INDEX] = true; settings->order_support[NEG_MEMBLT_INDEX] = bitmap_cache; settings->order_support[NEG_MEM3BLT_INDEX] = false; settings->order_support[NEG_MEMBLT_V2_INDEX] = bitmap_cache; settings->order_support[NEG_MEM3BLT_V2_INDEX] = false; settings->order_support[NEG_SAVEBITMAP_INDEX] = false; settings->order_support[NEG_GLYPH_INDEX_INDEX] = false; settings->order_support[NEG_FAST_INDEX_INDEX] = false; settings->order_support[NEG_FAST_GLYPH_INDEX] = false; settings->order_support[NEG_POLYGON_SC_INDEX] = false; settings->order_support[NEG_POLYGON_CB_INDEX] = false; settings->order_support[NEG_ELLIPSE_SC_INDEX] = false; settings->order_support[NEG_ELLIPSE_CB_INDEX] = false; dfi->clrconv = xnew(CLRCONV); dfi->clrconv->alpha = 1; dfi->clrconv->invert = 0; dfi->clrconv->rgb555 = 0; dfi->clrconv->palette = xnew(rdpPalette); freerdp_channels_pre_connect(instance->context->channels, instance); return true; } boolean df_post_connect(freerdp* instance) { rdpGdi* gdi; dfInfo* dfi; dfContext* context; context = ((dfContext*) instance->context); dfi = context->dfi; gdi_init(instance, CLRCONV_ALPHA | CLRCONV_INVERT | CLRBUF_16BPP | CLRBUF_32BPP, NULL); gdi = instance->context->gdi; dfi->err = DirectFBCreate(&(dfi->dfb)); dfi->dsc.flags = DSDESC_CAPS; dfi->dsc.caps = DSCAPS_PRIMARY; dfi->err = dfi->dfb->CreateSurface(dfi->dfb, &(dfi->dsc), &(dfi->primary)); dfi->err = dfi->primary->GetSize(dfi->primary, &(gdi->width), &(gdi->height)); dfi->dfb->SetVideoMode(dfi->dfb, gdi->width, gdi->height, gdi->dstBpp); dfi->dfb->CreateInputEventBuffer(dfi->dfb, DICAPS_ALL, DFB_TRUE, &(dfi->event_buffer)); dfi->event_buffer->CreateFileDescriptor(dfi->event_buffer, &(dfi->read_fds)); dfi->dfb->GetDisplayLayer(dfi->dfb, 0, &(dfi->layer)); dfi->layer->EnableCursor(dfi->layer, 1); dfi->dsc.flags = DSDESC_CAPS | DSDESC_WIDTH | DSDESC_HEIGHT | DSDESC_PREALLOCATED | DSDESC_PIXELFORMAT; dfi->dsc.caps = DSCAPS_SYSTEMONLY; dfi->dsc.width = gdi->width; dfi->dsc.height = gdi->height; if (gdi->dstBpp == 32 || gdi->dstBpp == 24) dfi->dsc.pixelformat = DSPF_AiRGB; else if (gdi->dstBpp == 16 || gdi->dstBpp == 15) dfi->dsc.pixelformat = DSPF_RGB16; else if (gdi->dstBpp == 8) dfi->dsc.pixelformat = DSPF_RGB332; else dfi->dsc.pixelformat = DSPF_AiRGB; dfi->dsc.preallocated[0].data = gdi->primary_buffer; dfi->dsc.preallocated[0].pitch = gdi->width * gdi->bytesPerPixel; dfi->dfb->CreateSurface(dfi->dfb, &(dfi->dsc), &(dfi->surface)); instance->update->BeginPaint = df_begin_paint; instance->update->EndPaint = df_end_paint; df_keyboard_init(); pointer_cache_register_callbacks(instance->update); df_register_graphics(instance->context->graphics); freerdp_channels_post_connect(instance->context->channels, instance); return true; } static int df_process_plugin_args(rdpSettings* settings, const char* name, RDP_PLUGIN_DATA* plugin_data, void* user_data) { rdpChannels* channels = (rdpChannels*) user_data; printf("loading plugin %s\n", name); freerdp_channels_load_plugin(channels, settings, name, plugin_data); return 1; } boolean df_verify_certificate(freerdp* instance, char* subject, char* issuer, char* fingerprint) { printf("Certificate details:\n"); printf("\tSubject: %s\n", subject); printf("\tIssuer: %s\n", issuer); printf("\tThumbprint: %s\n", fingerprint); printf("The above X.509 certificate could not be verified, possibly because you do not have " "the CA certificate in your certificate store, or the certificate has expired. " "Please look at the documentation on how to create local certificate store for a private CA.\n"); char answer; while (1) { printf("Do you trust the above certificate? (Y/N) "); answer = fgetc(stdin); if (answer == 'y' || answer == 'Y') { return true; } else if (answer == 'n' || answer == 'N') { break; } } return false; } static int df_receive_channel_data(freerdp* instance, int channelId, uint8* data, int size, int flags, int total_size) { return freerdp_channels_data(instance, channelId, data, size, flags, total_size); } static void df_process_cb_monitor_ready_event(rdpChannels* channels, freerdp* instance) { RDP_EVENT* event; RDP_CB_FORMAT_LIST_EVENT* format_list_event; event = freerdp_event_new(RDP_EVENT_CLASS_CLIPRDR, RDP_EVENT_TYPE_CB_FORMAT_LIST, NULL, NULL); format_list_event = (RDP_CB_FORMAT_LIST_EVENT*)event; format_list_event->num_formats = 0; freerdp_channels_send_event(channels, event); } static void df_process_channel_event(rdpChannels* channels, freerdp* instance) { RDP_EVENT* event; event = freerdp_channels_pop_event(channels); if (event) { switch (event->event_type) { case RDP_EVENT_TYPE_CB_MONITOR_READY: df_process_cb_monitor_ready_event(channels, instance); break; default: printf("df_process_channel_event: unknown event type %d\n", event->event_type); break; } freerdp_event_free(event); } } static void df_free(dfInfo* dfi) { dfi->dfb->Release(dfi->dfb); xfree(dfi); } int dfreerdp_run(freerdp* instance) { int i; int fds; int max_fds; int rcount; int wcount; void* rfds[32]; void* wfds[32]; fd_set rfds_set; fd_set wfds_set; dfInfo* dfi; dfContext* context; rdpChannels* channels; memset(rfds, 0, sizeof(rfds)); memset(wfds, 0, sizeof(wfds)); if (!freerdp_connect(instance)) return 0; context = (dfContext*) instance->context; dfi = context->dfi; channels = instance->context->channels; while (1) { rcount = 0; wcount = 0; if (freerdp_get_fds(instance, rfds, &rcount, wfds, &wcount) != true) { printf("Failed to get FreeRDP file descriptor\n"); break; } if (freerdp_channels_get_fds(channels, instance, rfds, &rcount, wfds, &wcount) != true) { printf("Failed to get channel manager file descriptor\n"); break; } if (df_get_fds(instance, rfds, &rcount, wfds, &wcount) != true) { printf("Failed to get dfreerdp file descriptor\n"); break; } max_fds = 0; FD_ZERO(&rfds_set); FD_ZERO(&wfds_set); for (i = 0; i < rcount; i++) { fds = (int)(long)(rfds[i]); if (fds > max_fds) max_fds = fds; FD_SET(fds, &rfds_set); } if (max_fds == 0) break; if (select(max_fds + 1, &rfds_set, &wfds_set, NULL, NULL) == -1) { /* these are not really errors */ if (!((errno == EAGAIN) || (errno == EWOULDBLOCK) || (errno == EINPROGRESS) || (errno == EINTR))) /* signal occurred */ { printf("dfreerdp_run: select failed\n"); break; } } if (freerdp_check_fds(instance) != true) { printf("Failed to check FreeRDP file descriptor\n"); break; } if (df_check_fds(instance, &rfds_set) != true) { printf("Failed to check dfreerdp file descriptor\n"); break; } if (freerdp_channels_check_fds(channels, instance) != true) { printf("Failed to check channel manager file descriptor\n"); break; } df_process_channel_event(channels, instance); } freerdp_channels_close(channels, instance); freerdp_channels_free(channels); df_free(dfi); gdi_free(instance); freerdp_disconnect(instance); freerdp_free(instance); return 0; } void* thread_func(void* param) { struct thread_data* data; data = (struct thread_data*) param; dfreerdp_run(data->instance); xfree(data); pthread_detach(pthread_self()); g_thread_count--; if (g_thread_count < 1) freerdp_sem_signal(g_sem); return NULL; } int main(int argc, char* argv[]) { pthread_t thread; freerdp* instance; dfContext* context; rdpChannels* channels; struct thread_data* data; setlocale(LC_ALL, ""); freerdp_channels_global_init(); g_sem = freerdp_sem_new(1); instance = freerdp_new(); instance->PreConnect = df_pre_connect; instance->PostConnect = df_post_connect; instance->VerifyCertificate = df_verify_certificate; instance->ReceiveChannelData = df_receive_channel_data; instance->context_size = sizeof(dfContext); instance->ContextNew = df_context_new; instance->ContextFree = df_context_free; freerdp_context_new(instance); context = (dfContext*) instance->context; channels = instance->context->channels; DirectFBInit(&argc, &argv); freerdp_parse_args(instance->settings, argc, argv, df_process_plugin_args, channels, NULL, NULL); data = (struct thread_data*) xzalloc(sizeof(struct thread_data)); data->instance = instance; g_thread_count++; pthread_create(&thread, 0, thread_func, data); while (g_thread_count > 0) { freerdp_sem_wait(g_sem); } freerdp_channels_global_uninit(); return 0; } FreeRDP-1.0.2/client/DirectFB/dfreerdp.h000066400000000000000000000030551207112532300176040ustar00rootroot00000000000000/** * FreeRDP: A Remote Desktop Protocol Client * DirectFB Client * * Copyright 2011 Marc-Andre Moreau * * 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. */ #ifndef __DFREERDP_H #define __DFREERDP_H #include #include #include #include #include #include #include #include #include typedef struct df_info dfInfo; struct df_context { rdpContext _p; dfInfo* dfi; rdpSettings* settings; }; typedef struct df_context dfContext; struct df_pointer { rdpPointer pointer; IDirectFBSurface* surface; uint32 xhot; uint32 yhot; }; typedef struct df_pointer dfPointer; struct df_info { int read_fds; DFBResult err; IDirectFB* dfb; DFBEvent event; HCLRCONV clrconv; DFBRectangle update_rect; DFBSurfaceDescription dsc; IDirectFBSurface* primary; IDirectFBSurface* surface; IDirectFBDisplayLayer* layer; IDirectFBEventBuffer* event_buffer; }; #endif /* __DFREERDP_H */ FreeRDP-1.0.2/client/Windows/000077500000000000000000000000001207112532300156455ustar00rootroot00000000000000FreeRDP-1.0.2/client/Windows/CMakeLists.txt000066400000000000000000000023051207112532300204050ustar00rootroot00000000000000# FreeRDP: A Remote Desktop Protocol Client # FreeRDP Windows cmake build script # # Copyright 2011 O.S. Systems Software Ltda. # Copyright 2011 Otavio Salvador # Copyright 2011 Marc-Andre Moreau # # 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. add_executable(wfreerdp WIN32 wf_gdi.c wf_gdi.h wf_event.c wf_event.h wf_graphics.c wf_graphics.h wfreerdp.c wfreerdp.h) target_link_libraries(wfreerdp freerdp-core) target_link_libraries(wfreerdp freerdp-gdi) target_link_libraries(wfreerdp freerdp-utils) target_link_libraries(wfreerdp freerdp-codec) target_link_libraries(wfreerdp freerdp-channels) install(TARGETS wfreerdp DESTINATION ${CMAKE_INSTALL_BINDIR}) FreeRDP-1.0.2/client/Windows/wf_event.c000066400000000000000000000126331207112532300176330ustar00rootroot00000000000000/** * FreeRDP: A Remote Desktop Protocol Client * Event Handling * * Copyright 2009-2011 Jay Sorg * Copyright 2010-2011 Vic Lee * Copyright 2010-2011 Marc-Andre Moreau * * 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. */ #include #include #include "wfreerdp.h" #include "wf_event.h" static HWND g_focus_hWnd; extern HCURSOR g_default_cursor; #define X_POS(lParam) (lParam & 0xffff) #define Y_POS(lParam) ((lParam >> 16) & 0xffff) LRESULT CALLBACK wf_ll_kbd_proc(int nCode, WPARAM wParam, LPARAM lParam) { DWORD flags; wfInfo* wfi; uint8 scanCode; rdpInput* input; uint16 kbdFlags; PKBDLLHOOKSTRUCT p; DEBUG_KBD("Low-level keyboard hook, hWnd %X nCode %X wParam %X\n", g_focus_hWnd, nCode, wParam); if (g_focus_hWnd && (nCode == HC_ACTION)) { switch (wParam) { case WM_KEYDOWN: case WM_SYSKEYDOWN: case WM_KEYUP: case WM_SYSKEYUP: wfi = (wfInfo*) GetWindowLongPtr(g_focus_hWnd, GWLP_USERDATA); p = (PKBDLLHOOKSTRUCT) lParam; scanCode = (uint8) p->scanCode; input = wfi->instance->input; flags = p->flags; kbdFlags = 0; DEBUG_KBD("keydown %d scanCode %04X flags %02X vkCode %02X\n", (wParam == WM_KEYDOWN), scanCode, flags, p->vkCode); if (wfi->fs_toggle && ((p->vkCode == VK_RETURN) || (p->vkCode == VK_CANCEL)) && (GetAsyncKeyState(VK_CONTROL) & 0x8000) && (GetAsyncKeyState(VK_MENU) & 0x8000)) /* could also use flags & LLKHF_ALTDOWN */ { if (wParam == WM_KEYDOWN) //wf_toggle_fullscreen(wfi); return 1; } if (scanCode == 0x45) /* NumLock-ish */ { if (flags & LLKHF_EXTENDED) { /* Windows sends NumLock as extended - rdp doesn't */ DEBUG_KBD("hack: NumLock (x45) should not be extended\n"); flags &= ~LLKHF_EXTENDED; } else { /* Windows sends Pause as if it was a RDP NumLock (handled above). * It must however be sent as a one-shot Ctrl+NumLock */ if (wParam == WM_KEYDOWN) { DEBUG_KBD("Pause, sent as Ctrl+NumLock\n"); input->KeyboardEvent(input, KBD_FLAGS_DOWN, 0x1D); /* Ctrl down */ input->KeyboardEvent(input, KBD_FLAGS_DOWN, 0x45); /* NumLock down */ input->KeyboardEvent(input, KBD_FLAGS_RELEASE, 0x1D); /* Ctrl up */ input->KeyboardEvent(input, KBD_FLAGS_RELEASE, 0x45); /* NumLock up */ } else { DEBUG_KBD("Pause up\n"); } return 1; } } if ((scanCode == 0x36) && (flags & LLKHF_EXTENDED)) { DEBUG_KBD("hack: right shift (x36) should not be extended\n"); flags &= ~LLKHF_EXTENDED; } kbdFlags |= (flags & LLKHF_UP) ? KBD_FLAGS_RELEASE : KBD_FLAGS_DOWN; kbdFlags |= (flags & LLKHF_EXTENDED) ? KBD_FLAGS_EXTENDED : 0; input->KeyboardEvent(input, kbdFlags, scanCode); if (p->vkCode == VK_CAPITAL) DEBUG_KBD("caps lock is processed on client side too to toggle caps lock indicator\n"); else return 1; break; } } return CallNextHookEx(NULL, nCode, wParam, lParam); } LRESULT CALLBACK wf_event_proc(HWND hWnd, UINT Msg, WPARAM wParam, LPARAM lParam) { HDC hdc; LONG ptr; wfInfo* wfi; int x, y, w, h; PAINTSTRUCT ps; rdpInput* input; boolean processed; processed = true; ptr = GetWindowLongPtr(hWnd, GWLP_USERDATA); wfi = (wfInfo*) ptr; if (wfi != NULL) { input = wfi->instance->input; switch (Msg) { case WM_PAINT: hdc = BeginPaint(hWnd, &ps); x = ps.rcPaint.left; y = ps.rcPaint.top; w = ps.rcPaint.right - ps.rcPaint.left + 1; h = ps.rcPaint.bottom - ps.rcPaint.top + 1; //printf("WM_PAINT: x:%d y:%d w:%d h:%d\n", x, y, w, h); BitBlt(hdc, x, y, w, h, wfi->primary->hdc, x, y, SRCCOPY); EndPaint(hWnd, &ps); break; case WM_LBUTTONDOWN: input->MouseEvent(input, PTR_FLAGS_DOWN | PTR_FLAGS_BUTTON1, X_POS(lParam), Y_POS(lParam)); break; case WM_LBUTTONUP: input->MouseEvent(input, PTR_FLAGS_BUTTON1, X_POS(lParam), Y_POS(lParam)); break; case WM_RBUTTONDOWN: input->MouseEvent(input, PTR_FLAGS_DOWN | PTR_FLAGS_BUTTON2, X_POS(lParam), Y_POS(lParam)); break; case WM_RBUTTONUP: input->MouseEvent(input, PTR_FLAGS_BUTTON2, X_POS(lParam), Y_POS(lParam)); break; case WM_MOUSEMOVE: input->MouseEvent(input, PTR_FLAGS_MOVE, X_POS(lParam), Y_POS(lParam)); break; case WM_SETCURSOR: SetCursor(wfi->cursor); break; default: processed = false; break; } } else { processed = false; } if (processed) return 0; switch (Msg) { case WM_DESTROY: PostQuitMessage(WM_QUIT); break; case WM_SETCURSOR: SetCursor(g_default_cursor); break; case WM_SETFOCUS: DEBUG_KBD("getting focus %X\n", hWnd); g_focus_hWnd = hWnd; break; case WM_KILLFOCUS: DEBUG_KBD("loosing focus %X\n", hWnd); if (g_focus_hWnd == hWnd) g_focus_hWnd = NULL; break; default: return DefWindowProc(hWnd, Msg, wParam, lParam); break; } return 0; } FreeRDP-1.0.2/client/Windows/wf_event.h000066400000000000000000000022321207112532300176320ustar00rootroot00000000000000/** * FreeRDP: A Remote Desktop Protocol Client * Event Handling * * Copyright 2009-2011 Jay Sorg * Copyright 2010-2011 Vic Lee * Copyright 2010-2011 Marc-Andre Moreau * * 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. */ #ifndef __WF_EVENT_H #define __WF_EVENT_H #include "wfreerdp.h" LRESULT CALLBACK wf_ll_kbd_proc(int nCode, WPARAM wParam, LPARAM lParam); LRESULT CALLBACK wf_event_proc(HWND hWnd, UINT Msg, WPARAM wParam, LPARAM lParam); #ifdef WITH_DEBUG_KBD #define DEBUG_KBD(fmt, ...) DEBUG_CLASS(KBD, fmt, ## __VA_ARGS__) #else #define DEBUG_KBD(fmt, ...) DEBUG_NULL(fmt, ## __VA_ARGS__) #endif #endif /* __WF_EVENT_H */ FreeRDP-1.0.2/client/Windows/wf_gdi.c000066400000000000000000000372551207112532300172640ustar00rootroot00000000000000/** * FreeRDP: A Remote Desktop Protocol Client * Windows GDI * * Copyright 2009-2011 Jay Sorg * Copyright 2010-2011 Vic Lee * Copyright 2010-2011 Marc-Andre Moreau * * 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. */ #include #include #include #include #include #include #include #include #include #include #include #include "wfreerdp.h" #include "wf_graphics.h" const uint8 wf_rop2_table[] = { R2_BLACK, /* 0 */ R2_NOTMERGEPEN, /* DPon */ R2_MASKNOTPEN, /* DPna */ R2_NOTCOPYPEN, /* Pn */ R2_MASKPENNOT, /* PDna */ R2_NOT, /* Dn */ R2_XORPEN, /* DPx */ R2_NOTMASKPEN, /* DPan */ R2_MASKPEN, /* DPa */ R2_NOTXORPEN, /* DPxn */ R2_NOP, /* D */ R2_MERGENOTPEN, /* DPno */ R2_COPYPEN, /* P */ R2_MERGEPENNOT, /* PDno */ R2_MERGEPEN, /* PDo */ R2_WHITE, /* 1 */ }; boolean wf_set_rop2(HDC hdc, int rop2) { if ((rop2 < 0x01) || (rop2 > 0x10)) { printf("Unsupported ROP2: %d\n", rop2); return false; } SetROP2(hdc, wf_rop2_table[rop2 - 1]); return true; } wfBitmap* wf_glyph_new(wfInfo* wfi, GLYPH_DATA* glyph) { wfBitmap* glyph_bmp; glyph_bmp = wf_image_new(wfi, glyph->cx, glyph->cy, 1, glyph->aj); return glyph_bmp; } void wf_glyph_free(wfBitmap* glyph) { wf_image_free(glyph); } uint8* wf_glyph_convert(wfInfo* wfi, int width, int height, uint8* data) { int indexx; int indexy; uint8* src; uint8* dst; uint8* cdata; int src_bytes_per_row; int dst_bytes_per_row; src_bytes_per_row = (width + 7) / 8; dst_bytes_per_row = src_bytes_per_row + (src_bytes_per_row % 2); cdata = (uint8 *) malloc(dst_bytes_per_row * height); src = data; for (indexy = 0; indexy < height; indexy++) { dst = cdata + indexy * dst_bytes_per_row; for (indexx = 0; indexx < dst_bytes_per_row; indexx++) { if (indexx < src_bytes_per_row) *dst++ = *src++; else *dst++ = 0; } } return cdata; } HBRUSH wf_create_brush(wfInfo * wfi, rdpBrush* brush, uint32 color, int bpp) { int i; HBRUSH br; LOGBRUSH lbr; uint8* cdata; uint8 ipattern[8]; HBITMAP pattern = NULL; lbr.lbStyle = brush->style; if (lbr.lbStyle == BS_DIBPATTERN || lbr.lbStyle == BS_DIBPATTERN8X8 || lbr.lbStyle == BS_DIBPATTERNPT) lbr.lbColor = DIB_RGB_COLORS; else lbr.lbColor = color; if (lbr.lbStyle == BS_PATTERN || lbr.lbStyle == BS_PATTERN8X8) { if (brush->bpp > 1) { pattern = wf_create_dib(wfi, 8, 8, bpp, brush->data, NULL); lbr.lbHatch = (ULONG_PTR) pattern; } else { for (i = 0; i != 8; i++) ipattern[7 - i] = brush->data[i]; cdata = wf_glyph_convert(wfi, 8, 8, ipattern); pattern = CreateBitmap(8, 8, 1, 1, cdata); lbr.lbHatch = (ULONG_PTR) pattern; free(cdata); } } else if (lbr.lbStyle == BS_HATCHED) { lbr.lbHatch = brush->hatch; } else { lbr.lbHatch = 0; } br = CreateBrushIndirect(&lbr); SetBrushOrgEx(wfi->drawing->hdc, brush->x, brush->y, NULL); if (pattern != NULL) DeleteObject(pattern); return br; } void wf_invalidate_region(wfInfo* wfi, int x, int y, int width, int height) { wfi->update_rect.left = x; wfi->update_rect.top = y; wfi->update_rect.right = x + width; wfi->update_rect.bottom = y + height; InvalidateRect(wfi->hwnd, &(wfi->update_rect), FALSE); gdi_InvalidateRegion(wfi->hdc, x, y, width, height); } void wf_toggle_fullscreen(wfInfo* wfi) { ShowWindow(wfi->hwnd, SW_HIDE); wfi->fullscreen = !wfi->fullscreen; SetForegroundWindow(wfi->hwnd); } void wf_gdi_palette_update(rdpContext* context, PALETTE_UPDATE* palette) { } void wf_set_null_clip_rgn(wfInfo* wfi) { SelectClipRgn(wfi->drawing->hdc, NULL); } void wf_set_clip_rgn(wfInfo* wfi, int x, int y, int width, int height) { HRGN clip; clip = CreateRectRgn(x, y, x + width, y + height); SelectClipRgn(wfi->drawing->hdc, clip); DeleteObject(clip); } void wf_gdi_set_bounds(rdpContext* context, rdpBounds* bounds) { HRGN hrgn; wfInfo* wfi = ((wfContext*) context)->wfi; if (bounds != NULL) { hrgn = CreateRectRgn(bounds->left, bounds->top, bounds->right + 1, bounds->bottom + 1); SelectClipRgn(wfi->drawing->hdc, hrgn); DeleteObject(hrgn); } else { SelectClipRgn(wfi->drawing->hdc, NULL); } } void wf_gdi_dstblt(rdpContext* context, DSTBLT_ORDER* dstblt) { wfInfo* wfi = ((wfContext*) context)->wfi; BitBlt(wfi->drawing->hdc, dstblt->nLeftRect, dstblt->nTopRect, dstblt->nWidth, dstblt->nHeight, NULL, 0, 0, gdi_rop3_code(dstblt->bRop)); wf_invalidate_region(wfi, dstblt->nLeftRect, dstblt->nTopRect, dstblt->nWidth, dstblt->nHeight); } void wf_gdi_patblt(rdpContext* context, PATBLT_ORDER* patblt) { HBRUSH brush; HBRUSH org_brush; int org_bkmode; uint32 fgcolor; uint32 bgcolor; COLORREF org_bkcolor; COLORREF org_textcolor; wfInfo* wfi = ((wfContext*) context)->wfi; fgcolor = freerdp_color_convert_bgr(patblt->foreColor, wfi->srcBpp, 32, wfi->clrconv); bgcolor = freerdp_color_convert_bgr(patblt->backColor, wfi->srcBpp, 32, wfi->clrconv); brush = wf_create_brush(wfi, &patblt->brush, fgcolor, wfi->srcBpp); org_bkmode = SetBkMode(wfi->drawing->hdc, OPAQUE); org_bkcolor = SetBkColor(wfi->drawing->hdc, bgcolor); org_textcolor = SetTextColor(wfi->drawing->hdc, fgcolor); org_brush = (HBRUSH)SelectObject(wfi->drawing->hdc, brush); PatBlt(wfi->drawing->hdc, patblt->nLeftRect, patblt->nTopRect, patblt->nWidth, patblt->nHeight, gdi_rop3_code(patblt->bRop)); SelectObject(wfi->drawing->hdc, org_brush); DeleteObject(brush); SetBkMode(wfi->drawing->hdc, org_bkmode); SetBkColor(wfi->drawing->hdc, org_bkcolor); SetTextColor(wfi->drawing->hdc, org_textcolor); if (wfi->drawing == wfi->primary) wf_invalidate_region(wfi, patblt->nLeftRect, patblt->nTopRect, patblt->nWidth, patblt->nHeight); } void wf_gdi_scrblt(rdpContext* context, SCRBLT_ORDER* scrblt) { wfInfo* wfi = ((wfContext*) context)->wfi; BitBlt(wfi->drawing->hdc, scrblt->nLeftRect, scrblt->nTopRect, scrblt->nWidth, scrblt->nHeight, wfi->primary->hdc, scrblt->nXSrc, scrblt->nYSrc, gdi_rop3_code(scrblt->bRop)); wf_invalidate_region(wfi, scrblt->nLeftRect, scrblt->nTopRect, scrblt->nWidth, scrblt->nHeight); } void wf_gdi_opaque_rect(rdpContext* context, OPAQUE_RECT_ORDER* opaque_rect) { RECT rect; HBRUSH brush; uint32 brush_color; wfInfo* wfi = ((wfContext*) context)->wfi; brush_color = freerdp_color_convert_var_bgr(opaque_rect->color, wfi->srcBpp, 24, wfi->clrconv); rect.left = opaque_rect->nLeftRect; rect.top = opaque_rect->nTopRect; rect.right = opaque_rect->nLeftRect + opaque_rect->nWidth; rect.bottom = opaque_rect->nTopRect + opaque_rect->nHeight; brush = CreateSolidBrush(brush_color); FillRect(wfi->drawing->hdc, &rect, brush); DeleteObject(brush); if (wfi->drawing == wfi->primary) wf_invalidate_region(wfi, rect.left, rect.top, rect.right - rect.left + 1, rect.bottom - rect.top + 1); } void wf_gdi_multi_opaque_rect(rdpContext* context, MULTI_OPAQUE_RECT_ORDER* multi_opaque_rect) { int i; RECT rect; HBRUSH brush; uint32 brush_color; DELTA_RECT* rectangle; wfInfo* wfi = ((wfContext*) context)->wfi; for (i = 1; i < (int) multi_opaque_rect->numRectangles + 1; i++) { rectangle = &multi_opaque_rect->rectangles[i]; brush_color = freerdp_color_convert_var_bgr(multi_opaque_rect->color, wfi->srcBpp, 32, wfi->clrconv); rect.left = rectangle->left; rect.top = rectangle->top; rect.right = rectangle->left + rectangle->width; rect.bottom = rectangle->top + rectangle->height; brush = CreateSolidBrush(brush_color); brush = CreateSolidBrush(brush_color); FillRect(wfi->drawing->hdc, &rect, brush); if (wfi->drawing == wfi->primary) wf_invalidate_region(wfi, rect.left, rect.top, rect.right - rect.left + 1, rect.bottom - rect.top + 1); DeleteObject(brush); } } void wf_gdi_line_to(rdpContext* context, LINE_TO_ORDER* line_to) { HPEN pen; HPEN org_pen; int x, y, w, h; uint32 pen_color; wfInfo* wfi = ((wfContext*) context)->wfi; pen_color = freerdp_color_convert_bgr(line_to->penColor, wfi->srcBpp, wfi->dstBpp, wfi->clrconv); pen = CreatePen(line_to->penStyle, line_to->penWidth, pen_color); wf_set_rop2(wfi->drawing->hdc, line_to->bRop2); org_pen = (HPEN) SelectObject(wfi->drawing->hdc, pen); MoveToEx(wfi->drawing->hdc, line_to->nXStart, line_to->nYStart, NULL); LineTo(wfi->drawing->hdc, line_to->nXEnd, line_to->nYEnd); x = (line_to->nXStart < line_to->nXEnd) ? line_to->nXStart : line_to->nXEnd; y = (line_to->nYStart < line_to->nYEnd) ? line_to->nYStart : line_to->nYEnd; w = (line_to->nXStart < line_to->nXEnd) ? (line_to->nXEnd - line_to->nXStart) : (line_to->nXStart - line_to->nXEnd); h = (line_to->nYStart < line_to->nYEnd) ? (line_to->nYEnd - line_to->nYStart) : (line_to->nYStart - line_to->nYEnd); if (wfi->drawing == wfi->primary) wf_invalidate_region(wfi, x, y, w, h); SelectObject(wfi->drawing->hdc, org_pen); DeleteObject(pen); } void wf_gdi_polyline(rdpContext* context, POLYLINE_ORDER* polyline) { int i; POINT* pts; int org_rop2; HPEN hpen; HPEN org_hpen; uint32 pen_color; wfInfo* wfi = ((wfContext*) context)->wfi; pen_color = freerdp_color_convert_bgr(polyline->penColor, wfi->srcBpp, wfi->dstBpp, wfi->clrconv); hpen = CreatePen(0, 1, pen_color); org_rop2 = wf_set_rop2(wfi->drawing->hdc, polyline->bRop2); org_hpen = (HPEN) SelectObject(wfi->drawing->hdc, hpen); if (polyline->numPoints > 0) { pts = (POINT*) xmalloc(sizeof(POINT) * polyline->numPoints); for (i = 0; i < (int) polyline->numPoints; i++) { pts[i].x = polyline->points[i].x; pts[i].y = polyline->points[i].y; if (wfi->drawing == wfi->primary) wf_invalidate_region(wfi, pts[i].x, pts[i].y, pts[i].x + 1, pts[i].y + 1); } Polyline(wfi->drawing->hdc, pts, polyline->numPoints); xfree(pts); } SelectObject(wfi->drawing->hdc, org_hpen); wf_set_rop2(wfi->drawing->hdc, org_rop2); DeleteObject(hpen); } void wf_gdi_memblt(rdpContext* context, MEMBLT_ORDER* memblt) { wfBitmap* bitmap; wfInfo* wfi = ((wfContext*) context)->wfi; bitmap = (wfBitmap*) memblt->bitmap; BitBlt(wfi->drawing->hdc, memblt->nLeftRect, memblt->nTopRect, memblt->nWidth, memblt->nHeight, bitmap->hdc, memblt->nXSrc, memblt->nYSrc, gdi_rop3_code(memblt->bRop)); if (wfi->drawing == wfi->primary) wf_invalidate_region(wfi, memblt->nLeftRect, memblt->nTopRect, memblt->nWidth, memblt->nHeight); } void wf_gdi_surface_bits(rdpContext* context, SURFACE_BITS_COMMAND* surface_bits_command) { int i, j; int tx, ty; char* tile_bitmap; RFX_MESSAGE* message; wfInfo* wfi = ((wfContext*) context)->wfi; RFX_CONTEXT* rfx_context = (RFX_CONTEXT*) wfi->rfx_context; NSC_CONTEXT* nsc_context = (NSC_CONTEXT*) wfi->nsc_context; tile_bitmap = (char*) xzalloc(32); if (surface_bits_command->codecID == CODEC_ID_REMOTEFX) { message = rfx_process_message(rfx_context, surface_bits_command->bitmapData, surface_bits_command->bitmapDataLength); /* blit each tile */ for (i = 0; i < message->num_tiles; i++) { tx = message->tiles[i]->x + surface_bits_command->destLeft; ty = message->tiles[i]->y + surface_bits_command->destTop; freerdp_image_convert(message->tiles[i]->data, wfi->tile->pdata, 64, 64, 32, 32, wfi->clrconv); for (j = 0; j < message->num_rects; j++) { wf_set_clip_rgn(wfi, surface_bits_command->destLeft + message->rects[j].x, surface_bits_command->destTop + message->rects[j].y, message->rects[j].width, message->rects[j].height); BitBlt(wfi->primary->hdc, tx, ty, 64, 64, wfi->tile->hdc, 0, 0, SRCCOPY); } } wf_set_null_clip_rgn(wfi); /* invalidate regions */ for (i = 0; i < message->num_rects; i++) { tx = surface_bits_command->destLeft + message->rects[i].x; ty = surface_bits_command->destTop + message->rects[i].y; wf_invalidate_region(wfi, tx, ty, message->rects[i].width, message->rects[i].height); } rfx_message_free(rfx_context, message); } else if (surface_bits_command->codecID == CODEC_ID_NSCODEC) { nsc_context->width = surface_bits_command->width; nsc_context->height = surface_bits_command->height; nsc_process_message(nsc_context, surface_bits_command->bitmapData, surface_bits_command->bitmapDataLength); wfi->image->_bitmap.width = surface_bits_command->width; wfi->image->_bitmap.height = surface_bits_command->height; wfi->image->_bitmap.bpp = surface_bits_command->bpp; wfi->image->_bitmap.data = (uint8*) xrealloc(wfi->image->_bitmap.data, wfi->image->_bitmap.width * wfi->image->_bitmap.height * 4); freerdp_image_flip(nsc_context->bmpdata, wfi->image->_bitmap.data, wfi->image->_bitmap.width, wfi->image->_bitmap.height, 32); BitBlt(wfi->primary->hdc, surface_bits_command->destLeft, surface_bits_command->destTop, surface_bits_command->width, surface_bits_command->height, wfi->image->hdc, 0, 0, GDI_SRCCOPY); nsc_context_destroy(nsc_context); } else if (surface_bits_command->codecID == CODEC_ID_NONE) { wfi->image->_bitmap.width = surface_bits_command->width; wfi->image->_bitmap.height = surface_bits_command->height; wfi->image->_bitmap.bpp = surface_bits_command->bpp; wfi->image->_bitmap.data = (uint8*) xrealloc(wfi->image->_bitmap.data, wfi->image->_bitmap.width * wfi->image->_bitmap.height * 4); if ((surface_bits_command->bpp != 32) || (wfi->clrconv->alpha == true)) { uint8* temp_image; freerdp_image_convert(surface_bits_command->bitmapData, wfi->image->_bitmap.data, wfi->image->_bitmap.width, wfi->image->_bitmap.height, wfi->image->_bitmap.bpp, 32, wfi->clrconv); surface_bits_command->bpp = 32; surface_bits_command->bitmapData = wfi->image->_bitmap.data; temp_image = (uint8*) xmalloc(wfi->image->_bitmap.width * wfi->image->_bitmap.height * 4); freerdp_image_flip(wfi->image->_bitmap.data, temp_image, wfi->image->_bitmap.width, wfi->image->_bitmap.height, 32); xfree(wfi->image->_bitmap.data); wfi->image->_bitmap.data = temp_image; } else { freerdp_image_flip(surface_bits_command->bitmapData, wfi->image->_bitmap.data, wfi->image->_bitmap.width, wfi->image->_bitmap.height, 32); } BitBlt(wfi->primary->hdc, surface_bits_command->destLeft, surface_bits_command->destTop, surface_bits_command->width, surface_bits_command->height, wfi->image->hdc, 0, 0, SRCCOPY); } else { printf("Unsupported codecID %d\n", surface_bits_command->codecID); } if (tile_bitmap != NULL) xfree(tile_bitmap); } void wf_gdi_register_update_callbacks(rdpUpdate* update) { rdpPrimaryUpdate* primary = update->primary; update->Palette = wf_gdi_palette_update; update->SetBounds = wf_gdi_set_bounds; primary->DstBlt = wf_gdi_dstblt; primary->PatBlt = wf_gdi_patblt; primary->ScrBlt = wf_gdi_scrblt; primary->OpaqueRect = wf_gdi_opaque_rect; primary->DrawNineGrid = NULL; primary->MultiDstBlt = NULL; primary->MultiPatBlt = NULL; primary->MultiScrBlt = NULL; primary->MultiOpaqueRect = wf_gdi_multi_opaque_rect; primary->MultiDrawNineGrid = NULL; primary->LineTo = wf_gdi_line_to; primary->Polyline = wf_gdi_polyline; primary->MemBlt = wf_gdi_memblt; primary->Mem3Blt = NULL; primary->SaveBitmap = NULL; primary->GlyphIndex = NULL; primary->FastIndex = NULL; primary->FastGlyph = NULL; primary->PolygonSC = NULL; primary->PolygonCB = NULL; primary->EllipseSC = NULL; primary->EllipseCB = NULL; update->SurfaceBits = wf_gdi_surface_bits; } FreeRDP-1.0.2/client/Windows/wf_gdi.h000066400000000000000000000021711207112532300172560ustar00rootroot00000000000000/** * FreeRDP: A Remote Desktop Protocol Client * Windows GDI * * Copyright 2009-2011 Jay Sorg * Copyright 2010-2011 Vic Lee * Copyright 2010-2011 Marc-Andre Moreau * * 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. */ #ifndef __WF_GDI_H #define __WF_GDI_H #include "wfreerdp.h" void wf_invalidate_region(wfInfo* wfi, int x, int y, int width, int height); wfBitmap* wf_image_new(wfInfo* wfi, int width, int height, int bpp, uint8* data); void wf_image_free(wfBitmap* image); void wf_toggle_fullscreen(wfInfo* wfi); void wf_gdi_register_update_callbacks(rdpUpdate* update); #endif /* __WF_GDI_H */ FreeRDP-1.0.2/client/Windows/wf_graphics.c000066400000000000000000000135261207112532300203140ustar00rootroot00000000000000/** * FreeRDP: A Remote Desktop Protocol Client * Windows Graphical Objects * * Copyright 2010-2011 Marc-Andre Moreau * * 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. */ #include #include #include "wf_gdi.h" #include "wf_graphics.h" HBITMAP wf_create_dib(wfInfo* wfi, int width, int height, int bpp, uint8* data, uint8** pdata) { HDC hdc; int negHeight; HBITMAP bitmap; BITMAPINFO bmi; uint8* cdata = NULL; /** * See: http://msdn.microsoft.com/en-us/library/dd183376 * if biHeight is positive, the bitmap is bottom-up * if biHeight is negative, the bitmap is top-down * Since we get top-down bitmaps, let's keep it that way */ negHeight = (height < 0) ? height : height * (-1); hdc = GetDC(NULL); bmi.bmiHeader.biSize = sizeof(BITMAPINFO); bmi.bmiHeader.biWidth = width; bmi.bmiHeader.biHeight = negHeight; bmi.bmiHeader.biPlanes = 1; bmi.bmiHeader.biBitCount = bpp; bmi.bmiHeader.biCompression = BI_RGB; bitmap = CreateDIBSection(hdc, &bmi, DIB_RGB_COLORS, (void**) &cdata, NULL, 0); if (data != NULL) freerdp_image_convert(data, cdata, width, height, bpp, bpp, wfi->clrconv); if (pdata != NULL) *pdata = cdata; ReleaseDC(NULL, hdc); GdiFlush(); return bitmap; } wfBitmap* wf_image_new(wfInfo* wfi, int width, int height, int bpp, uint8* data) { HDC hdc; wfBitmap* image; hdc = GetDC(NULL); image = (wfBitmap*) malloc(sizeof(wfBitmap)); image->hdc = CreateCompatibleDC(hdc); if (data == NULL) image->bitmap = CreateCompatibleBitmap(hdc, width, height); else image->bitmap = wf_create_dib(wfi, width, height, bpp, data, &(image->pdata)); image->org_bitmap = (HBITMAP) SelectObject(image->hdc, image->bitmap); ReleaseDC(NULL, hdc); return image; } wfBitmap* wf_bitmap_new(wfInfo* wfi, int width, int height, int bpp, uint8* data) { HDC hdc; wfBitmap* bitmap; hdc = GetDC(NULL); bitmap = (wfBitmap*) malloc(sizeof(wfBitmap)); bitmap->hdc = CreateCompatibleDC(hdc); bitmap->bitmap = wf_create_dib(wfi, width, height, bpp, data, &(bitmap->pdata)); bitmap->org_bitmap = (HBITMAP) SelectObject(bitmap->hdc, bitmap->bitmap); ReleaseDC(NULL, hdc); return bitmap; } void wf_image_free(wfBitmap* image) { if (image != 0) { SelectObject(image->hdc, image->org_bitmap); DeleteObject(image->bitmap); DeleteDC(image->hdc); free(image); } } /* Bitmap Class */ void wf_Bitmap_New(rdpContext* context, rdpBitmap* bitmap) { HDC hdc; wfBitmap* wf_bitmap = (wfBitmap*) bitmap; wfInfo* wfi = ((wfContext*) context)->wfi; wf_bitmap = (wfBitmap*) bitmap; hdc = GetDC(NULL); wf_bitmap->hdc = CreateCompatibleDC(hdc); if (bitmap->data == NULL) wf_bitmap->bitmap = CreateCompatibleBitmap(hdc, bitmap->width, bitmap->height); else wf_bitmap->bitmap = wf_create_dib(wfi, bitmap->width, bitmap->height, bitmap->bpp, bitmap->data, NULL); wf_bitmap->org_bitmap = (HBITMAP) SelectObject(wf_bitmap->hdc, wf_bitmap->bitmap); ReleaseDC(NULL, hdc); } void wf_Bitmap_Free(rdpContext* context, rdpBitmap* bitmap) { wfBitmap* wf_bitmap = (wfBitmap*) bitmap; if (wf_bitmap != 0) { SelectObject(wf_bitmap->hdc, wf_bitmap->org_bitmap); DeleteObject(wf_bitmap->bitmap); DeleteDC(wf_bitmap->hdc); } } void wf_Bitmap_Paint(rdpContext* context, rdpBitmap* bitmap) { int width, height; wfBitmap* wf_bitmap = (wfBitmap*) bitmap; wfInfo* wfi = ((wfContext*) context)->wfi; width = bitmap->right - bitmap->left + 1; height = bitmap->bottom - bitmap->top + 1; BitBlt(wfi->primary->hdc, bitmap->left, bitmap->top, width, height, wf_bitmap->hdc, 0, 0, SRCCOPY); wf_invalidate_region(wfi, bitmap->left, bitmap->top, width, height); } void wf_Bitmap_Decompress(rdpContext* context, rdpBitmap* bitmap, uint8* data, int width, int height, int bpp, int length, boolean compressed) { uint16 size; size = width * height * (bpp / 8); if (bitmap->data == NULL) bitmap->data = (uint8*) xmalloc(size); else bitmap->data = (uint8*) xrealloc(bitmap->data, size); if (compressed) { boolean status; status = bitmap_decompress(data, bitmap->data, width, height, length, bpp, bpp); if (status != true) { printf("Bitmap Decompression Failed\n"); } } else { freerdp_image_flip(data, bitmap->data, width, height, bpp); } bitmap->compressed = false; bitmap->length = size; bitmap->bpp = bpp; } void wf_Bitmap_SetSurface(rdpContext* context, rdpBitmap* bitmap, boolean primary) { wfInfo* wfi = ((wfContext*) context)->wfi; if (primary) wfi->drawing = wfi->primary; else wfi->drawing = (wfBitmap*) bitmap; } /* Pointer Class */ void wf_Pointer_New(rdpContext* context, rdpPointer* pointer) { } void wf_Pointer_Free(rdpContext* context, rdpPointer* pointer) { } void wf_Pointer_Set(rdpContext* context, rdpPointer* pointer) { } /* Graphics Module */ void wf_register_graphics(rdpGraphics* graphics) { rdpBitmap bitmap; rdpPointer pointer; memset(&bitmap, 0, sizeof(rdpBitmap)); bitmap.size = sizeof(wfBitmap); bitmap.New = wf_Bitmap_New; bitmap.Free = wf_Bitmap_Free; bitmap.Paint = wf_Bitmap_Paint; bitmap.Decompress = wf_Bitmap_Decompress; bitmap.SetSurface = wf_Bitmap_SetSurface; memset(&pointer, 0, sizeof(rdpPointer)); pointer.size = sizeof(wfPointer); pointer.New = wf_Pointer_New; pointer.Free = wf_Pointer_Free; pointer.Set = wf_Pointer_Set; graphics_register_bitmap(graphics, &bitmap); graphics_register_pointer(graphics, &pointer); } FreeRDP-1.0.2/client/Windows/wf_graphics.h000066400000000000000000000022111207112532300203060ustar00rootroot00000000000000/** * FreeRDP: A Remote Desktop Protocol Client * Windows Graphical Objects * * Copyright 2010-2011 Marc-Andre Moreau * * 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. */ #ifndef __WF_GRAPHICS_H #define __WF_GRAPHICS_H #include "wfreerdp.h" HBITMAP wf_create_dib(wfInfo* wfi, int width, int height, int bpp, uint8* data, uint8** pdata); wfBitmap* wf_image_new(wfInfo* wfi, int width, int height, int bpp, uint8* data); wfBitmap* wf_bitmap_new(wfInfo* wfi, int width, int height, int bpp, uint8* data); void wf_image_free(wfBitmap* image); void wf_register_graphics(rdpGraphics* graphics); #endif /* WF_GRAPHICS */ FreeRDP-1.0.2/client/Windows/wfreerdp.c000066400000000000000000000405151207112532300176340ustar00rootroot00000000000000/** * FreeRDP: A Remote Desktop Protocol Client * Windows Client * * Copyright 2009-2011 Jay Sorg * Copyright 2010-2011 Vic Lee * Copyright 2010-2011 Marc-Andre Moreau * * 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. */ #include #include #include #include #include #ifdef _MSC_VER #include #endif #include #include #include #include #include #include #include "wf_gdi.h" #include "wf_graphics.h" #include "wfreerdp.h" struct _thread_data { freerdp* instance; }; typedef struct _thread_data thread_data; HANDLE g_done_event; HINSTANCE g_hInstance; HCURSOR g_default_cursor; volatile int g_thread_count = 0; LPCTSTR g_wnd_class_name = L"wfreerdp"; void wf_context_new(freerdp* instance, rdpContext* context) { context->channels = freerdp_channels_new(); } void wf_context_free(freerdp* instance, rdpContext* context) { } int wf_create_console(void) { if (!AllocConsole()) return 1; freopen("CONOUT$", "w", stdout); printf("Debug console created.\n"); return 0; } void wf_sw_begin_paint(rdpContext* context) { rdpGdi* gdi = context->gdi; gdi->primary->hdc->hwnd->invalid->null = 1; gdi->primary->hdc->hwnd->ninvalid = 0; } void wf_sw_end_paint(rdpContext* context) { int i; rdpGdi* gdi; wfInfo* wfi; sint32 x, y; uint32 w, h; int ninvalid; RECT update_rect; HGDI_RGN cinvalid; gdi = context->gdi; wfi = ((wfContext*) context)->wfi; if (gdi->primary->hdc->hwnd->ninvalid < 1) return; ninvalid = gdi->primary->hdc->hwnd->ninvalid; cinvalid = gdi->primary->hdc->hwnd->cinvalid; for (i = 0; i < ninvalid; i++) { x = cinvalid[i].x; y = cinvalid[i].y; w = cinvalid[i].w; h = cinvalid[i].h; update_rect.left = x; update_rect.top = y; update_rect.right = x + w - 1; update_rect.bottom = y + h - 1; InvalidateRect(wfi->hwnd, &update_rect, FALSE); } } void wf_hw_begin_paint(rdpContext* context) { wfInfo* wfi = ((wfContext*) context)->wfi; wfi->hdc->hwnd->invalid->null = 1; wfi->hdc->hwnd->ninvalid = 0; } void wf_hw_end_paint(rdpContext* context) { } boolean wf_pre_connect(freerdp* instance) { int i1; wfInfo* wfi; wfContext* context; rdpSettings* settings; wfi = (wfInfo*) xzalloc(sizeof(wfInfo)); context = (wfContext*) instance->context; wfi->instance = instance; context->wfi = wfi; settings = instance->settings; settings->os_major_type = OSMAJORTYPE_WINDOWS; settings->os_minor_type = OSMINORTYPE_WINDOWS_NT; settings->order_support[NEG_DSTBLT_INDEX] = true; settings->order_support[NEG_PATBLT_INDEX] = true; settings->order_support[NEG_SCRBLT_INDEX] = true; settings->order_support[NEG_OPAQUE_RECT_INDEX] = true; settings->order_support[NEG_DRAWNINEGRID_INDEX] = false; settings->order_support[NEG_MULTIDSTBLT_INDEX] = false; settings->order_support[NEG_MULTIPATBLT_INDEX] = false; settings->order_support[NEG_MULTISCRBLT_INDEX] = false; settings->order_support[NEG_MULTIOPAQUERECT_INDEX] = true; settings->order_support[NEG_MULTI_DRAWNINEGRID_INDEX] = false; settings->order_support[NEG_LINETO_INDEX] = true; settings->order_support[NEG_POLYLINE_INDEX] = true; settings->order_support[NEG_MEMBLT_INDEX] = true; settings->order_support[NEG_MEM3BLT_INDEX] = false; settings->order_support[NEG_SAVEBITMAP_INDEX] = false; settings->order_support[NEG_GLYPH_INDEX_INDEX] = false; settings->order_support[NEG_FAST_INDEX_INDEX] = false; settings->order_support[NEG_FAST_GLYPH_INDEX] = false; settings->order_support[NEG_POLYGON_SC_INDEX] = false; settings->order_support[NEG_POLYGON_CB_INDEX] = false; settings->order_support[NEG_ELLIPSE_SC_INDEX] = false; settings->order_support[NEG_ELLIPSE_CB_INDEX] = false; settings->glyph_cache = false; wfi->cursor = g_default_cursor; wfi->fullscreen = settings->fullscreen; wfi->fs_toggle = wfi->fullscreen; wfi->sw_gdi = settings->sw_gdi; wfi->clrconv = (HCLRCONV) xzalloc(sizeof(CLRCONV)); wfi->clrconv->palette = NULL; wfi->clrconv->alpha = 0; instance->context->cache = cache_new(settings); if (wfi->percentscreen > 0) { i1 = (GetSystemMetrics(SM_CXSCREEN) * wfi->percentscreen) / 100; settings->width = i1; i1 = (GetSystemMetrics(SM_CYSCREEN) * wfi->percentscreen) / 100; settings->height = i1; } if (wfi->fs_toggle) { settings->width = GetSystemMetrics(SM_CXSCREEN); settings->height = GetSystemMetrics(SM_CYSCREEN); } i1 = settings->width; i1 = (i1 + 3) & (~3); settings->width = i1; if ((settings->width < 64) || (settings->height < 64) || (settings->width > 4096) || (settings->height > 4096)) { printf("wf_pre_connect: invalid dimensions %d %d\n", settings->width, settings->height); return 1; } settings->kbd_layout = (int) GetKeyboardLayout(0) & 0x0000FFFF; freerdp_channels_pre_connect(instance->context->channels, instance); return true; } void cpuid(unsigned info, unsigned *eax, unsigned *ebx, unsigned *ecx, unsigned *edx) { #if defined(__GNUC__) #if defined(__i386__) || defined(__x86_64__) *eax = info; __asm volatile ("mov %%ebx, %%edi;" /* 32bit PIC: don't clobber ebx */ "cpuid;" "mov %%ebx, %%esi;" "mov %%edi, %%ebx;" :"+a" (*eax), "=S" (*ebx), "=c" (*ecx), "=d" (*edx) : :"edi"); #endif #elif defined(_MSC_VER) int a[4]; __cpuid(a, info); *eax = a[0]; *ebx = a[1]; *ecx = a[2]; *edx = a[3]; #endif } uint32 wfi_detect_cpu() { uint32 cpu_opt = 0; unsigned int eax, ebx, ecx, edx = 0; cpuid(1, &eax, &ebx, &ecx, &edx); if (edx & (1<<26)) { cpu_opt |= CPU_SSE2; } return cpu_opt; } boolean wf_post_connect(freerdp* instance) { rdpGdi* gdi; wfInfo* wfi; rdpCache* cache; wfContext* context; int width, height; wchar_t win_title[64]; rdpSettings* settings; settings = instance->settings; context = (wfContext*) instance->context; cache = instance->context->cache; wfi = context->wfi; wfi->dstBpp = 32; width = settings->width; height = settings->height; if (wfi->sw_gdi) { gdi_init(instance, CLRCONV_ALPHA | CLRCONV_INVERT | CLRBUF_32BPP, NULL); gdi = instance->context->gdi; wfi->hdc = gdi->primary->hdc; wfi->primary = wf_image_new(wfi, width, height, wfi->dstBpp, gdi->primary_buffer); rfx_context_set_cpu_opt(gdi->rfx_context, wfi_detect_cpu()); } else { wf_gdi_register_update_callbacks(instance->update); wfi->srcBpp = instance->settings->color_depth; wfi->primary = wf_image_new(wfi, width, height, wfi->dstBpp, NULL); wfi->hdc = gdi_GetDC(); wfi->hdc->bitsPerPixel = wfi->dstBpp; wfi->hdc->bytesPerPixel = wfi->dstBpp / 8; wfi->hdc->alpha = wfi->clrconv->alpha; wfi->hdc->invert = wfi->clrconv->invert; wfi->hdc->hwnd = (HGDI_WND) malloc(sizeof(GDI_WND)); wfi->hdc->hwnd->invalid = gdi_CreateRectRgn(0, 0, 0, 0); wfi->hdc->hwnd->invalid->null = 1; wfi->hdc->hwnd->count = 32; wfi->hdc->hwnd->cinvalid = (HGDI_RGN) malloc(sizeof(GDI_RGN) * wfi->hdc->hwnd->count); wfi->hdc->hwnd->ninvalid = 0; wfi->image = wf_bitmap_new(wfi, 64, 64, 32, NULL); wfi->image->_bitmap.data = NULL; if (settings->rfx_codec) { wfi->tile = wf_bitmap_new(wfi, 64, 64, 32, NULL); wfi->rfx_context = rfx_context_new(); rfx_context_set_cpu_opt(wfi->rfx_context, wfi_detect_cpu()); } if (settings->ns_codec) wfi->nsc_context = nsc_context_new(); } if (settings->window_title != NULL) _snwprintf(win_title, sizeof(win_title), L"%S", settings->window_title); else if (settings->port == 3389) _snwprintf(win_title, sizeof(win_title) / sizeof(win_title[0]), L"FreeRDP: %S", settings->hostname); else _snwprintf(win_title, sizeof(win_title) / sizeof(win_title[0]), L"FreeRDP: %S:%d", settings->hostname, settings->port); if (wfi->hwnd == 0) { wfi->hwnd = CreateWindowEx((DWORD) NULL, g_wnd_class_name, win_title, 0, 0, 0, 0, 0, NULL, NULL, g_hInstance, NULL); SetWindowLongPtr(wfi->hwnd, GWLP_USERDATA, (LONG_PTR) wfi); } if (wfi->fullscreen) { SetWindowLongPtr(wfi->hwnd, GWL_STYLE, WS_POPUP); SetWindowPos(wfi->hwnd, HWND_TOP, 0, 0, width, height, SWP_FRAMECHANGED); } else { POINT diff; RECT rc_client, rc_wnd; SetWindowLongPtr(wfi->hwnd, GWL_STYLE, WS_CAPTION | WS_OVERLAPPED | WS_SYSMENU | WS_MINIMIZEBOX); /* Now resize to get full canvas size and room for caption and borders */ SetWindowPos(wfi->hwnd, HWND_TOP, 10, 10, width, height, SWP_FRAMECHANGED); GetClientRect(wfi->hwnd, &rc_client); GetWindowRect(wfi->hwnd, &rc_wnd); diff.x = (rc_wnd.right - rc_wnd.left) - rc_client.right; diff.y = (rc_wnd.bottom - rc_wnd.top) - rc_client.bottom; SetWindowPos(wfi->hwnd, HWND_TOP, -1, -1, width + diff.x, height + diff.y, SWP_NOMOVE | SWP_FRAMECHANGED); } BitBlt(wfi->primary->hdc, 0, 0, width, height, NULL, 0, 0, BLACKNESS); wfi->drawing = wfi->primary; ShowWindow(wfi->hwnd, SW_SHOWNORMAL); UpdateWindow(wfi->hwnd); if (wfi->sw_gdi) { instance->update->BeginPaint = wf_sw_begin_paint; instance->update->EndPaint = wf_sw_end_paint; } else { instance->update->BeginPaint = wf_hw_begin_paint; instance->update->EndPaint = wf_hw_end_paint; } pointer_cache_register_callbacks(instance->update); if (wfi->sw_gdi != true) { brush_cache_register_callbacks(instance->update); bitmap_cache_register_callbacks(instance->update); offscreen_cache_register_callbacks(instance->update); } wf_register_graphics(instance->context->graphics); freerdp_channels_post_connect(instance->context->channels, instance); return true; } boolean wf_verify_certificate(freerdp* instance, char* subject, char* issuer, char* fingerprint) { return true; } int wf_receive_channel_data(freerdp* instance, int channelId, uint8* data, int size, int flags, int total_size) { return freerdp_channels_data(instance, channelId, data, size, flags, total_size); } void wf_process_channel_event(rdpChannels* channels, freerdp* instance) { RDP_EVENT* event; event = freerdp_channels_pop_event(channels); if (event) freerdp_event_free(event); } boolean wf_get_fds(freerdp* instance, void** rfds, int* rcount, void** wfds, int* wcount) { return true; } boolean wf_check_fds(freerdp* instance) { return true; } int wf_process_plugin_args(rdpSettings* settings, const char* name, RDP_PLUGIN_DATA* plugin_data, void* user_data) { rdpChannels* channels = (rdpChannels*) user_data; printf("loading plugin %s\n", name); freerdp_channels_load_plugin(channels, settings, name, plugin_data); return 1; } int wf_process_client_args(rdpSettings* settings, const char* opt, const char* val, void* user_data) { return 0; } int wfreerdp_run(freerdp* instance) { MSG msg; int index; int rcount; int wcount; BOOL msg_ret; int quit_msg; void* rfds[32]; void* wfds[32]; int fds_count; HANDLE fds[64]; rdpChannels* channels; memset(rfds, 0, sizeof(rfds)); memset(wfds, 0, sizeof(wfds)); if (freerdp_connect(instance) != true) return 0; channels = instance->context->channels; while (1) { rcount = 0; wcount = 0; if (freerdp_get_fds(instance, rfds, &rcount, wfds, &wcount) != true) { printf("Failed to get FreeRDP file descriptor\n"); break; } if (wf_get_fds(instance, rfds, &rcount, wfds, &wcount) != true) { printf("Failed to get wfreerdp file descriptor\n"); break; } if (freerdp_channels_get_fds(channels, instance, rfds, &rcount, wfds, &wcount) != true) { printf("Failed to get channel manager file descriptor\n"); break; } fds_count = 0; /* setup read fds */ for (index = 0; index < rcount; index++) { fds[fds_count++] = rfds[index]; } /* setup write fds */ for (index = 0; index < wcount; index++) { fds[fds_count++] = wfds[index]; } /* exit if nothing to do */ if (fds_count == 0) { printf("wfreerdp_run: fds_count is zero\n"); break; } /* do the wait */ if (MsgWaitForMultipleObjects(fds_count, fds, FALSE, 1, QS_ALLINPUT) == WAIT_FAILED) { printf("wfreerdp_run: WaitForMultipleObjects failed: 0x%04X\n", GetLastError()); break; } if (freerdp_check_fds(instance) != true) { printf("Failed to check FreeRDP file descriptor\n"); break; } if (wf_check_fds(instance) != true) { printf("Failed to check wfreerdp file descriptor\n"); break; } if (freerdp_channels_check_fds(channels, instance) != true) { printf("Failed to check channel manager file descriptor\n"); break; } wf_process_channel_event(channels, instance); quit_msg = FALSE; while (PeekMessage(&msg, NULL, 0, 0, PM_NOREMOVE)) { msg_ret = GetMessage(&msg, NULL, 0, 0); if (msg_ret == 0 || msg_ret == -1) { quit_msg = TRUE; break; } TranslateMessage(&msg); DispatchMessage(&msg); } if (quit_msg) break; } /* cleanup */ freerdp_channels_free(channels); freerdp_free(instance); return 0; } static DWORD WINAPI thread_func(LPVOID lpParam) { wfInfo* wfi; freerdp* instance; thread_data* data; data = (thread_data*) lpParam; instance = data->instance; wfi = (wfInfo*) xzalloc(sizeof(wfInfo)); ((wfContext*) instance->context)->wfi = wfi; wfi->instance = instance; wfreerdp_run(instance); g_thread_count--; if (g_thread_count < 1) SetEvent(g_done_event); return (DWORD) NULL; } static DWORD WINAPI kbd_thread_func(LPVOID lpParam) { MSG msg; BOOL status; HHOOK hook_handle; hook_handle = SetWindowsHookEx(WH_KEYBOARD_LL, wf_ll_kbd_proc, g_hInstance, 0); if (hook_handle) { while ((status = GetMessage( &msg, NULL, 0, 0 )) != 0) { if (status == -1) { printf("keyboard thread error getting message\n"); break; } else { TranslateMessage(&msg); DispatchMessage(&msg); } } UnhookWindowsHookEx(hook_handle); } else printf("failed to install keyboard hook\n"); return (DWORD) NULL; } INT WINAPI WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, LPSTR lpCmdLine, int nCmdShow) { freerdp* instance; thread_data* data; WSADATA wsa_data; WNDCLASSEX wnd_cls; if (NULL == getenv("HOME")) { char home[MAX_PATH * 2] = "HOME="; strcat(home, getenv("HOMEDRIVE")); strcat(home, getenv("HOMEPATH")); _putenv(home); } if (WSAStartup(0x101, &wsa_data) != 0) return 1; g_done_event = CreateEvent(0, 1, 0, 0); #if defined(WITH_DEBUG) || defined(_DEBUG) wf_create_console(); #endif g_default_cursor = LoadCursor(NULL, IDC_ARROW); wnd_cls.cbSize = sizeof(WNDCLASSEX); wnd_cls.style = CS_HREDRAW | CS_VREDRAW; wnd_cls.lpfnWndProc = wf_event_proc; wnd_cls.cbClsExtra = 0; wnd_cls.cbWndExtra = 0; wnd_cls.hIcon = LoadIcon(NULL, IDI_APPLICATION); wnd_cls.hCursor = g_default_cursor; wnd_cls.hbrBackground = (HBRUSH) GetStockObject(WHITE_BRUSH); wnd_cls.lpszMenuName = NULL; wnd_cls.lpszClassName = g_wnd_class_name; wnd_cls.hInstance = hInstance; wnd_cls.hIconSm = LoadIcon(NULL, IDI_APPLICATION); RegisterClassEx(&wnd_cls); g_hInstance = hInstance; freerdp_channels_global_init(); instance = freerdp_new(); instance->PreConnect = wf_pre_connect; instance->PostConnect = wf_post_connect; instance->VerifyCertificate = wf_verify_certificate; instance->ReceiveChannelData = wf_receive_channel_data; instance->context_size = sizeof(wfContext); instance->ContextNew = wf_context_new; instance->ContextFree = wf_context_free; freerdp_context_new(instance); instance->context->argc = __argc; instance->context->argv = __argv; if (!CreateThread(NULL, 0, kbd_thread_func, NULL, 0, NULL)) printf("error creating keyboard handler thread"); //while (1) { data = (thread_data*) xzalloc(sizeof(thread_data)); data->instance = instance; freerdp_parse_args(instance->settings, __argc, __argv, wf_process_plugin_args, instance->context->channels, wf_process_client_args, NULL); if (CreateThread(NULL, 0, thread_func, data, 0, NULL) != 0) g_thread_count++; } if (g_thread_count > 0) WaitForSingleObject(g_done_event, INFINITE); else MessageBox(GetConsoleWindow(), L"Failed to start wfreerdp.\n\nPlease check the debug output.", L"FreeRDP Error", MB_ICONSTOP); WSACleanup(); #ifdef _DEBUG system("pause"); #endif return 0; } FreeRDP-1.0.2/client/Windows/wfreerdp.h000066400000000000000000000037531207112532300176440ustar00rootroot00000000000000/** * FreeRDP: A Remote Desktop Protocol Client * Windows Client * * Copyright 2009-2011 Jay Sorg * Copyright 2010-2011 Vic Lee * Copyright 2010-2011 Marc-Andre Moreau * * 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. */ #ifndef __WFREERDP_H #define __WFREERDP_H #ifndef WIN32_LEAN_AND_MEAN #define WIN32_LEAN_AND_MEAN #endif #include #include #include #include #include #include #include #include #include #include #include #include #include "wf_event.h" struct wf_bitmap { rdpBitmap _bitmap; HDC hdc; HBITMAP bitmap; HBITMAP org_bitmap; uint8* pdata; }; typedef struct wf_bitmap wfBitmap; struct wf_pointer { rdpPointer pointer; }; typedef struct wf_pointer wfPointer; typedef struct wf_info wfInfo; struct wf_context { rdpContext _p; wfInfo* wfi; }; typedef struct wf_context wfContext; struct wf_info { int fs_toggle; int fullscreen; int percentscreen; char window_title[64]; HWND hwnd; HGDI_DC hdc; uint16 srcBpp; uint16 dstBpp; freerdp* instance; wfBitmap* primary; wfBitmap* drawing; HCLRCONV clrconv; HCURSOR cursor; HBRUSH brush; HBRUSH org_brush; RECT update_rect; wfBitmap* tile; wfBitmap* image; RFX_CONTEXT* rfx_context; NSC_CONTEXT* nsc_context; boolean sw_gdi; }; #endif FreeRDP-1.0.2/client/X11/000077500000000000000000000000001207112532300145645ustar00rootroot00000000000000FreeRDP-1.0.2/client/X11/CMakeLists.txt000066400000000000000000000053701207112532300173310ustar00rootroot00000000000000# FreeRDP: A Remote Desktop Protocol Client # FreeRDP X11 Client # # Copyright 2011 O.S. Systems Software Ltda. # Copyright 2011 Otavio Salvador # Copyright 2011 Marc-Andre Moreau # # 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. include(FindXmlto) include_directories(${X11_INCLUDE_DIRS}) add_executable(xfreerdp xf_gdi.c xf_gdi.h xf_rail.c xf_rail.h xf_tsmf.c xf_tsmf.h xf_event.c xf_event.h xf_cliprdr.c xf_cliprdr.h xf_monitor.c xf_monitor.h xf_graphics.c xf_graphics.h xf_keyboard.c xf_keyboard.h xf_window.c xf_window.h xfreerdp.c xfreerdp.h) if(WITH_MANPAGES) if(XMLTO_FOUND) add_custom_command(OUTPUT xfreerdp.1 COMMAND ${XMLTO_EXECUTABLE} man ${CMAKE_CURRENT_SOURCE_DIR}/xfreerdp.1.xml DEPENDS xfreerdp.1.xml) add_custom_target(xfreerdp.manpage ALL DEPENDS xfreerdp.1) install(FILES ${CMAKE_CURRENT_BINARY_DIR}/xfreerdp.1 DESTINATION share/man/man1) else(XMLTO_FOUND) message(WARNING "WITH_MANPAGES was set, but xmlto was not found. man-pages will not be installed") endif(XMLTO_FOUND) endif(WITH_MANPAGES) find_suggested_package(Xinerama) if(WITH_XINERAMA) add_definitions(-DWITH_XINERAMA -DWITH_XEXT) include_directories(${XINERAMA_INCLUDE_DIRS}) target_link_libraries(xfreerdp ${XINERAMA_LIBRARIES}) endif() find_suggested_package(Xext) if(WITH_XEXT) add_definitions(-DWITH_XEXT) include_directories(${XEXT_INCLUDE_DIRS}) target_link_libraries(xfreerdp ${XEXT_LIBRARIES}) endif() find_suggested_package(Xcursor) if(WITH_XCURSOR) add_definitions(-DWITH_XCURSOR) include_directories(${XCURSOR_INCLUDE_DIRS}) target_link_libraries(xfreerdp ${XCURSOR_LIBRARIES}) endif() find_suggested_package(Xv) if(WITH_XV) add_definitions(-DWITH_XV) include_directories(${XV_INCLUDE_DIRS}) target_link_libraries(xfreerdp ${XV_LIBRARIES}) endif() include_directories(${CMAKE_SOURCE_DIR}/resources) target_link_libraries(xfreerdp freerdp-core) target_link_libraries(xfreerdp freerdp-gdi) target_link_libraries(xfreerdp freerdp-kbd) target_link_libraries(xfreerdp freerdp-rail) target_link_libraries(xfreerdp freerdp-channels) target_link_libraries(xfreerdp freerdp-utils) target_link_libraries(xfreerdp ${X11_LIBRARIES} ${CMAKE_DL_LIBS}) install(TARGETS xfreerdp DESTINATION ${CMAKE_INSTALL_BINDIR}) FreeRDP-1.0.2/client/X11/xf_cliprdr.c000066400000000000000000000717761207112532300171060ustar00rootroot00000000000000/** * FreeRDP: A Remote Desktop Protocol Client * X11 Clipboard Redirection * * Copyright 2010-2011 Vic Lee * * 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. */ #include #include #include #include #include #include #include #include "xf_cliprdr.h" typedef struct clipboard_format_mapping clipboardFormatMapping; struct clipboard_format_mapping { Atom target_format; uint32 format_id; }; typedef struct clipboard_context clipboardContext; struct clipboard_context { rdpChannels* channels; Window root_window; Atom clipboard_atom; Atom property_atom; Atom identity_atom; clipboardFormatMapping format_mappings[20]; int num_format_mappings; /* server->client data */ uint32* formats; int num_formats; Atom targets[20]; int num_targets; uint8* data; uint32 data_format; uint32 data_alt_format; int data_length; XEvent* respond; /* client->server data */ Window owner; int request_index; boolean sync; /* INCR mechanism */ Atom incr_atom; boolean incr_starts; uint8* incr_data; int incr_data_length; }; void xf_cliprdr_init(xfInfo* xfi, rdpChannels* chanman) { int n; uint32 id; clipboardContext* cb; cb = xnew(clipboardContext); xfi->clipboard_context = cb; cb->channels = chanman; cb->request_index = -1; cb->root_window = DefaultRootWindow(xfi->display); cb->clipboard_atom = XInternAtom(xfi->display, "CLIPBOARD", false); if (cb->clipboard_atom == None) { DEBUG_WARN("unable to get CLIPBOARD atom"); } id = 1; cb->property_atom = XInternAtom(xfi->display, "_FREERDP_CLIPRDR", false); cb->identity_atom = XInternAtom(xfi->display, "_FREERDP_CLIPRDR_ID", false); XChangeProperty(xfi->display, xfi->drawable, cb->identity_atom, XA_INTEGER, 32, PropModeReplace, (uint8*) &id, 1); XSelectInput(xfi->display, cb->root_window, PropertyChangeMask); n = 0; cb->format_mappings[n].target_format = XInternAtom(xfi->display, "_FREERDP_RAW", false); cb->format_mappings[n].format_id = CB_FORMAT_RAW; n++; cb->format_mappings[n].target_format = XInternAtom(xfi->display, "UTF8_STRING", false); cb->format_mappings[n].format_id = CB_FORMAT_UNICODETEXT; n++; cb->format_mappings[n].target_format = XA_STRING; cb->format_mappings[n].format_id = CB_FORMAT_TEXT; n++; cb->format_mappings[n].target_format = XInternAtom(xfi->display, "image/png", false); cb->format_mappings[n].format_id = CB_FORMAT_PNG; n++; cb->format_mappings[n].target_format = XInternAtom(xfi->display, "image/jpeg", false); cb->format_mappings[n].format_id = CB_FORMAT_JPEG; n++; cb->format_mappings[n].target_format = XInternAtom(xfi->display, "image/gif", false); cb->format_mappings[n].format_id = CB_FORMAT_GIF; n++; cb->format_mappings[n].target_format = XInternAtom(xfi->display, "image/bmp", false); cb->format_mappings[n].format_id = CB_FORMAT_DIB; n++; cb->format_mappings[n].target_format = XInternAtom(xfi->display, "text/html", false); cb->format_mappings[n].format_id = CB_FORMAT_HTML; cb->num_format_mappings = n + 1; cb->targets[0] = XInternAtom(xfi->display, "TIMESTAMP", false); cb->targets[1] = XInternAtom(xfi->display, "TARGETS", false); cb->num_targets = 2; cb->incr_atom = XInternAtom(xfi->display, "INCR", false); } void xf_cliprdr_uninit(xfInfo* xfi) { clipboardContext* cb = (clipboardContext*) xfi->clipboard_context; if (cb) { xfree(cb->formats); xfree(cb->data); xfree(cb->respond); xfree(cb->incr_data); xfree(cb); xfi->clipboard_context = NULL; } } static uint8* lf2crlf(uint8* data, int* size) { uint8 c; uint8* outbuf; uint8* out; uint8* in_end; uint8* in; int out_size; out_size = (*size) * 2 + 1; outbuf = (uint8*) xzalloc(out_size); out = outbuf; in = data; in_end = data + (*size); while (in < in_end) { c = *in++; if (c == '\n') { *out++ = '\r'; *out++ = '\n'; } else { *out++ = c; } } *out++ = 0; *size = out - outbuf; return outbuf; } static void crlf2lf(uint8* data, int* size) { uint8 c; uint8* out; uint8* in; uint8* in_end; out = data; in = data; in_end = data + (*size); while (in < in_end) { c = *in++; if (c != '\r') *out++ = c; } *size = out - data; } static void be2le(uint8* data, int size) { uint8 c; while (size >= 2) { c = data[0]; data[0] = data[1]; data[1] = c; data += 2; size -= 2; } } static boolean xf_cliprdr_is_self_owned(xfInfo* xfi) { Atom type; uint32 id = 0; uint32* pid = NULL; int format, result = 0; unsigned long length, bytes_left; clipboardContext* cb = (clipboardContext*) xfi->clipboard_context; cb->owner = XGetSelectionOwner(xfi->display, cb->clipboard_atom); if (cb->owner != None) { result = XGetWindowProperty(xfi->display, cb->owner, cb->identity_atom, 0, 4, 0, XA_INTEGER, &type, &format, &length, &bytes_left, (uint8**) &pid); } if (pid) { id = *pid; XFree(pid); } if ((cb->owner == None) || (cb->owner == xfi->drawable)) return false; if (result != Success) return false; return (id ? true : false); } static int xf_cliprdr_select_format_by_id(clipboardContext* cb, uint32 format_id) { int i; for (i = 0; i < cb->num_format_mappings; i++) { if (cb->format_mappings[i].format_id == format_id) return i; } return -1; } static int xf_cliprdr_select_format_by_atom(clipboardContext* cb, Atom target) { int i; int j; if (cb->formats == NULL) return -1; for (i = 0; i < cb->num_format_mappings; i++) { if (cb->format_mappings[i].target_format != target) continue; if (cb->format_mappings[i].format_id == CB_FORMAT_RAW) return i; for (j = 0; j < cb->num_formats; j++) { if (cb->format_mappings[i].format_id == cb->formats[j]) return i; } } return -1; } static void xf_cliprdr_send_raw_format_list(xfInfo* xfi) { Atom type; uint8* format_data; int format, result; unsigned long length, bytes_left; RDP_CB_FORMAT_LIST_EVENT* event; clipboardContext* cb = (clipboardContext*) xfi->clipboard_context; result = XGetWindowProperty(xfi->display, cb->root_window, cb->property_atom, 0, 3600, 0, XA_STRING, &type, &format, &length, &bytes_left, (uint8**) &format_data); if (result != Success) { DEBUG_WARN("XGetWindowProperty failed"); return; } DEBUG_X11_CLIPRDR("format=%d len=%d bytes_left=%d", format, (int) length, (int) bytes_left); event = (RDP_CB_FORMAT_LIST_EVENT*) freerdp_event_new(RDP_EVENT_CLASS_CLIPRDR, RDP_EVENT_TYPE_CB_FORMAT_LIST, NULL, NULL); event->raw_format_data = (uint8*) xmalloc(length); memcpy(event->raw_format_data, format_data, length); event->raw_format_data_size = length; XFree(format_data); freerdp_channels_send_event(cb->channels, (RDP_EVENT*) event); } static void xf_cliprdr_send_null_format_list(xfInfo* xfi) { RDP_CB_FORMAT_LIST_EVENT* event; clipboardContext* cb = (clipboardContext*) xfi->clipboard_context; event = (RDP_CB_FORMAT_LIST_EVENT*) freerdp_event_new(RDP_EVENT_CLASS_CLIPRDR, RDP_EVENT_TYPE_CB_FORMAT_LIST, NULL, NULL); event->num_formats = 0; freerdp_channels_send_event(cb->channels, (RDP_EVENT*) event); } static void xf_cliprdr_send_supported_format_list(xfInfo* xfi) { int i; RDP_CB_FORMAT_LIST_EVENT* event; clipboardContext* cb = (clipboardContext*) xfi->clipboard_context; event = (RDP_CB_FORMAT_LIST_EVENT*) freerdp_event_new(RDP_EVENT_CLASS_CLIPRDR, RDP_EVENT_TYPE_CB_FORMAT_LIST, NULL, NULL); event->formats = (uint32*) xmalloc(sizeof(uint32) * cb->num_format_mappings); event->num_formats = cb->num_format_mappings; for (i = 0; i < cb->num_format_mappings; i++) event->formats[i] = cb->format_mappings[i].format_id; freerdp_channels_send_event(cb->channels, (RDP_EVENT*) event); } static void xf_cliprdr_send_format_list(xfInfo* xfi) { clipboardContext* cb = (clipboardContext*) xfi->clipboard_context; if (xf_cliprdr_is_self_owned(xfi)) { xf_cliprdr_send_raw_format_list(xfi); } else if (cb->owner == None) { xf_cliprdr_send_null_format_list(xfi); } else if (cb->owner != xfi->drawable) { /* Request the owner for TARGETS, and wait for SelectionNotify event */ XConvertSelection(xfi->display, cb->clipboard_atom, cb->targets[1], cb->property_atom, xfi->drawable, CurrentTime); } } static void xf_cliprdr_send_data_request(xfInfo* xfi, uint32 format) { RDP_CB_DATA_REQUEST_EVENT* event; clipboardContext* cb = (clipboardContext*) xfi->clipboard_context; event = (RDP_CB_DATA_REQUEST_EVENT*) freerdp_event_new(RDP_EVENT_CLASS_CLIPRDR, RDP_EVENT_TYPE_CB_DATA_REQUEST, NULL, NULL); event->format = format; freerdp_channels_send_event(cb->channels, (RDP_EVENT*) event); } static void xf_cliprdr_send_data_response(xfInfo* xfi, uint8* data, int size) { RDP_CB_DATA_RESPONSE_EVENT* event; clipboardContext* cb = (clipboardContext*) xfi->clipboard_context; event = (RDP_CB_DATA_RESPONSE_EVENT*) freerdp_event_new(RDP_EVENT_CLASS_CLIPRDR, RDP_EVENT_TYPE_CB_DATA_RESPONSE, NULL, NULL); event->data = data; event->size = size; freerdp_channels_send_event(cb->channels, (RDP_EVENT*) event); } static void xf_cliprdr_send_null_data_response(xfInfo* xfi) { xf_cliprdr_send_data_response(xfi, NULL, 0); } static void xf_cliprdr_process_cb_monitor_ready_event(xfInfo* xfi) { clipboardContext* cb = (clipboardContext*) xfi->clipboard_context; xf_cliprdr_send_format_list(xfi); cb->sync = true; } static void xf_cliprdr_process_cb_data_request_event(xfInfo* xfi, RDP_CB_DATA_REQUEST_EVENT* event) { int i; clipboardContext* cb = (clipboardContext*) xfi->clipboard_context; DEBUG_X11_CLIPRDR("format %d", event->format); if (xf_cliprdr_is_self_owned(xfi)) { /* CB_FORMAT_RAW */ i = 0; XChangeProperty(xfi->display, xfi->drawable, cb->property_atom, XA_INTEGER, 32, PropModeReplace, (uint8*) &event->format, 1); } else { i = xf_cliprdr_select_format_by_id(cb, event->format); } if (i < 0) { DEBUG_X11_CLIPRDR("unsupported format requested"); xf_cliprdr_send_null_data_response(xfi); } else { cb->request_index = i; DEBUG_X11_CLIPRDR("target=%d", (int) cb->format_mappings[i].target_format); XConvertSelection(xfi->display, cb->clipboard_atom, cb->format_mappings[i].target_format, cb->property_atom, xfi->drawable, CurrentTime); XFlush(xfi->display); /* After this point, we expect a SelectionNotify event from the clipboard owner. */ } } static void xf_cliprdr_get_requested_targets(xfInfo* xfi) { int num; int i, j; Atom atom; int format; uint8* data = NULL; unsigned long length, bytes_left; RDP_CB_FORMAT_LIST_EVENT* event; clipboardContext* cb = (clipboardContext*) xfi->clipboard_context; XGetWindowProperty(xfi->display, xfi->drawable, cb->property_atom, 0, 200, 0, XA_ATOM, &atom, &format, &length, &bytes_left, &data); DEBUG_X11_CLIPRDR("type=%d format=%d length=%d bytes_left=%d", (int) atom, format, (int) length, (int) bytes_left); if (length > 0) { event = (RDP_CB_FORMAT_LIST_EVENT*) freerdp_event_new(RDP_EVENT_CLASS_CLIPRDR, RDP_EVENT_TYPE_CB_FORMAT_LIST, NULL, NULL); event->formats = (uint32*) xmalloc(sizeof(uint32) * cb->num_format_mappings); num = 0; for (i = 0; i < length; i++) { atom = ((Atom*) data)[i]; DEBUG_X11("atom %d", (int) atom); for (j = 0; j < cb->num_format_mappings; j++) { if (cb->format_mappings[j].target_format == atom) { DEBUG_X11("found format %d for atom %d", cb->format_mappings[j].format_id, (int)atom); event->formats[num++] = cb->format_mappings[j].format_id; break; } } } event->num_formats = num; XFree(data); freerdp_channels_send_event(cb->channels, (RDP_EVENT*) event); } else { if (data) XFree(data); xf_cliprdr_send_null_format_list(xfi); } } static uint8* xf_cliprdr_process_requested_raw(uint8* data, int* size) { uint8* outbuf; outbuf = (uint8*) xmalloc(*size); memcpy(outbuf, data, *size); return outbuf; } static uint8* xf_cliprdr_process_requested_unicodetext(uint8* data, int* size) { uint8* inbuf; uint8* outbuf; size_t out_size; UNICONV* uniconv; inbuf = lf2crlf(data, size); uniconv = freerdp_uniconv_new(); outbuf = (uint8*) freerdp_uniconv_out(uniconv, (char*) inbuf, &out_size); freerdp_uniconv_free(uniconv); xfree(inbuf); *size = (int) out_size + 2; return outbuf; } static uint8* xf_cliprdr_process_requested_text(uint8* data, int* size) { uint8* outbuf; outbuf = lf2crlf(data, size); return outbuf; } static uint8* xf_cliprdr_process_requested_dib(uint8* data, int* size) { uint8* outbuf; /* length should be at least BMP header (14) + sizeof(BITMAPINFOHEADER) */ if (*size < 54) { DEBUG_X11_CLIPRDR("bmp length %d too short", *size); return NULL; } *size -= 14; outbuf = (uint8*) xzalloc(*size); memcpy(outbuf, data + 14, *size); return outbuf; } static uint8* xf_cliprdr_process_requested_html(uint8* data, int* size) { uint8* inbuf; uint8* in; uint8* outbuf; char num[11]; UNICONV* uniconv; inbuf = NULL; if (*size > 2) { if ((uint8) data[0] == 0xFE && (uint8) data[1] == 0xFF) { be2le(data, *size); } if ((uint8) data[0] == 0xFF && (uint8) data[1] == 0xFE) { uniconv = freerdp_uniconv_new(); inbuf = (uint8*) freerdp_uniconv_in(uniconv, data + 2, *size - 2); freerdp_uniconv_free(uniconv); } } if (inbuf == NULL) { inbuf = xzalloc(*size + 1); memcpy(inbuf, data, *size); } outbuf = (uint8*) xzalloc(*size + 200); strcpy((char*) outbuf, "Version:0.9\r\n" "StartHTML:0000000000\r\n" "EndHTML:0000000000\r\n" "StartFragment:0000000000\r\n" "EndFragment:0000000000\r\n"); in = (uint8*) strstr((char*) inbuf, ""); } strcat((char*) outbuf, ""); /* StartFragment */ snprintf(num, sizeof(num), "%010lu", (unsigned long) strlen((char*) outbuf)); memcpy(outbuf + 69, num, 10); strcat((char*) outbuf, (char*) inbuf); /* EndFragment */ snprintf(num, sizeof(num), "%010lu", (unsigned long) strlen((char*) outbuf)); memcpy(outbuf + 93, num, 10); strcat((char*) outbuf, ""); if (in == NULL) { strcat((char*) outbuf, ""); } /* EndHTML */ snprintf(num, sizeof(num), "%010lu", (unsigned long) strlen((char*) outbuf)); memcpy(outbuf + 43, num, 10); *size = strlen((char*) outbuf) + 1; xfree(inbuf); return outbuf; } static void xf_cliprdr_process_requested_data(xfInfo* xfi, boolean has_data, uint8* data, int size) { uint8* outbuf; clipboardContext* cb = (clipboardContext*) xfi->clipboard_context; if (cb->incr_starts && has_data) return; if (!has_data || data == NULL) { xf_cliprdr_send_null_data_response(xfi); return; } switch (cb->format_mappings[cb->request_index].format_id) { case CB_FORMAT_RAW: case CB_FORMAT_PNG: case CB_FORMAT_JPEG: case CB_FORMAT_GIF: outbuf = xf_cliprdr_process_requested_raw(data, &size); break; case CB_FORMAT_UNICODETEXT: outbuf = xf_cliprdr_process_requested_unicodetext(data, &size); break; case CB_FORMAT_TEXT: outbuf = xf_cliprdr_process_requested_text(data, &size); break; case CB_FORMAT_DIB: outbuf = xf_cliprdr_process_requested_dib(data, &size); break; case CB_FORMAT_HTML: outbuf = xf_cliprdr_process_requested_html(data, &size); break; default: outbuf = NULL; break; } if (outbuf) xf_cliprdr_send_data_response(xfi, outbuf, size); else xf_cliprdr_send_null_data_response(xfi); /* Resend the format list, otherwise the server won't request again for the next paste */ xf_cliprdr_send_format_list(xfi); } static boolean xf_cliprdr_get_requested_data(xfInfo* xfi, Atom target) { Atom type; int format; uint8* data = NULL; boolean has_data = false; unsigned long length, bytes_left, dummy; clipboardContext* cb = (clipboardContext*) xfi->clipboard_context; if ((cb->request_index < 0) || (cb->format_mappings[cb->request_index].target_format != target)) { DEBUG_X11_CLIPRDR("invalid target"); xf_cliprdr_send_null_data_response(xfi); return false; } XGetWindowProperty(xfi->display, xfi->drawable, cb->property_atom, 0, 0, 0, target, &type, &format, &length, &bytes_left, &data); DEBUG_X11_CLIPRDR("type=%d format=%d bytes=%d request_index=%d", (int) type, format, (int) bytes_left, cb->request_index); if (data) { XFree(data); data = NULL; } if (bytes_left <= 0 && !cb->incr_starts) { DEBUG_X11("no data"); } else if (type == cb->incr_atom) { DEBUG_X11("INCR started"); cb->incr_starts = true; if (cb->incr_data) { xfree(cb->incr_data); cb->incr_data = NULL; } cb->incr_data_length = 0; /* Data will be followed in PropertyNotify event */ has_data = true; } else { if (bytes_left <= 0) { /* INCR finish */ data = cb->incr_data; cb->incr_data = NULL; bytes_left = cb->incr_data_length; cb->incr_data_length = 0; cb->incr_starts = 0; DEBUG_X11("INCR finished"); has_data = true; } else if (XGetWindowProperty(xfi->display, xfi->drawable, cb->property_atom, 0, bytes_left, 0, target, &type, &format, &length, &dummy, &data) == Success) { if (cb->incr_starts) { bytes_left = length * format / 8; DEBUG_X11("%d bytes", (int)bytes_left); cb->incr_data = (uint8*) xrealloc(cb->incr_data, cb->incr_data_length + bytes_left); memcpy(cb->incr_data + cb->incr_data_length, data, bytes_left); cb->incr_data_length += bytes_left; XFree(data); data = NULL; } has_data = true; } else { DEBUG_X11_CLIPRDR("XGetWindowProperty failed"); } } XDeleteProperty(xfi->display, xfi->drawable, cb->property_atom); xf_cliprdr_process_requested_data(xfi, has_data, data, (int) bytes_left); if (data) XFree(data); return true; } static void xf_cliprdr_append_target(clipboardContext* cb, Atom target) { int i; if (cb->num_targets >= sizeof(cb->targets) / sizeof(Atom)) return; for (i = 0; i < cb->num_targets; i++) { if (cb->targets[i] == target) return; } cb->targets[cb->num_targets++] = target; } static void xf_cliprdr_provide_targets(xfInfo* xfi, XEvent* respond) { clipboardContext* cb = (clipboardContext*) xfi->clipboard_context; if (respond->xselection.property != None) { XChangeProperty(xfi->display, respond->xselection.requestor, respond->xselection.property, XA_ATOM, 32, PropModeReplace, (uint8*) cb->targets, cb->num_targets); } } static void xf_cliprdr_provide_data(xfInfo* xfi, XEvent* respond) { clipboardContext* cb = (clipboardContext*) xfi->clipboard_context; if (respond->xselection.property != None) { XChangeProperty(xfi->display, respond->xselection.requestor, respond->xselection.property, respond->xselection.target, 8, PropModeReplace, (uint8*) cb->data, cb->data_length); } } static void xf_cliprdr_process_cb_format_list_event(xfInfo* xfi, RDP_CB_FORMAT_LIST_EVENT* event) { int i, j; clipboardContext* cb = (clipboardContext*) xfi->clipboard_context; if (cb->data) { xfree(cb->data); cb->data = NULL; } if (cb->formats) xfree(cb->formats); cb->formats = event->formats; cb->num_formats = event->num_formats; event->formats = NULL; event->num_formats = 0; cb->num_targets = 2; for (i = 0; i < cb->num_formats; i++) { for (j = 0; j < cb->num_format_mappings; j++) { if (cb->formats[i] == cb->format_mappings[j].format_id) { DEBUG_X11("announce format#%d : %d", i, cb->formats[i]); xf_cliprdr_append_target(cb, cb->format_mappings[j].target_format); } } } XSetSelectionOwner(xfi->display, cb->clipboard_atom, xfi->drawable, CurrentTime); if (event->raw_format_data) { XChangeProperty(xfi->display, cb->root_window, cb->property_atom, XA_STRING, 8, PropModeReplace, event->raw_format_data, event->raw_format_data_size); } XFlush(xfi->display); } static void xf_cliprdr_process_text(clipboardContext* cb, uint8* data, int size) { cb->data = (uint8*) xmalloc(size); memcpy(cb->data, data, size); cb->data_length = size; crlf2lf(cb->data, &cb->data_length); } static void xf_cliprdr_process_unicodetext(clipboardContext* cb, uint8* data, int size) { UNICONV* uniconv; uniconv = freerdp_uniconv_new(); cb->data = (uint8*) freerdp_uniconv_in(uniconv, data, size); freerdp_uniconv_free(uniconv); cb->data_length = strlen((char*) cb->data); crlf2lf(cb->data, &cb->data_length); } static void xf_cliprdr_process_dib(clipboardContext* cb, uint8* data, int size) { STREAM* s; uint16 bpp; uint32 offset; uint32 ncolors; /* size should be at least sizeof(BITMAPINFOHEADER) */ if (size < 40) { DEBUG_X11_CLIPRDR("dib size %d too short", size); return; } s = stream_new(0); stream_attach(s, data, size); stream_seek(s, 14); stream_read_uint16(s, bpp); stream_read_uint32(s, ncolors); offset = 14 + 40 + (bpp <= 8 ? (ncolors == 0 ? (1 << bpp) : ncolors) * 4 : 0); stream_detach(s); stream_free(s); DEBUG_X11_CLIPRDR("offset=%d bpp=%d ncolors=%d", offset, bpp, ncolors); s = stream_new(14 + size); stream_write_uint8(s, 'B'); stream_write_uint8(s, 'M'); stream_write_uint32(s, 14 + size); stream_write_uint32(s, 0); stream_write_uint32(s, offset); stream_write(s, data, size); cb->data = stream_get_head(s); cb->data_length = stream_get_length(s); stream_detach(s); stream_free(s); } static void xf_cliprdr_process_html(clipboardContext* cb, uint8* data, int size) { char* start_str; char* end_str; int start; int end; start_str = strstr((char*) data, "StartHTML:"); end_str = strstr((char*) data, "EndHTML:"); if (start_str == NULL || end_str == NULL) { DEBUG_X11_CLIPRDR("invalid HTML clipboard format"); return; } start = atoi(start_str + 10); end = atoi(end_str + 8); if (start > size || end > size || start >= end) { DEBUG_X11_CLIPRDR("invalid HTML offset"); return; } cb->data = (uint8*) xmalloc(size - start + 1); memcpy(cb->data, data + start, end - start); cb->data_length = end - start; crlf2lf(cb->data, &cb->data_length); } static void xf_cliprdr_process_cb_data_response_event(xfInfo* xfi, RDP_CB_DATA_RESPONSE_EVENT* event) { clipboardContext* cb = (clipboardContext*) xfi->clipboard_context; DEBUG_X11_CLIPRDR("size=%d", event->size); if (cb->respond == NULL) { DEBUG_X11_CLIPRDR("unexpected data"); return; } if (event->size == 0) { cb->respond->xselection.property = None; } else { if (cb->data) { xfree(cb->data); cb->data = NULL; } switch (cb->data_format) { case CB_FORMAT_RAW: case CB_FORMAT_PNG: case CB_FORMAT_JPEG: case CB_FORMAT_GIF: cb->data = event->data; cb->data_length = event->size; event->data = NULL; event->size = 0; break; case CB_FORMAT_TEXT: xf_cliprdr_process_text(cb, event->data, event->size); break; case CB_FORMAT_UNICODETEXT: xf_cliprdr_process_unicodetext(cb, event->data, event->size); break; case CB_FORMAT_DIB: xf_cliprdr_process_dib(cb, event->data, event->size); break; case CB_FORMAT_HTML: xf_cliprdr_process_html(cb, event->data, event->size); break; default: cb->respond->xselection.property = None; break; } xf_cliprdr_provide_data(xfi, cb->respond); } XSendEvent(xfi->display, cb->respond->xselection.requestor, 0, 0, cb->respond); XFlush(xfi->display); xfree(cb->respond); cb->respond = NULL; } void xf_process_cliprdr_event(xfInfo* xfi, RDP_EVENT* event) { switch (event->event_type) { case RDP_EVENT_TYPE_CB_MONITOR_READY: xf_cliprdr_process_cb_monitor_ready_event(xfi); break; case RDP_EVENT_TYPE_CB_FORMAT_LIST: xf_cliprdr_process_cb_format_list_event(xfi, (RDP_CB_FORMAT_LIST_EVENT*) event); break; case RDP_EVENT_TYPE_CB_DATA_REQUEST: xf_cliprdr_process_cb_data_request_event(xfi, (RDP_CB_DATA_REQUEST_EVENT*) event); break; case RDP_EVENT_TYPE_CB_DATA_RESPONSE: xf_cliprdr_process_cb_data_response_event(xfi, (RDP_CB_DATA_RESPONSE_EVENT*) event); break; default: DEBUG_X11_CLIPRDR("unknown event type %d", event->event_type); break; } } boolean xf_cliprdr_process_selection_notify(xfInfo* xfi, XEvent* xevent) { clipboardContext* cb = (clipboardContext*) xfi->clipboard_context; if (xevent->xselection.target == cb->targets[1]) { if (xevent->xselection.property == None) { DEBUG_X11_CLIPRDR("owner not support TARGETS. sending all format."); xf_cliprdr_send_supported_format_list(xfi); } else { xf_cliprdr_get_requested_targets(xfi); } return true; } else { return xf_cliprdr_get_requested_data(xfi, xevent->xselection.target); } } boolean xf_cliprdr_process_selection_request(xfInfo* xfi, XEvent* xevent) { int i; int fmt; Atom type; uint32 format; XEvent* respond; uint32 alt_format; uint8* data = NULL; boolean delay_respond; unsigned long length, bytes_left; clipboardContext* cb = (clipboardContext*) xfi->clipboard_context; DEBUG_X11_CLIPRDR("target=%d", (int) xevent->xselectionrequest.target); if (xevent->xselectionrequest.owner != xfi->drawable) { DEBUG_X11_CLIPRDR("not owner"); return false; } delay_respond = false; respond = xnew(XEvent); respond->xselection.property = None; respond->xselection.type = SelectionNotify; respond->xselection.display = xevent->xselectionrequest.display; respond->xselection.requestor = xevent->xselectionrequest.requestor; respond->xselection.selection = xevent->xselectionrequest.selection; respond->xselection.target = xevent->xselectionrequest.target; respond->xselection.time = xevent->xselectionrequest.time; if (xevent->xselectionrequest.target == cb->targets[0]) /* TIMESTAMP */ { /* TODO */ DEBUG_X11_CLIPRDR("target: TIMESTAMP (unimplemented)"); } else if (xevent->xselectionrequest.target == cb->targets[1]) /* TARGETS */ { /* Someone else requests our available formats */ DEBUG_X11_CLIPRDR("target: TARGETS"); respond->xselection.property = xevent->xselectionrequest.property; xf_cliprdr_provide_targets(xfi, respond); } else { DEBUG_X11_CLIPRDR("target: other"); i = xf_cliprdr_select_format_by_atom(cb, xevent->xselectionrequest.target); if (i >= 0 && xevent->xselectionrequest.requestor != xfi->drawable) { format = cb->format_mappings[i].format_id; alt_format = format; if (format == CB_FORMAT_RAW) { if (XGetWindowProperty(xfi->display, xevent->xselectionrequest.requestor, cb->property_atom, 0, 4, 0, XA_INTEGER, &type, &fmt, &length, &bytes_left, &data) != Success) { DEBUG_X11_CLIPRDR("XGetWindowProperty failed"); } if (data) { memcpy(&alt_format, data, 4); XFree(data); } } DEBUG_X11_CLIPRDR("provide format 0x%04x alt_format 0x%04x", format, alt_format); if ((cb->data != 0) && (format == cb->data_format) && (alt_format == cb->data_alt_format)) { /* Cached clipboard data available. Send it now */ respond->xselection.property = xevent->xselectionrequest.property; xf_cliprdr_provide_data(xfi, respond); } else if (cb->respond) { DEBUG_X11_CLIPRDR("duplicated request"); } else { /** * Send clipboard data request to the server. * Response will be postponed after receiving the data */ if (cb->data) { xfree(cb->data); cb->data = NULL; } respond->xselection.property = xevent->xselectionrequest.property; cb->respond = respond; cb->data_format = format; cb->data_alt_format = alt_format; delay_respond = true; xf_cliprdr_send_data_request(xfi, alt_format); } } } if (delay_respond == false) { XSendEvent(xfi->display, xevent->xselectionrequest.requestor, 0, 0, respond); XFlush(xfi->display); xfree(respond); } return true; } boolean xf_cliprdr_process_selection_clear(xfInfo* xfi, XEvent* xevent) { clipboardContext* cb = (clipboardContext*) xfi->clipboard_context; if (xf_cliprdr_is_self_owned(xfi)) return false; XDeleteProperty(xfi->display, cb->root_window, cb->property_atom); return true; } boolean xf_cliprdr_process_property_notify(xfInfo* xfi, XEvent* xevent) { clipboardContext* cb = (clipboardContext*) xfi->clipboard_context; if (xevent->xproperty.atom != cb->property_atom) return false; /* Not cliprdr-related */ if (xevent->xproperty.window == cb->root_window) { DEBUG_X11_CLIPRDR("root window PropertyNotify"); xf_cliprdr_send_format_list(xfi); } else if (xevent->xproperty.window == xfi->drawable && xevent->xproperty.state == PropertyNewValue && cb->incr_starts && cb->request_index >= 0) { DEBUG_X11_CLIPRDR("cliprdr window PropertyNotify"); xf_cliprdr_get_requested_data(xfi, cb->format_mappings[cb->request_index].target_format); } return true; } void xf_cliprdr_check_owner(xfInfo* xfi) { Window owner; clipboardContext* cb = (clipboardContext*) xfi->clipboard_context; if (cb->sync) { owner = XGetSelectionOwner(xfi->display, cb->clipboard_atom); if (cb->owner != owner) { cb->owner = owner; xf_cliprdr_send_format_list(xfi); } } } FreeRDP-1.0.2/client/X11/xf_cliprdr.h000066400000000000000000000026651207112532300171020ustar00rootroot00000000000000/** * FreeRDP: A Remote Desktop Protocol Client * X11 Clipboard Redirection * * Copyright 2010-2011 Vic Lee * * 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. */ #ifndef __XF_CLIPRDR_H #define __XF_CLIPRDR_H #include "xfreerdp.h" void xf_cliprdr_init(xfInfo* xfi, rdpChannels* chanman); void xf_cliprdr_uninit(xfInfo* xfi); void xf_process_cliprdr_event(xfInfo* xfi, RDP_EVENT* event); boolean xf_cliprdr_process_selection_notify(xfInfo* xfi, XEvent* xevent); boolean xf_cliprdr_process_selection_request(xfInfo* xfi, XEvent* xevent); boolean xf_cliprdr_process_selection_clear(xfInfo* xfi, XEvent* xevent); boolean xf_cliprdr_process_property_notify(xfInfo* xfi, XEvent* xevent); void xf_cliprdr_check_owner(xfInfo* xfi); #ifdef WITH_DEBUG_X11_CLIPRDR #define DEBUG_X11_CLIPRDR(fmt, ...) DEBUG_CLASS(X11_CLIPRDR, fmt, ## __VA_ARGS__) #else #define DEBUG_X11_CLIPRDR(fmt, ...) DEBUG_NULL(fmt, ## __VA_ARGS__) #endif #endif /* __XF_CLIPRDR_H */ FreeRDP-1.0.2/client/X11/xf_event.c000066400000000000000000000377551207112532300165670ustar00rootroot00000000000000/** * FreeRDP: A Remote Desktop Protocol Client * X11 Event Handling * * Copyright 2011 Marc-Andre Moreau * * 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. */ #include #include #include #include #include "xf_rail.h" #include "xf_window.h" #include "xf_cliprdr.h" #include "xf_event.h" static const char* const X11_EVENT_STRINGS[] = { "", "", "KeyPress", "KeyRelease", "ButtonPress", "ButtonRelease", "MotionNotify", "EnterNotify", "LeaveNotify", "FocusIn", "FocusOut", "KeymapNotify", "Expose", "GraphicsExpose", "NoExpose", "VisibilityNotify", "CreateNotify", "DestroyNotify", "UnmapNotify", "MapNotify", "MapRequest", "ReparentNotify", "ConfigureNotify", "ConfigureRequest", "GravityNotify", "ResizeRequest", "CirculateNotify", "CirculateRequest", "PropertyNotify", "SelectionClear", "SelectionRequest", "SelectionNotify", "ColormapNotify", "ClientMessage", "MappingNotify", "GenericEvent", }; void xf_send_mouse_motion_event(rdpInput* input, boolean down, uint32 button, uint16 x, uint16 y) { input->MouseEvent(input, PTR_FLAGS_MOVE, x, y); } boolean xf_event_Expose(xfInfo* xfi, XEvent* event, boolean app) { int x, y; int w, h; x = event->xexpose.x; y = event->xexpose.y; w = event->xexpose.width; h = event->xexpose.height; if (app != true) { XCopyArea(xfi->display, xfi->primary, xfi->window->handle, xfi->gc, x, y, w, h, x, y); } else { xfWindow* xfw; rdpWindow* window; rdpRail* rail = ((rdpContext*) xfi->context)->rail; window = window_list_get_by_extra_id(rail->list, (void*) event->xexpose.window); if (window != NULL) { xfw = (xfWindow*) window->extra; xf_UpdateWindowArea(xfi, xfw, x, y, w, h); } } return true; } boolean xf_event_VisibilityNotify(xfInfo* xfi, XEvent* event, boolean app) { xfi->unobscured = event->xvisibility.state == VisibilityUnobscured; return true; } boolean xf_event_MotionNotify(xfInfo* xfi, XEvent* event, boolean app) { rdpInput* input; input = xfi->instance->input; if (app != true) { if (xfi->mouse_motion != true) { if ((event->xmotion.state & (Button1Mask | Button2Mask | Button3Mask)) == 0) return true; } input->MouseEvent(input, PTR_FLAGS_MOVE, event->xmotion.x, event->xmotion.y); if (xfi->fullscreen) XSetInputFocus(xfi->display, xfi->window->handle, RevertToPointerRoot, CurrentTime); } else if (xfi->mouse_motion == true) { rdpWindow* window; int x = event->xmotion.x; int y = event->xmotion.y; rdpRail* rail = ((rdpContext*) xfi->context)->rail; window = window_list_get_by_extra_id(rail->list, (void*) event->xmotion.window); if (window != NULL) { x += window->windowOffsetX; y += window->windowOffsetY; input->MouseEvent(input, PTR_FLAGS_MOVE, x, y); } } return true; } boolean xf_event_ButtonPress(xfInfo* xfi, XEvent* event, boolean app) { uint16 x, y; uint16 flags; boolean wheel; rdpInput* input; input = xfi->instance->input; x = 0; y = 0; flags = 0; wheel = false; switch (event->xbutton.button) { case 1: x = event->xbutton.x; y = event->xbutton.y; flags = PTR_FLAGS_DOWN | PTR_FLAGS_BUTTON1; break; case 2: x = event->xbutton.x; y = event->xbutton.y; flags = PTR_FLAGS_DOWN | PTR_FLAGS_BUTTON3; break; case 3: x = event->xbutton.x; y = event->xbutton.y; flags = PTR_FLAGS_DOWN | PTR_FLAGS_BUTTON2; break; case 4: wheel = true; flags = PTR_FLAGS_WHEEL | 0x0078; break; case 5: wheel = true; flags = PTR_FLAGS_WHEEL | PTR_FLAGS_WHEEL_NEGATIVE | 0x0088; break; default: x = 0; y = 0; flags = 0; break; } if (flags != 0) { if (wheel) { input->MouseEvent(input, flags, 0, 0); } else { if (app) { rdpWindow* window; rdpRail* rail = ((rdpContext*) xfi->context)->rail; window = window_list_get_by_extra_id(rail->list, (void*) event->xbutton.window); if (window != NULL) { x += window->windowOffsetX; y += window->windowOffsetY; } } input->MouseEvent(input, flags, x, y); } } return true; } boolean xf_event_ButtonRelease(xfInfo* xfi, XEvent* event, boolean app) { uint16 x, y; uint16 flags; rdpInput* input; input = xfi->instance->input; x = 0; y = 0; flags = 0; switch (event->xbutton.button) { case 1: x = event->xbutton.x; y = event->xbutton.y; flags = PTR_FLAGS_BUTTON1; break; case 2: x = event->xbutton.x; y = event->xbutton.y; flags = PTR_FLAGS_BUTTON3; break; case 3: x = event->xbutton.x; y = event->xbutton.y; flags = PTR_FLAGS_BUTTON2; break; default: flags = 0; break; } if (flags != 0) { if (app) { rdpWindow* window; rdpRail* rail = ((rdpContext*) xfi->context)->rail; window = window_list_get_by_extra_id(rail->list, (void*) event->xbutton.window); if (window != NULL) { x += window->windowOffsetX; y += window->windowOffsetY; } } input->MouseEvent(input, flags, x, y); } return true; } boolean xf_event_KeyPress(xfInfo* xfi, XEvent* event, boolean app) { KeySym keysym; char str[256]; XLookupString((XKeyEvent*) event, str, sizeof(str), &keysym, NULL); xf_kbd_set_keypress(xfi, event->xkey.keycode, keysym); if (xfi->fullscreen_toggle && xf_kbd_handle_special_keys(xfi, keysym)) return true; xf_kbd_send_key(xfi, true, event->xkey.keycode); return true; } boolean xf_event_KeyRelease(xfInfo* xfi, XEvent* event, boolean app) { XEvent next_event; if (XPending(xfi->display)) { memset(&next_event, 0, sizeof(next_event)); XPeekEvent(xfi->display, &next_event); if (next_event.type == KeyPress) { if (next_event.xkey.keycode == event->xkey.keycode) return true; } } xf_kbd_unset_keypress(xfi, event->xkey.keycode); xf_kbd_send_key(xfi, false, event->xkey.keycode); return true; } boolean xf_event_FocusIn(xfInfo* xfi, XEvent* event, boolean app) { if (event->xfocus.mode == NotifyGrab) return true; xfi->focused = true; if (xfi->mouse_active && (app != true)) XGrabKeyboard(xfi->display, xfi->window->handle, true, GrabModeAsync, GrabModeAsync, CurrentTime); if (app) xf_rail_send_activate(xfi, event->xany.window, true); xf_kbd_focus_in(xfi); if (app != true) xf_cliprdr_check_owner(xfi); return true; } boolean xf_event_FocusOut(xfInfo* xfi, XEvent* event, boolean app) { if (event->xfocus.mode == NotifyUngrab) return true; xfi->focused = false; if (event->xfocus.mode == NotifyWhileGrabbed) XUngrabKeyboard(xfi->display, CurrentTime); if (app) xf_rail_send_activate(xfi, event->xany.window, false); return true; } boolean xf_event_MappingNotify(xfInfo* xfi, XEvent* event, boolean app) { if (event->xmapping.request == MappingModifier) { XFreeModifiermap(xfi->modifier_map); xfi->modifier_map = XGetModifierMapping(xfi->display); } return true; } boolean xf_event_ClientMessage(xfInfo* xfi, XEvent* event, boolean app) { if ((event->xclient.message_type == xfi->WM_PROTOCOLS) && ((Atom) event->xclient.data.l[0] == xfi->WM_DELETE_WINDOW)) { if (app) { rdpWindow* window; rdpRail* rail = ((rdpContext*) xfi->context)->rail; window = window_list_get_by_extra_id(rail->list, (void*) event->xclient.window); if (window != NULL) { xf_rail_send_client_system_command(xfi, window->windowId, SC_CLOSE); } return true; } else { return false; } } return true; } boolean xf_event_EnterNotify(xfInfo* xfi, XEvent* event, boolean app) { if (app != true) { xfi->mouse_active = true; if (xfi->fullscreen) XSetInputFocus(xfi->display, xfi->window->handle, RevertToPointerRoot, CurrentTime); if (xfi->focused) XGrabKeyboard(xfi->display, xfi->window->handle, true, GrabModeAsync, GrabModeAsync, CurrentTime); } else { /* keep track of which window has focus so that we can apply pointer updates */ xfWindow* xfw; rdpWindow* window; rdpRail* rail = ((rdpContext*) xfi->context)->rail; window = window_list_get_by_extra_id(rail->list, (void*) event->xexpose.window); if (window != NULL) { xfw = (xfWindow*) window->extra; xfi->window = xfw; } } return true; } boolean xf_event_LeaveNotify(xfInfo* xfi, XEvent* event, boolean app) { if (app != true) { xfi->mouse_active = false; XUngrabKeyboard(xfi->display, CurrentTime); } return true; } boolean xf_event_ConfigureNotify(xfInfo* xfi, XEvent* event, boolean app) { rdpWindow* window; rdpRail* rail = ((rdpContext*) xfi->context)->rail; window = window_list_get_by_extra_id(rail->list, (void*) event->xconfigure.window); if (window != NULL) { xfWindow* xfw; Window childWindow; xfw = (xfWindow*) window->extra; /* * ConfigureNotify coordinates are expressed relative to the window parent. * Translate these to root window coordinates. */ XTranslateCoordinates(xfi->display, xfw->handle, RootWindowOfScreen(xfi->screen), 0, 0, &xfw->left, &xfw->top, &childWindow); xfw->width = event->xconfigure.width; xfw->height = event->xconfigure.height; xfw->right = xfw->left + xfw->width - 1; xfw->bottom = xfw->top + xfw->height - 1; DEBUG_X11_LMS("window=0x%X rc={l=%d t=%d r=%d b=%d} w=%u h=%u send_event=%d", (uint32) xfw->handle, xfw->left, xfw->top, xfw->right, xfw->bottom, xfw->width, xfw->height, event->xconfigure.send_event); if (app && ! event->xconfigure.send_event) xf_rail_adjust_position(xfi, window); } return True; } boolean xf_event_MapNotify(xfInfo* xfi, XEvent* event, boolean app) { rdpWindow* window; rdpRail* rail = ((rdpContext*) xfi->context)->rail; if (app != true) return true; window = window_list_get_by_extra_id(rail->list, (void*) event->xany.window); if (window != NULL) { /* local restore event */ xf_rail_send_client_system_command(xfi, window->windowId, SC_RESTORE); xfWindow *xfw = (xfWindow*) window->extra; xfw->is_mapped = true; } return true; } boolean xf_event_UnmapNotify(xfInfo* xfi, XEvent* event, boolean app) { rdpWindow* window; rdpRail* rail = ((rdpContext*) xfi->context)->rail; if (app != true) return true; window = window_list_get_by_extra_id(rail->list, (void*) event->xany.window); if (window != NULL) { xfWindow *xfw = (xfWindow*) window->extra; xfw->is_mapped = false; } return true; } boolean xf_event_SelectionNotify(xfInfo* xfi, XEvent* event, boolean app) { if (app != true) { if (xf_cliprdr_process_selection_notify(xfi, event)) return true; } return true; } boolean xf_event_SelectionRequest(xfInfo* xfi, XEvent* event, boolean app) { if (app != true) { if (xf_cliprdr_process_selection_request(xfi, event)) return true; } return true; } boolean xf_event_SelectionClear(xfInfo* xfi, XEvent* event, boolean app) { if (app != true) { if (xf_cliprdr_process_selection_clear(xfi, event)) return true; } return true; } boolean xf_event_PropertyNotify(xfInfo* xfi, XEvent* event, boolean app) { if (app != true) { if (xf_cliprdr_process_property_notify(xfi, event)) return true; } return true; } boolean xf_event_suppress_events(xfInfo *xfi, rdpWindow *window, XEvent*event) { if (! xfi->remote_app) return false; switch (xfi->window->local_move.state) { case LMS_NOT_ACTIVE: // No local move in progress, nothing to do break; case LMS_STARTING: // Local move initiated by RDP server, but we // have not yet seen any updates from the X server switch(event->type) { case ConfigureNotify: // Starting to see move events // from the X server. Local // move is now in progress. xfi->window->local_move.state = LMS_ACTIVE; // Allow these events to be processed during move to keep // our state up to date. break; case ButtonPress: case ButtonRelease: case KeyPress: case KeyRelease: case UnmapNotify: // A button release event means the X // window server did not grab the // mouse before the user released it. // In this case we must cancel the // local move. The event will be // processed below as normal, below. break; case VisibilityNotify: case PropertyNotify: case Expose: // Allow these events to pass break; default: // Eat any other events return true; } break; case LMS_ACTIVE: // Local move is in progress switch(event->type) { case ConfigureNotify: case VisibilityNotify: case PropertyNotify: case Expose: // Keep us up to date on position break; default: // Any other event terminates move xf_rail_end_local_move(xfi, window); break; } break; case LMS_TERMINATING: // Already sent RDP end move to sever // Allow events to pass. break; } return false; } boolean xf_event_process(freerdp* instance, XEvent* event) { boolean status = true; xfInfo* xfi = ((xfContext*) instance->context)->xfi; rdpRail* rail = ((rdpContext*) xfi->context)->rail; rdpWindow* window; if (xfi->remote_app) { window = window_list_get_by_extra_id( rail->list, (void*) event->xexpose.window); if (window) { // Update "current" window for cursor change orders xfi->window = (xfWindow *) window->extra; if (xf_event_suppress_events(xfi, window, event)) return true; } } if (event->type != MotionNotify) DEBUG_X11("%s Event: wnd=0x%04X", X11_EVENT_STRINGS[event->type], (uint32) event->xany.window); switch (event->type) { case Expose: status = xf_event_Expose(xfi, event, xfi->remote_app); break; case VisibilityNotify: status = xf_event_VisibilityNotify(xfi, event, xfi->remote_app); break; case MotionNotify: status = xf_event_MotionNotify(xfi, event, xfi->remote_app); break; case ButtonPress: status = xf_event_ButtonPress(xfi, event, xfi->remote_app); break; case ButtonRelease: status = xf_event_ButtonRelease(xfi, event, xfi->remote_app); break; case KeyPress: status = xf_event_KeyPress(xfi, event, xfi->remote_app); break; case KeyRelease: status = xf_event_KeyRelease(xfi, event, xfi->remote_app); break; case FocusIn: status = xf_event_FocusIn(xfi, event, xfi->remote_app); break; case FocusOut: status = xf_event_FocusOut(xfi, event, xfi->remote_app); break; case EnterNotify: status = xf_event_EnterNotify(xfi, event, xfi->remote_app); break; case LeaveNotify: status = xf_event_LeaveNotify(xfi, event, xfi->remote_app); break; case NoExpose: break; case GraphicsExpose: break; case ConfigureNotify: status = xf_event_ConfigureNotify(xfi, event, xfi->remote_app); break; case MapNotify: status = xf_event_MapNotify(xfi, event, xfi->remote_app); break; case UnmapNotify: status = xf_event_UnmapNotify(xfi, event, xfi->remote_app); break; case ReparentNotify: break; case MappingNotify: status = xf_event_MappingNotify(xfi, event, xfi->remote_app); break; case ClientMessage: status = xf_event_ClientMessage(xfi, event, xfi->remote_app); break; case SelectionNotify: status = xf_event_SelectionNotify(xfi, event, xfi->remote_app); break; case SelectionRequest: status = xf_event_SelectionRequest(xfi, event, xfi->remote_app); break; case SelectionClear: status = xf_event_SelectionClear(xfi, event, xfi->remote_app); break; case PropertyNotify: status = xf_event_PropertyNotify(xfi, event, xfi->remote_app); break; } return status; } FreeRDP-1.0.2/client/X11/xf_event.h000066400000000000000000000017251207112532300165600ustar00rootroot00000000000000/** * FreeRDP: A Remote Desktop Protocol Client * X11 Event Handling * * Copyright 2011 Marc-Andre Moreau * * 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. */ #ifndef __XF_EVENT_H #define __XF_EVENT_H #include "xf_keyboard.h" #include "xfreerdp.h" boolean xf_event_process(freerdp* instance, XEvent* event); void xf_event_SendClientEvent(xfInfo *xfi, xfWindow* window, Atom atom, unsigned int numArgs, ...); #endif /* __XF_EVENT_H */ FreeRDP-1.0.2/client/X11/xf_gdi.c000066400000000000000000000510561207112532300161770ustar00rootroot00000000000000/** * FreeRDP: A Remote Desktop Protocol Client * X11 GDI * * Copyright 2011 Marc-Andre Moreau * * 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. */ #include #include #include #include #include #include #include #include #include #include "xf_gdi.h" static const uint8 xf_rop2_table[] = { 0, GXclear, /* 0 */ GXnor, /* DPon */ GXandInverted, /* DPna */ GXcopyInverted, /* Pn */ GXandReverse, /* PDna */ GXinvert, /* Dn */ GXxor, /* DPx */ GXnand, /* DPan */ GXand, /* DPa */ GXequiv, /* DPxn */ GXnoop, /* D */ GXorInverted, /* DPno */ GXcopy, /* P */ GXorReverse, /* PDno */ GXor, /* DPo */ GXset /* 1 */ }; boolean xf_set_rop2(xfInfo* xfi, int rop2) { if ((rop2 < 0x01) || (rop2 > 0x10)) { printf("Unsupported ROP2: %d\n", rop2); return false; } XSetFunction(xfi->display, xfi->gc, xf_rop2_table[rop2]); return true; } boolean xf_set_rop3(xfInfo* xfi, int rop3) { int function = -1; switch (rop3) { case GDI_BLACKNESS: function = GXclear; break; case 0x000500A9: function = GXnor; break; case 0x000A0329: function = GXandInverted; break; case 0x000F0001: function = GXcopyInverted; break; case GDI_NOTSRCERASE: function = GXnor; break; case GDI_DSna: function = GXandInverted; break; case GDI_NOTSRCCOPY: function = GXcopyInverted; break; case GDI_SRCERASE: function = GXandReverse; break; case 0x00500325: function = GXandReverse; break; case GDI_DSTINVERT: function = GXinvert; break; case GDI_PATINVERT: function = GXxor; break; case 0x005F00E9: function = GXnand; break; case GDI_SRCINVERT: function = GXxor; break; case 0x007700E6: function = GXnand; break; case GDI_SRCAND: function = GXand; break; case 0x00990066: function = GXequiv; break; case 0x00A000C9: function = GXand; break; case GDI_PDxn: function = GXequiv; break; case 0x00AA0029: function = GXnoop; break; case 0x00AF0229: function = GXorInverted; break; case GDI_MERGEPAINT: function = GXorInverted; break; case GDI_SRCCOPY: function = GXcopy; break; case 0x00DD0228: function = GXorReverse; break; case GDI_SRCPAINT: function = GXor; break; case GDI_PATCOPY: function = GXcopy; break; case 0x00F50225: function = GXorReverse; break; case 0x00FA0089: function = GXor; break; case GDI_WHITENESS: function = GXset; break; default: break; } if (function < 0) { printf("Unsupported ROP3: 0x%08X\n", rop3); XSetFunction(xfi->display, xfi->gc, GXclear); return false; } XSetFunction(xfi->display, xfi->gc, function); return true; } Pixmap xf_brush_new(xfInfo* xfi, int width, int height, int bpp, uint8* data) { Pixmap bitmap; uint8* cdata; XImage* image; bitmap = XCreatePixmap(xfi->display, xfi->drawable, width, height, xfi->depth); if(data != NULL) { GC gc; // FIXME, should cache cdata = freerdp_image_convert(data, NULL, width, height, bpp, xfi->bpp, xfi->clrconv); image = XCreateImage(xfi->display, xfi->visual, xfi->depth, ZPixmap, 0, (char*) cdata, width, height, xfi->scanline_pad, 0); gc = XCreateGC(xfi->display, xfi->drawable, 0, NULL); XPutImage(xfi->display, bitmap, gc, image, 0, 0, 0, 0, width, height); XFree(image); if (cdata != data) xfree(cdata); XFreeGC(xfi->display, gc); } return bitmap; } Pixmap xf_mono_bitmap_new(xfInfo* xfi, int width, int height, uint8* data) { int scanline; XImage* image; Pixmap bitmap; scanline = (width + 7) / 8; bitmap = XCreatePixmap(xfi->display, xfi->drawable, width, height, 1); image = XCreateImage(xfi->display, xfi->visual, 1, ZPixmap, 0, (char*) data, width, height, 8, scanline); XPutImage(xfi->display, bitmap, xfi->gc_mono, image, 0, 0, 0, 0, width, height); XFree(image); return bitmap; } Pixmap xf_glyph_new(xfInfo* xfi, int width, int height, uint8* data) { int scanline; Pixmap bitmap; XImage* image; scanline = (width + 7) / 8; bitmap = XCreatePixmap(xfi->display, xfi->drawable, width, height, 1); image = XCreateImage(xfi->display, xfi->visual, 1, ZPixmap, 0, (char*) data, width, height, 8, scanline); image->byte_order = MSBFirst; image->bitmap_bit_order = MSBFirst; XInitImage(image); XPutImage(xfi->display, bitmap, xfi->gc_mono, image, 0, 0, 0, 0, width, height); XFree(image); return bitmap; } void xf_gdi_palette_update(rdpContext* context, PALETTE_UPDATE* palette) { xfInfo* xfi = ((xfContext*) context)->xfi; xfi->clrconv->palette->count = palette->number; xfi->clrconv->palette->entries = palette->entries; } void xf_gdi_set_bounds(rdpContext* context, rdpBounds* bounds) { XRectangle clip; xfInfo* xfi = ((xfContext*) context)->xfi; if (bounds != NULL) { clip.x = bounds->left; clip.y = bounds->top; clip.width = bounds->right - bounds->left + 1; clip.height = bounds->bottom - bounds->top + 1; XSetClipRectangles(xfi->display, xfi->gc, 0, 0, &clip, 1, YXBanded); } else { XSetClipMask(xfi->display, xfi->gc, None); } } void xf_gdi_dstblt(rdpContext* context, DSTBLT_ORDER* dstblt) { xfInfo* xfi = ((xfContext*) context)->xfi; xf_set_rop3(xfi, gdi_rop3_code(dstblt->bRop)); XSetFillStyle(xfi->display, xfi->gc, FillSolid); XFillRectangle(xfi->display, xfi->drawing, xfi->gc, dstblt->nLeftRect, dstblt->nTopRect, dstblt->nWidth, dstblt->nHeight); if (xfi->drawing == xfi->primary) { if (xfi->remote_app != true) { XFillRectangle(xfi->display, xfi->drawable, xfi->gc, dstblt->nLeftRect, dstblt->nTopRect, dstblt->nWidth, dstblt->nHeight); } gdi_InvalidateRegion(xfi->hdc, dstblt->nLeftRect, dstblt->nTopRect, dstblt->nWidth, dstblt->nHeight); } XSetFunction(xfi->display, xfi->gc, GXcopy); } void xf_gdi_patblt(rdpContext* context, PATBLT_ORDER* patblt) { Pixmap pattern; rdpBrush* brush; uint32 foreColor; uint32 backColor; xfInfo* xfi = ((xfContext*) context)->xfi; brush = &patblt->brush; xf_set_rop3(xfi, gdi_rop3_code(patblt->bRop)); foreColor = freerdp_color_convert_rgb(patblt->foreColor, xfi->srcBpp, xfi->bpp, xfi->clrconv); backColor = freerdp_color_convert_rgb(patblt->backColor, xfi->srcBpp, xfi->bpp, xfi->clrconv); if (brush->style == GDI_BS_SOLID) { XSetFillStyle(xfi->display, xfi->gc, FillSolid); XSetForeground(xfi->display, xfi->gc, foreColor); XFillRectangle(xfi->display, xfi->drawing, xfi->gc, patblt->nLeftRect, patblt->nTopRect, patblt->nWidth, patblt->nHeight); } else if (brush->style == GDI_BS_PATTERN) { if (brush->bpp > 1) { pattern = xf_brush_new(xfi, 8, 8, brush->bpp, brush->data); XSetFillStyle(xfi->display, xfi->gc, FillTiled); XSetTile(xfi->display, xfi->gc, pattern); XSetTSOrigin(xfi->display, xfi->gc, brush->x, brush->y); XFillRectangle(xfi->display, xfi->drawing, xfi->gc, patblt->nLeftRect, patblt->nTopRect, patblt->nWidth, patblt->nHeight); XSetTile(xfi->display, xfi->gc, xfi->primary); XFreePixmap(xfi->display, pattern); } else { pattern = xf_mono_bitmap_new(xfi, 8, 8, brush->data); XSetForeground(xfi->display, xfi->gc, backColor); XSetBackground(xfi->display, xfi->gc, foreColor); XSetFillStyle(xfi->display, xfi->gc, FillOpaqueStippled); XSetStipple(xfi->display, xfi->gc, pattern); XSetTSOrigin(xfi->display, xfi->gc, brush->x, brush->y); XFillRectangle(xfi->display, xfi->drawing, xfi->gc, patblt->nLeftRect, patblt->nTopRect, patblt->nWidth, patblt->nHeight); XFreePixmap(xfi->display, pattern); } } else { printf("unimplemented brush style:%d\n", brush->style); } if (xfi->drawing == xfi->primary) { XSetFunction(xfi->display, xfi->gc, GXcopy); if (xfi->remote_app != true) { XCopyArea(xfi->display, xfi->primary, xfi->drawable, xfi->gc, patblt->nLeftRect, patblt->nTopRect, patblt->nWidth, patblt->nHeight, patblt->nLeftRect, patblt->nTopRect); } gdi_InvalidateRegion(xfi->hdc, patblt->nLeftRect, patblt->nTopRect, patblt->nWidth, patblt->nHeight); } XSetFunction(xfi->display, xfi->gc, GXcopy); } void xf_gdi_scrblt(rdpContext* context, SCRBLT_ORDER* scrblt) { xfInfo* xfi = ((xfContext*) context)->xfi; xf_set_rop3(xfi, gdi_rop3_code(scrblt->bRop)); XCopyArea(xfi->display, xfi->primary, xfi->drawing, xfi->gc, scrblt->nXSrc, scrblt->nYSrc, scrblt->nWidth, scrblt->nHeight, scrblt->nLeftRect, scrblt->nTopRect); if (xfi->drawing == xfi->primary) { if (xfi->remote_app != true) { if (xfi->unobscured) { XCopyArea(xfi->display, xfi->drawable, xfi->drawable, xfi->gc, scrblt->nXSrc, scrblt->nYSrc, scrblt->nWidth, scrblt->nHeight, scrblt->nLeftRect, scrblt->nTopRect); } else { XSetFunction(xfi->display, xfi->gc, GXcopy); XCopyArea(xfi->display, xfi->primary, xfi->drawable, xfi->gc, scrblt->nLeftRect, scrblt->nTopRect, scrblt->nWidth, scrblt->nHeight, scrblt->nLeftRect, scrblt->nTopRect); } } gdi_InvalidateRegion(xfi->hdc, scrblt->nLeftRect, scrblt->nTopRect, scrblt->nWidth, scrblt->nHeight); } XSetFunction(xfi->display, xfi->gc, GXcopy); } void xf_gdi_opaque_rect(rdpContext* context, OPAQUE_RECT_ORDER* opaque_rect) { uint32 color; xfInfo* xfi = ((xfContext*) context)->xfi; color = freerdp_color_convert_var(opaque_rect->color, xfi->srcBpp, xfi->bpp, xfi->clrconv); XSetFunction(xfi->display, xfi->gc, GXcopy); XSetFillStyle(xfi->display, xfi->gc, FillSolid); XSetForeground(xfi->display, xfi->gc, color); XFillRectangle(xfi->display, xfi->drawing, xfi->gc, opaque_rect->nLeftRect, opaque_rect->nTopRect, opaque_rect->nWidth, opaque_rect->nHeight); if (xfi->drawing == xfi->primary) { if (xfi->remote_app != true) { XFillRectangle(xfi->display, xfi->drawable, xfi->gc, opaque_rect->nLeftRect, opaque_rect->nTopRect, opaque_rect->nWidth, opaque_rect->nHeight); } gdi_InvalidateRegion(xfi->hdc, opaque_rect->nLeftRect, opaque_rect->nTopRect, opaque_rect->nWidth, opaque_rect->nHeight); } } void xf_gdi_multi_opaque_rect(rdpContext* context, MULTI_OPAQUE_RECT_ORDER* multi_opaque_rect) { int i; uint32 color; DELTA_RECT* rectangle; xfInfo* xfi = ((xfContext*) context)->xfi; color = freerdp_color_convert_var(multi_opaque_rect->color, xfi->srcBpp, xfi->bpp, xfi->clrconv); XSetFunction(xfi->display, xfi->gc, GXcopy); XSetFillStyle(xfi->display, xfi->gc, FillSolid); XSetForeground(xfi->display, xfi->gc, color); for (i = 1; i < multi_opaque_rect->numRectangles + 1; i++) { rectangle = &multi_opaque_rect->rectangles[i]; XFillRectangle(xfi->display, xfi->drawing, xfi->gc, rectangle->left, rectangle->top, rectangle->width, rectangle->height); if (xfi->drawing == xfi->primary) { if (xfi->remote_app != true) { XFillRectangle(xfi->display, xfi->drawable, xfi->gc, rectangle->left, rectangle->top, rectangle->width, rectangle->height); } gdi_InvalidateRegion(xfi->hdc, rectangle->left, rectangle->top, rectangle->width, rectangle->height); } } } void xf_gdi_line_to(rdpContext* context, LINE_TO_ORDER* line_to) { uint32 color; xfInfo* xfi = ((xfContext*) context)->xfi; xf_set_rop2(xfi, line_to->bRop2); color = freerdp_color_convert_rgb(line_to->penColor, xfi->srcBpp, xfi->bpp, xfi->clrconv); XSetFillStyle(xfi->display, xfi->gc, FillSolid); XSetForeground(xfi->display, xfi->gc, color); XDrawLine(xfi->display, xfi->drawing, xfi->gc, line_to->nXStart, line_to->nYStart, line_to->nXEnd, line_to->nYEnd); if (xfi->drawing == xfi->primary) { int width, height; if (xfi->remote_app != true) { XDrawLine(xfi->display, xfi->drawable, xfi->gc, line_to->nXStart, line_to->nYStart, line_to->nXEnd, line_to->nYEnd); } width = line_to->nXStart - line_to->nXEnd; height = line_to->nYStart - line_to->nYEnd; if (width < 0) width *= (-1); if (height < 0) height *= (-1); gdi_InvalidateRegion(xfi->hdc, line_to->nXStart, line_to->nYStart, width, height); } XSetFunction(xfi->display, xfi->gc, GXcopy); } void xf_gdi_polyline(rdpContext* context, POLYLINE_ORDER* polyline) { int i; int x, y; int x1, y1; int x2, y2; int npoints; uint32 color; XPoint* points; int width, height; xfInfo* xfi = ((xfContext*) context)->xfi; xf_set_rop2(xfi, polyline->bRop2); color = freerdp_color_convert_rgb(polyline->penColor, xfi->srcBpp, xfi->bpp, xfi->clrconv); XSetFillStyle(xfi->display, xfi->gc, FillSolid); XSetForeground(xfi->display, xfi->gc, color); npoints = polyline->numPoints + 1; points = xmalloc(sizeof(XPoint) * npoints); points[0].x = polyline->xStart; points[0].y = polyline->yStart; for (i = 0; i < polyline->numPoints; i++) { points[i + 1].x = polyline->points[i].x; points[i + 1].y = polyline->points[i].y; } XDrawLines(xfi->display, xfi->drawing, xfi->gc, points, npoints, CoordModePrevious); if (xfi->drawing == xfi->primary) { if (xfi->remote_app != true) XDrawLines(xfi->display, xfi->drawable, xfi->gc, points, npoints, CoordModePrevious); x1 = points[0].x; y1 = points[0].y; for (i = 1; i < npoints; i++) { x2 = points[i].x + x1; y2 = points[i].y + y1; x = (x2 < x1) ? x2 : x1; width = (x2 > x1) ? x2 - x1 : x1 - x2; y = (y2 < y1) ? y2 : y1; height = (y2 > y1) ? y2 - y1 : y1 - y2; x1 = x2; y1 = y2; gdi_InvalidateRegion(xfi->hdc, x, y, width, height); } } XSetFunction(xfi->display, xfi->gc, GXcopy); xfree(points); } void xf_gdi_memblt(rdpContext* context, MEMBLT_ORDER* memblt) { xfBitmap* bitmap; xfInfo* xfi = ((xfContext*) context)->xfi; bitmap = (xfBitmap*) memblt->bitmap; xf_set_rop3(xfi, gdi_rop3_code(memblt->bRop)); XCopyArea(xfi->display, bitmap->pixmap, xfi->drawing, xfi->gc, memblt->nXSrc, memblt->nYSrc, memblt->nWidth, memblt->nHeight, memblt->nLeftRect, memblt->nTopRect); if (xfi->drawing == xfi->primary) { if (xfi->remote_app != true) { XCopyArea(xfi->display, bitmap->pixmap, xfi->drawable, xfi->gc, memblt->nXSrc, memblt->nYSrc, memblt->nWidth, memblt->nHeight, memblt->nLeftRect, memblt->nTopRect); } gdi_InvalidateRegion(xfi->hdc, memblt->nLeftRect, memblt->nTopRect, memblt->nWidth, memblt->nHeight); } XSetFunction(xfi->display, xfi->gc, GXcopy); } void xf_gdi_mem3blt(rdpContext* context, MEM3BLT_ORDER* mem3blt) { } void xf_gdi_surface_frame_marker(rdpContext* context, SURFACE_FRAME_MARKER* surface_frame_marker) { } void xf_gdi_surface_bits(rdpContext* context, SURFACE_BITS_COMMAND* surface_bits_command) { int i, tx, ty; XImage* image; RFX_MESSAGE* message; xfInfo* xfi = ((xfContext*) context)->xfi; RFX_CONTEXT* rfx_context = (RFX_CONTEXT*) xfi->rfx_context; NSC_CONTEXT* nsc_context = (NSC_CONTEXT*) xfi->nsc_context; if (surface_bits_command->codecID == CODEC_ID_REMOTEFX) { message = rfx_process_message(rfx_context, surface_bits_command->bitmapData, surface_bits_command->bitmapDataLength); XSetFunction(xfi->display, xfi->gc, GXcopy); XSetFillStyle(xfi->display, xfi->gc, FillSolid); XSetClipRectangles(xfi->display, xfi->gc, surface_bits_command->destLeft, surface_bits_command->destTop, (XRectangle*) message->rects, message->num_rects, YXBanded); /* Draw the tiles to primary surface, each is 64x64. */ for (i = 0; i < message->num_tiles; i++) { image = XCreateImage(xfi->display, xfi->visual, 24, ZPixmap, 0, (char*) message->tiles[i]->data, 64, 64, 32, 0); tx = message->tiles[i]->x + surface_bits_command->destLeft; ty = message->tiles[i]->y + surface_bits_command->destTop; XPutImage(xfi->display, xfi->primary, xfi->gc, image, 0, 0, tx, ty, 64, 64); XFree(image); } /* Copy the updated region from backstore to the window. */ for (i = 0; i < message->num_rects; i++) { tx = message->rects[i].x + surface_bits_command->destLeft; ty = message->rects[i].y + surface_bits_command->destTop; if (xfi->remote_app != true) { XCopyArea(xfi->display, xfi->primary, xfi->drawable, xfi->gc, tx, ty, message->rects[i].width, message->rects[i].height, tx, ty); } gdi_InvalidateRegion(xfi->hdc, tx, ty, message->rects[i].width, message->rects[i].height); } XSetClipMask(xfi->display, xfi->gc, None); rfx_message_free(rfx_context, message); } else if (surface_bits_command->codecID == CODEC_ID_NSCODEC) { nsc_context->width = surface_bits_command->width; nsc_context->height = surface_bits_command->height; nsc_process_message(nsc_context, surface_bits_command->bitmapData, surface_bits_command->bitmapDataLength); XSetFunction(xfi->display, xfi->gc, GXcopy); XSetFillStyle(xfi->display, xfi->gc, FillSolid); xfi->bmp_codec_nsc = (uint8*) xrealloc(xfi->bmp_codec_nsc, surface_bits_command->width * surface_bits_command->height * 4); freerdp_image_flip(nsc_context->bmpdata, xfi->bmp_codec_nsc, surface_bits_command->width, surface_bits_command->height, 32); image = XCreateImage(xfi->display, xfi->visual, 24, ZPixmap, 0, (char*) xfi->bmp_codec_nsc, surface_bits_command->width, surface_bits_command->height, 32, 0); XPutImage(xfi->display, xfi->primary, xfi->gc, image, 0, 0, surface_bits_command->destLeft, surface_bits_command->destTop, surface_bits_command->width, surface_bits_command->height); if (xfi->remote_app != true) { XCopyArea(xfi->display, xfi->primary, xfi->window->handle, xfi->gc, surface_bits_command->destLeft, surface_bits_command->destTop, surface_bits_command->width, surface_bits_command->height, surface_bits_command->destLeft, surface_bits_command->destTop); } gdi_InvalidateRegion(xfi->hdc, surface_bits_command->destLeft, surface_bits_command->destTop, surface_bits_command->width, surface_bits_command->height); XSetClipMask(xfi->display, xfi->gc, None); nsc_context_destroy(nsc_context); } else if (surface_bits_command->codecID == CODEC_ID_NONE) { XSetFunction(xfi->display, xfi->gc, GXcopy); XSetFillStyle(xfi->display, xfi->gc, FillSolid); xfi->bmp_codec_none = (uint8*) xrealloc(xfi->bmp_codec_none, surface_bits_command->width * surface_bits_command->height * 4); freerdp_image_flip(surface_bits_command->bitmapData, xfi->bmp_codec_none, surface_bits_command->width, surface_bits_command->height, 32); image = XCreateImage(xfi->display, xfi->visual, 24, ZPixmap, 0, (char*) xfi->bmp_codec_none, surface_bits_command->width, surface_bits_command->height, 32, 0); XPutImage(xfi->display, xfi->primary, xfi->gc, image, 0, 0, surface_bits_command->destLeft, surface_bits_command->destTop, surface_bits_command->width, surface_bits_command->height); if (xfi->remote_app != true) { XCopyArea(xfi->display, xfi->primary, xfi->window->handle, xfi->gc, surface_bits_command->destLeft, surface_bits_command->destTop, surface_bits_command->width, surface_bits_command->height, surface_bits_command->destLeft, surface_bits_command->destTop); } gdi_InvalidateRegion(xfi->hdc, surface_bits_command->destLeft, surface_bits_command->destTop, surface_bits_command->width, surface_bits_command->height); XSetClipMask(xfi->display, xfi->gc, None); } else { printf("Unsupported codecID %d\n", surface_bits_command->codecID); } } void xf_gdi_register_update_callbacks(rdpUpdate* update) { rdpPrimaryUpdate* primary = update->primary; update->Palette = xf_gdi_palette_update; update->SetBounds = xf_gdi_set_bounds; primary->DstBlt = xf_gdi_dstblt; primary->PatBlt = xf_gdi_patblt; primary->ScrBlt = xf_gdi_scrblt; primary->OpaqueRect = xf_gdi_opaque_rect; primary->DrawNineGrid = NULL; primary->MultiDstBlt = NULL; primary->MultiPatBlt = NULL; primary->MultiScrBlt = NULL; primary->MultiOpaqueRect = xf_gdi_multi_opaque_rect; primary->MultiDrawNineGrid = NULL; primary->LineTo = xf_gdi_line_to; primary->Polyline = xf_gdi_polyline; primary->MemBlt = xf_gdi_memblt; primary->Mem3Blt = xf_gdi_mem3blt; primary->SaveBitmap = NULL; primary->GlyphIndex = NULL; primary->FastIndex = NULL; primary->FastGlyph = NULL; primary->PolygonSC = NULL; primary->PolygonCB = NULL; primary->EllipseSC = NULL; primary->EllipseCB = NULL; update->SurfaceBits = xf_gdi_surface_bits; update->SurfaceFrameMarker = xf_gdi_surface_frame_marker; } FreeRDP-1.0.2/client/X11/xf_gdi.h000066400000000000000000000015421207112532300161770ustar00rootroot00000000000000/** * FreeRDP: A Remote Desktop Protocol Client * X11 GDI * * Copyright 2011 Marc-Andre Moreau * * 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. */ #ifndef __XF_GDI_H #define __XF_GDI_H #include #include "xfreerdp.h" void xf_gdi_register_update_callbacks(rdpUpdate* update); #endif /* __XF_GDI_H */ FreeRDP-1.0.2/client/X11/xf_graphics.c000066400000000000000000000206201207112532300172250ustar00rootroot00000000000000/** * FreeRDP: A Remote Desktop Protocol Client * X11 Graphical Objects * * Copyright 2011 Marc-Andre Moreau * * 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. */ #include #include #ifdef WITH_XCURSOR #include #endif #include #include "xf_graphics.h" /* Bitmap Class */ void xf_Bitmap_New(rdpContext* context, rdpBitmap* bitmap) { uint8* data; Pixmap pixmap; XImage* image; xfInfo* xfi = ((xfContext*) context)->xfi; XSetFunction(xfi->display, xfi->gc, GXcopy); pixmap = XCreatePixmap(xfi->display, xfi->drawable, bitmap->width, bitmap->height, xfi->depth); if (bitmap->data != NULL) { data = freerdp_image_convert(bitmap->data, NULL, bitmap->width, bitmap->height, xfi->srcBpp, xfi->bpp, xfi->clrconv); if (bitmap->ephemeral != true) { image = XCreateImage(xfi->display, xfi->visual, xfi->depth, ZPixmap, 0, (char*) data, bitmap->width, bitmap->height, xfi->scanline_pad, 0); XPutImage(xfi->display, pixmap, xfi->gc, image, 0, 0, 0, 0, bitmap->width, bitmap->height); XFree(image); if (data != bitmap->data) xfree(data); } else { if (data != bitmap->data) xfree(bitmap->data); bitmap->data = data; } } ((xfBitmap*) bitmap)->pixmap = pixmap; } void xf_Bitmap_Free(rdpContext* context, rdpBitmap* bitmap) { xfInfo* xfi = ((xfContext*) context)->xfi; if (((xfBitmap*) bitmap)->pixmap != 0) XFreePixmap(xfi->display, ((xfBitmap*) bitmap)->pixmap); } void xf_Bitmap_Paint(rdpContext* context, rdpBitmap* bitmap) { XImage* image; int width, height; xfInfo* xfi = ((xfContext*) context)->xfi; width = bitmap->right - bitmap->left + 1; height = bitmap->bottom - bitmap->top + 1; XSetFunction(xfi->display, xfi->gc, GXcopy); image = XCreateImage(xfi->display, xfi->visual, xfi->depth, ZPixmap, 0, (char*) bitmap->data, bitmap->width, bitmap->height, xfi->scanline_pad, 0); XPutImage(xfi->display, xfi->primary, xfi->gc, image, 0, 0, bitmap->left, bitmap->top, width, height); XFree(image); if (xfi->remote_app != true) { XCopyArea(xfi->display, xfi->primary, xfi->drawable, xfi->gc, bitmap->left, bitmap->top, width, height, bitmap->left, bitmap->top); } gdi_InvalidateRegion(xfi->hdc, bitmap->left, bitmap->top, width, height); } void xf_Bitmap_Decompress(rdpContext* context, rdpBitmap* bitmap, uint8* data, int width, int height, int bpp, int length, boolean compressed) { uint16 size; size = width * height * (bpp + 7) / 8; if (bitmap->data == NULL) bitmap->data = (uint8*) xmalloc(size); else bitmap->data = (uint8*) xrealloc(bitmap->data, size); if (compressed) { boolean status; status = bitmap_decompress(data, bitmap->data, width, height, length, bpp, bpp); if (status != true) { printf("Bitmap Decompression Failed\n"); } } else { freerdp_image_flip(data, bitmap->data, width, height, bpp); } bitmap->compressed = false; bitmap->length = size; bitmap->bpp = bpp; } void xf_Bitmap_SetSurface(rdpContext* context, rdpBitmap* bitmap, boolean primary) { xfInfo* xfi = ((xfContext*) context)->xfi; if (primary) xfi->drawing = xfi->primary; else xfi->drawing = ((xfBitmap*) bitmap)->pixmap; } /* Pointer Class */ void xf_Pointer_New(rdpContext* context, rdpPointer* pointer) { XcursorImage ci; xfInfo* xfi = ((xfContext*) context)->xfi; memset(&ci, 0, sizeof(ci)); ci.version = XCURSOR_IMAGE_VERSION; ci.size = sizeof(ci); ci.width = pointer->width; ci.height = pointer->height; ci.xhot = pointer->xPos; ci.yhot = pointer->yPos; ci.pixels = (XcursorPixel*) malloc(ci.width * ci.height * 4); memset(ci.pixels, 0, ci.width * ci.height * 4); if ((pointer->andMaskData != 0) && (pointer->xorMaskData != 0)) { freerdp_alpha_cursor_convert((uint8*) (ci.pixels), pointer->xorMaskData, pointer->andMaskData, pointer->width, pointer->height, pointer->xorBpp, xfi->clrconv); } ((xfPointer*) pointer)->cursor = XcursorImageLoadCursor(xfi->display, &ci); xfree(ci.pixels); } void xf_Pointer_Free(rdpContext* context, rdpPointer* pointer) { xfInfo* xfi = ((xfContext*) context)->xfi; if (((xfPointer*) pointer)->cursor != 0) XFreeCursor(xfi->display, ((xfPointer*) pointer)->cursor); } void xf_Pointer_Set(rdpContext* context, rdpPointer* pointer) { xfInfo* xfi = ((xfContext*) context)->xfi; /* in RemoteApp mode, window can be null if none has had focus */ if (xfi->window != NULL) XDefineCursor(xfi->display, xfi->window->handle, ((xfPointer*) pointer)->cursor); } /* Glyph Class */ void xf_Glyph_New(rdpContext* context, rdpGlyph* glyph) { xfInfo* xfi; int scanline; XImage* image; xfGlyph* xf_glyph; xf_glyph = (xfGlyph*) glyph; xfi = ((xfContext*) context)->xfi; scanline = (glyph->cx + 7) / 8; xf_glyph->pixmap = XCreatePixmap(xfi->display, xfi->drawing, glyph->cx, glyph->cy, 1); image = XCreateImage(xfi->display, xfi->visual, 1, ZPixmap, 0, (char*) glyph->aj, glyph->cx, glyph->cy, 8, scanline); image->byte_order = MSBFirst; image->bitmap_bit_order = MSBFirst; XInitImage(image); XPutImage(xfi->display, xf_glyph->pixmap, xfi->gc_mono, image, 0, 0, 0, 0, glyph->cx, glyph->cy); XFree(image); } void xf_Glyph_Free(rdpContext* context, rdpGlyph* glyph) { xfInfo* xfi = ((xfContext*) context)->xfi; if (((xfGlyph*) glyph)->pixmap != 0) XFreePixmap(xfi->display, ((xfGlyph*) glyph)->pixmap); } void xf_Glyph_Draw(rdpContext* context, rdpGlyph* glyph, int x, int y) { xfGlyph* xf_glyph; xfInfo* xfi = ((xfContext*) context)->xfi; xf_glyph = (xfGlyph*) glyph; XSetStipple(xfi->display, xfi->gc, xf_glyph->pixmap); XSetTSOrigin(xfi->display, xfi->gc, x, y); XFillRectangle(xfi->display, xfi->drawing, xfi->gc, x, y, glyph->cx, glyph->cy); XSetStipple(xfi->display, xfi->gc, xfi->bitmap_mono); } void xf_Glyph_BeginDraw(rdpContext* context, int x, int y, int width, int height, uint32 bgcolor, uint32 fgcolor) { xfInfo* xfi = ((xfContext*) context)->xfi; bgcolor = (xfi->clrconv->invert)? freerdp_color_convert_var_bgr(bgcolor, xfi->srcBpp, 32, xfi->clrconv): freerdp_color_convert_var_rgb(bgcolor, xfi->srcBpp, 32, xfi->clrconv); fgcolor = (xfi->clrconv->invert)? freerdp_color_convert_var_bgr(fgcolor, xfi->srcBpp, 32, xfi->clrconv): freerdp_color_convert_var_rgb(fgcolor, xfi->srcBpp, 32, xfi->clrconv); XSetFunction(xfi->display, xfi->gc, GXcopy); XSetFillStyle(xfi->display, xfi->gc, FillSolid); XSetForeground(xfi->display, xfi->gc, fgcolor); XFillRectangle(xfi->display, xfi->drawing, xfi->gc, x, y, width, height); XSetForeground(xfi->display, xfi->gc, bgcolor); XSetBackground(xfi->display, xfi->gc, fgcolor); XSetFillStyle(xfi->display, xfi->gc, FillStippled); } void xf_Glyph_EndDraw(rdpContext* context, int x, int y, int width, int height, uint32 bgcolor, uint32 fgcolor) { xfInfo* xfi = ((xfContext*) context)->xfi; if (xfi->drawing == xfi->primary) { if (xfi->remote_app != true) { XCopyArea(xfi->display, xfi->primary, xfi->drawable, xfi->gc, x, y, width, height, x, y); } gdi_InvalidateRegion(xfi->hdc, x, y, width, height); } } /* Graphics Module */ void xf_register_graphics(rdpGraphics* graphics) { rdpBitmap* bitmap; rdpPointer* pointer; rdpGlyph* glyph; bitmap = xnew(rdpBitmap); bitmap->size = sizeof(xfBitmap); bitmap->New = xf_Bitmap_New; bitmap->Free = xf_Bitmap_Free; bitmap->Paint = xf_Bitmap_Paint; bitmap->Decompress = xf_Bitmap_Decompress; bitmap->SetSurface = xf_Bitmap_SetSurface; graphics_register_bitmap(graphics, bitmap); xfree(bitmap); pointer = xnew(rdpPointer); pointer->size = sizeof(xfPointer); pointer->New = xf_Pointer_New; pointer->Free = xf_Pointer_Free; pointer->Set = xf_Pointer_Set; graphics_register_pointer(graphics, pointer); xfree(pointer); glyph = xnew(rdpGlyph); glyph->size = sizeof(xfGlyph); glyph->New = xf_Glyph_New; glyph->Free = xf_Glyph_Free; glyph->Draw = xf_Glyph_Draw; glyph->BeginDraw = xf_Glyph_BeginDraw; glyph->EndDraw = xf_Glyph_EndDraw; graphics_register_glyph(graphics, glyph); xfree(glyph); } FreeRDP-1.0.2/client/X11/xf_graphics.h000066400000000000000000000015311207112532300172320ustar00rootroot00000000000000/** * FreeRDP: A Remote Desktop Protocol Client * X11 Graphical Objects * * Copyright 2011 Marc-Andre Moreau * * 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. */ #ifndef __XF_GRAPHICS_H #define __XF_GRAPHICS_H #include "xfreerdp.h" void xf_register_graphics(rdpGraphics* graphics); #endif /* __XF_GRAPHICS_H */ FreeRDP-1.0.2/client/X11/xf_keyboard.c000066400000000000000000000116141207112532300172300ustar00rootroot00000000000000/** * FreeRDP: A Remote Desktop Protocol Client * X11 Keyboard Handling * * Copyright 2011 Marc-Andre Moreau * * 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. */ #include #include #include #include #include #include #include "xf_keyboard.h" void xf_kbd_init(xfInfo* xfi) { memset(xfi->pressed_keys, 0, 256 * sizeof(boolean)); xfi->keyboard_layout_id = xfi->instance->settings->kbd_layout; xfi->keyboard_layout_id = freerdp_kbd_init(xfi->display, xfi->keyboard_layout_id); xfi->instance->settings->kbd_layout = xfi->keyboard_layout_id; } void xf_kbd_set_keypress(xfInfo* xfi, uint8 keycode, KeySym keysym) { if (keycode >= 8) xfi->pressed_keys[keycode] = keysym; else return; } void xf_kbd_unset_keypress(xfInfo* xfi, uint8 keycode) { if (keycode >= 8) xfi->pressed_keys[keycode] = NoSymbol; else return; } boolean xf_kbd_key_pressed(xfInfo* xfi, KeySym keysym) { KeyCode keycode = XKeysymToKeycode(xfi->display, keysym); return (xfi->pressed_keys[keycode] == keysym); } void xf_kbd_send_key(xfInfo* xfi, boolean down, uint8 keycode) { uint16 flags; uint8 scancode; boolean extended; rdpInput* input; input = xfi->instance->input; scancode = freerdp_kbd_get_scancode_by_keycode(keycode, &extended); if (scancode == 0) { /* unknown key */ } else if ((scancode == 0x46) && extended && !xf_kbd_key_pressed(xfi, XK_Control_L) && !xf_kbd_key_pressed(xfi, XK_Control_R)) { /* Pause without Ctrl has to be sent as Ctrl + NumLock. */ if (down) { input->KeyboardEvent(input, KBD_FLAGS_DOWN, 0x1D); /* Ctrl down */ input->KeyboardEvent(input, KBD_FLAGS_DOWN, 0x45); /* NumLock down */ input->KeyboardEvent(input, KBD_FLAGS_RELEASE, 0x1D); /* Ctrl up */ input->KeyboardEvent(input, KBD_FLAGS_RELEASE, 0x45); /* NumLock up */ } } else { flags = (extended) ? KBD_FLAGS_EXTENDED : 0; flags |= (down) ? KBD_FLAGS_DOWN : KBD_FLAGS_RELEASE; input->KeyboardEvent(input, flags, scancode); if ((scancode == 0x3A) && (down == false)) /* caps lock was released */ { uint32 syncFlags; syncFlags = xf_kbd_get_toggle_keys_state(xfi); input->SynchronizeEvent(input, syncFlags); } } } int xf_kbd_read_keyboard_state(xfInfo* xfi) { int dummy; Window wdummy; uint32 state = 0; if (xfi->remote_app != true) { XQueryPointer(xfi->display, xfi->window->handle, &wdummy, &wdummy, &dummy, &dummy, &dummy, &dummy, &state); } else { XQueryPointer(xfi->display, DefaultRootWindow(xfi->display), &wdummy, &wdummy, &dummy, &dummy, &dummy, &dummy, &state); } return state; } boolean xf_kbd_get_key_state(xfInfo* xfi, int state, int keysym) { int offset; int modifierpos, key, keysymMask = 0; KeyCode keycode = XKeysymToKeycode(xfi->display, keysym); if (keycode == NoSymbol) return false; for (modifierpos = 0; modifierpos < 8; modifierpos++) { offset = xfi->modifier_map->max_keypermod * modifierpos; for (key = 0; key < xfi->modifier_map->max_keypermod; key++) { if (xfi->modifier_map->modifiermap[offset + key] == keycode) { keysymMask |= 1 << modifierpos; } } } return (state & keysymMask) ? true : false; } int xf_kbd_get_toggle_keys_state(xfInfo* xfi) { int state; int toggle_keys_state = 0; state = xf_kbd_read_keyboard_state(xfi); if (xf_kbd_get_key_state(xfi, state, XK_Scroll_Lock)) toggle_keys_state |= KBD_SYNC_SCROLL_LOCK; if (xf_kbd_get_key_state(xfi, state, XK_Num_Lock)) toggle_keys_state |= KBD_SYNC_NUM_LOCK; if (xf_kbd_get_key_state(xfi, state, XK_Caps_Lock)) toggle_keys_state |= KBD_SYNC_CAPS_LOCK; if (xf_kbd_get_key_state(xfi, state, XK_Kana_Lock)) toggle_keys_state |= KBD_SYNC_KANA_LOCK; return toggle_keys_state; } void xf_kbd_focus_in(xfInfo* xfi) { rdpInput* input; uint32 syncFlags; input = xfi->instance->input; /* on focus in send a tab up like mstsc.exe */ input->KeyboardEvent(input, KBD_FLAGS_RELEASE, 0x0F); /* synchronize toggle keys */ syncFlags = xf_kbd_get_toggle_keys_state(xfi); input->SynchronizeEvent(input, syncFlags); } boolean xf_kbd_handle_special_keys(xfInfo* xfi, KeySym keysym) { if (keysym == XK_Return) { if ((xf_kbd_key_pressed(xfi, XK_Alt_L) || xf_kbd_key_pressed(xfi, XK_Alt_R)) && (xf_kbd_key_pressed(xfi, XK_Control_L) || xf_kbd_key_pressed(xfi, XK_Control_R))) { /* Ctrl-Alt-Enter: toggle full screen */ xf_toggle_fullscreen(xfi); return true; } } return false; } FreeRDP-1.0.2/client/X11/xf_keyboard.h000066400000000000000000000025731207112532300172410ustar00rootroot00000000000000/** * FreeRDP: A Remote Desktop Protocol Client * X11 Keyboard Handling * * Copyright 2011 Marc-Andre Moreau * * 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. */ #ifndef __XF_KEYBOARD_H #define __XF_KEYBOARD_H #include #include #include "xfreerdp.h" void xf_kbd_init(xfInfo* xfi); void xf_kbd_set_keypress(xfInfo* xfi, uint8 keycode, KeySym keysym); void xf_kbd_unset_keypress(xfInfo* xfi, uint8 keycode); boolean xf_kbd_key_pressed(xfInfo* xfi, KeySym keysym); void xf_kbd_send_key(xfInfo* xfi, boolean down, uint8 keycode); int xf_kbd_read_keyboard_state(xfInfo* xfi); boolean xf_kbd_get_key_state(xfInfo* xfi, int state, int keysym); int xf_kbd_get_toggle_keys_state(xfInfo* xfi); void xf_kbd_focus_in(xfInfo* xfi); boolean xf_kbd_handle_special_keys(xfInfo* xfi, KeySym keysym); #endif /* __XF_KEYBOARD_H */ FreeRDP-1.0.2/client/X11/xf_monitor.c000066400000000000000000000073671207112532300171310ustar00rootroot00000000000000/** * FreeRDP: A Remote Desktop Protocol Client * X11 Monitor Handling * * Copyright 2011 Marc-Andre Moreau * * 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. */ #include #include #include #include #include #ifdef WITH_XINERAMA #include #endif #include "xf_monitor.h" /* See MSDN Section on Multiple Display Monitors: http://msdn.microsoft.com/en-us/library/dd145071 */ boolean xf_detect_monitors(xfInfo* xfi, rdpSettings* settings) { int i; VIRTUAL_SCREEN* vscreen; #ifdef WITH_XINERAMA int ignored, ignored2; XineramaScreenInfo* screen_info = NULL; #endif vscreen = &xfi->vscreen; if (xf_GetWorkArea(xfi) != true) { xfi->workArea.x = 0; xfi->workArea.y = 0; xfi->workArea.width = WidthOfScreen(xfi->screen); xfi->workArea.height = HeightOfScreen(xfi->screen); } if (settings->fullscreen) { settings->width = WidthOfScreen(xfi->screen); settings->height = HeightOfScreen(xfi->screen); } else if (settings->workarea) { settings->width = xfi->workArea.width; settings->height = xfi->workArea.height; } else if (settings->percent_screen) { settings->width = (xfi->workArea.width * settings->percent_screen) / 100; settings->height = (xfi->workArea.height * settings->percent_screen) / 100; } if (settings->fullscreen != true && settings->workarea != true) return true; #ifdef WITH_XINERAMA if (XineramaQueryExtension(xfi->display, &ignored, &ignored2)) { if (XineramaIsActive(xfi->display)) { screen_info = XineramaQueryScreens(xfi->display, &vscreen->nmonitors); if (vscreen->nmonitors > 16) vscreen->nmonitors = 0; vscreen->monitors = xzalloc(sizeof(MONITOR_INFO) * vscreen->nmonitors); if (vscreen->nmonitors) { for (i = 0; i < vscreen->nmonitors; i++) { vscreen->monitors[i].area.left = screen_info[i].x_org; vscreen->monitors[i].area.top = screen_info[i].y_org; vscreen->monitors[i].area.right = screen_info[i].x_org + screen_info[i].width - 1; vscreen->monitors[i].area.bottom = screen_info[i].y_org + screen_info[i].height - 1; if ((screen_info[i].x_org == 0) && (screen_info[i].y_org == 0)) vscreen->monitors[i].primary = true; } } XFree(screen_info); } } #endif settings->num_monitors = vscreen->nmonitors; for (i = 0; i < vscreen->nmonitors; i++) { settings->monitors[i].x = vscreen->monitors[i].area.left; settings->monitors[i].y = vscreen->monitors[i].area.top; settings->monitors[i].width = vscreen->monitors[i].area.right - vscreen->monitors[i].area.left + 1; settings->monitors[i].height = vscreen->monitors[i].area.bottom - vscreen->monitors[i].area.top + 1; settings->monitors[i].is_primary = vscreen->monitors[i].primary; vscreen->area.left = MIN(vscreen->monitors[i].area.left, vscreen->area.left); vscreen->area.right = MAX(vscreen->monitors[i].area.right, vscreen->area.right); vscreen->area.top = MIN(vscreen->monitors[i].area.top, vscreen->area.top); vscreen->area.bottom = MAX(vscreen->monitors[i].area.bottom, vscreen->area.bottom); } if (settings->num_monitors) { settings->width = vscreen->area.right - vscreen->area.left + 1; settings->height = vscreen->area.bottom - vscreen->area.top + 1; } return true; } FreeRDP-1.0.2/client/X11/xf_monitor.h000066400000000000000000000023051207112532300171210ustar00rootroot00000000000000/** * FreeRDP: A Remote Desktop Protocol Client * X11 Monitor Handling * * Copyright 2011 Marc-Andre Moreau * * 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. */ #ifndef __XF_MONITOR_H #define __XF_MONITOR_H #include #include struct _MONITOR_INFO { RECTANGLE_16 area; RECTANGLE_16 workarea; boolean primary; }; typedef struct _MONITOR_INFO MONITOR_INFO; struct _VIRTUAL_SCREEN { int nmonitors; RECTANGLE_16 area; RECTANGLE_16 workarea; MONITOR_INFO* monitors; }; typedef struct _VIRTUAL_SCREEN VIRTUAL_SCREEN; #include "xfreerdp.h" boolean xf_detect_monitors(xfInfo* xfi, rdpSettings* settings); #endif /* __XF_MONITOR_H */ FreeRDP-1.0.2/client/X11/xf_rail.c000066400000000000000000000414021207112532300163550ustar00rootroot00000000000000/** * FreeRDP: A Remote Desktop Protocol Client * X11 RAIL * * Copyright 2011 Marc-Andre Moreau * * 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. */ #include #include #include #include #include #include #include "xf_window.h" #include "xf_rail.h" void xf_rail_enable_remoteapp_mode(xfInfo* xfi) { if (xfi->remote_app == false) { xfi->remote_app = true; xfi->drawable = DefaultRootWindow(xfi->display); xf_DestroyWindow(xfi, xfi->window); xfi->window = NULL; } } void xf_rail_paint(xfInfo* xfi, rdpRail* rail, sint32 uleft, sint32 utop, uint32 uright, uint32 ubottom) { xfWindow* xfw; rdpWindow* window; boolean intersect; uint32 iwidth, iheight; sint32 ileft, itop; uint32 iright, ibottom; sint32 wleft, wtop; uint32 wright, wbottom; window_list_rewind(rail->list); while (window_list_has_next(rail->list)) { window = window_list_get_next(rail->list); xfw = (xfWindow*) window->extra; // RDP can have zero width or height windows. X cannot, so we ignore these. if (window->windowWidth == 0 || window->windowHeight == 0) { continue; } wleft = window->windowOffsetX; wtop = window->windowOffsetY; wright = window->windowOffsetX + window->windowWidth - 1; wbottom = window->windowOffsetY + window->windowHeight - 1; ileft = MAX(uleft, wleft); itop = MAX(utop, wtop); iright = MIN(uright, wright); ibottom = MIN(ubottom, wbottom); iwidth = iright - ileft + 1; iheight = ibottom - itop + 1; intersect = ((iright > ileft) && (ibottom > itop)) ? true : false; if (intersect) { xf_UpdateWindowArea(xfi, xfw, ileft - wleft, itop - wtop, iwidth, iheight); } } } void xf_rail_CreateWindow(rdpRail* rail, rdpWindow* window) { xfInfo* xfi; xfWindow* xfw; xfi = (xfInfo*) rail->extra; xf_rail_enable_remoteapp_mode(xfi); xfw = xf_CreateWindow((xfInfo*) rail->extra, window, window->windowOffsetX, window->windowOffsetY, window->windowWidth, window->windowHeight, window->windowId); xf_SetWindowStyle(xfi, xfw, window->style, window->extendedStyle); XStoreName(xfi->display, xfw->handle, window->title); window->extra = (void*) xfw; window->extraId = (void*) xfw->handle; } void xf_rail_MoveWindow(rdpRail* rail, rdpWindow* window) { xfInfo* xfi; xfWindow* xfw; xfi = (xfInfo*) rail->extra; xfw = (xfWindow*) window->extra; // Do nothing if window is already in the correct position if ( xfw->left == window->windowOffsetX && xfw->top == window->windowOffsetY && xfw->width == window->windowWidth && xfw->height == window->windowHeight) { return; } xf_MoveWindow((xfInfo*) rail->extra, xfw, window->windowOffsetX, window->windowOffsetY, window->windowWidth, window->windowHeight); } void xf_rail_ShowWindow(rdpRail* rail, rdpWindow* window, uint8 state) { xfInfo* xfi; xfWindow* xfw; xfi = (xfInfo*) rail->extra; xfw = (xfWindow*) window->extra; xf_ShowWindow((xfInfo*) rail->extra, xfw, state); } void xf_rail_SetWindowText(rdpRail* rail, rdpWindow* window) { xfInfo* xfi; xfWindow* xfw; xfi = (xfInfo*) rail->extra; xfw = (xfWindow*) window->extra; XStoreName(xfi->display, xfw->handle, window->title); } void xf_rail_SetWindowIcon(rdpRail* rail, rdpWindow* window, rdpIcon* icon) { xfInfo* xfi; xfWindow* xfw; xfi = (xfInfo*) rail->extra; xfw = (xfWindow*) window->extra; icon->extra = freerdp_icon_convert(icon->entry->bitsColor, NULL, icon->entry->bitsMask, icon->entry->width, icon->entry->height, icon->entry->bpp, rail->clrconv); xf_SetWindowIcon(xfi, xfw, icon); } void xf_rail_SetWindowRects(rdpRail* rail, rdpWindow* window) { xfInfo* xfi; xfWindow* xfw; xfi = (xfInfo*) rail->extra; xfw = (xfWindow*) window->extra; xf_SetWindowRects(xfi, xfw, window->windowRects, window->numWindowRects); } void xf_rail_SetWindowVisibilityRects(rdpRail* rail, rdpWindow* window) { xfInfo* xfi; xfWindow* xfw; xfi = (xfInfo*) rail->extra; xfw = (xfWindow*) window->extra; xf_SetWindowVisibilityRects(xfi, xfw, window->windowRects, window->numWindowRects); } void xf_rail_DestroyWindow(rdpRail* rail, rdpWindow* window) { xfWindow* xfw; xfw = (xfWindow*) window->extra; xf_DestroyWindow((xfInfo*) rail->extra, xfw); } void xf_rail_register_callbacks(xfInfo* xfi, rdpRail* rail) { rail->extra = (void*) xfi; rail->rail_CreateWindow = xf_rail_CreateWindow; rail->rail_MoveWindow = xf_rail_MoveWindow; rail->rail_ShowWindow = xf_rail_ShowWindow; rail->rail_SetWindowText = xf_rail_SetWindowText; rail->rail_SetWindowIcon = xf_rail_SetWindowIcon; rail->rail_SetWindowRects = xf_rail_SetWindowRects; rail->rail_SetWindowVisibilityRects = xf_rail_SetWindowVisibilityRects; rail->rail_DestroyWindow = xf_rail_DestroyWindow; } static void xf_on_free_rail_client_event(RDP_EVENT* event) { if (event->event_class == RDP_EVENT_CLASS_RAIL) { rail_free_cloned_order(event->event_type, event->user_data); } } static void xf_send_rail_client_event(rdpChannels* channels, uint16 event_type, void* param) { RDP_EVENT* out_event = NULL; void * payload = NULL; payload = rail_clone_order(event_type, param); if (payload != NULL) { out_event = freerdp_event_new(RDP_EVENT_CLASS_RAIL, event_type, xf_on_free_rail_client_event, payload); freerdp_channels_send_event(channels, out_event); } } void xf_rail_send_activate(xfInfo* xfi, Window xwindow, boolean enabled) { rdpRail* rail; rdpChannels* channels; rdpWindow* rail_window; RAIL_ACTIVATE_ORDER activate; rail = xfi->_context->rail; channels = xfi->_context->channels; rail_window = window_list_get_by_extra_id(rail->list, (void*) xwindow); if (rail_window == NULL) return; activate.windowId = rail_window->windowId; activate.enabled = enabled; xf_send_rail_client_event(channels, RDP_EVENT_TYPE_RAIL_CLIENT_ACTIVATE, &activate); } void xf_rail_send_client_system_command(xfInfo* xfi, uint32 windowId, uint16 command) { rdpChannels* channels; RAIL_SYSCOMMAND_ORDER syscommand; channels = xfi->_context->channels; syscommand.windowId = windowId; syscommand.command = command; xf_send_rail_client_event(channels, RDP_EVENT_TYPE_RAIL_CLIENT_SYSCOMMAND, &syscommand); } /** * The position of the X window can become out of sync with the RDP window * if the X window is moved locally by the window manager. In this event * send an update to the RDP server informing it of the new window position * and size. */ void xf_rail_adjust_position(xfInfo* xfi, rdpWindow *window) { xfWindow* xfw; rdpChannels* channels; RAIL_WINDOW_MOVE_ORDER window_move; xfw = (xfWindow*) window->extra; channels = xfi->_context->channels; if (! xfw->is_mapped || xfw->local_move.state != LMS_NOT_ACTIVE) return; // If current window position disagrees with RDP window position, send // update to RDP server if ( xfw->left != window->windowOffsetX || xfw->top != window->windowOffsetY || xfw->width != window->windowWidth || xfw->height != window->windowHeight) { window_move.windowId = window->windowId; window_move.left = xfw->left; window_move.top = xfw->top; window_move.right = xfw->right; window_move.bottom = xfw->bottom; DEBUG_X11_LMS("window=0x%X rc={l=%d t=%d r=%d b=%d} w=%u h=%u" " RDP=0x%X rc={l=%d t=%d} w=%d h=%d", (uint32) xfw->handle, xfw->left, xfw->top, xfw->right, xfw->bottom, xfw->width, xfw->height, window->windowId, window->windowOffsetX, window->windowOffsetY, window->windowWidth, window->windowHeight); xf_send_rail_client_event(channels, RDP_EVENT_TYPE_RAIL_CLIENT_WINDOW_MOVE, &window_move); } } void xf_rail_end_local_move(xfInfo* xfi, rdpWindow *window) { xfWindow* xfw; rdpChannels* channels; RAIL_WINDOW_MOVE_ORDER window_move; int x,y; rdpInput* input = xfi->instance->input; xfw = (xfWindow*) window->extra; channels = xfi->_context->channels; // Send RDP client event to inform RDP server window_move.windowId = window->windowId; window_move.left = xfw->left; window_move.top = xfw->top; window_move.right = xfw->right + 1; // In the update to RDP the position is one past the window window_move.bottom = xfw->bottom + 1; DEBUG_X11_LMS("window=0x%X rc={l=%d t=%d r=%d b=%d} w=%d h=%d", (uint32) xfw->handle, xfw->left, xfw->top, xfw->right, xfw->bottom, xfw->width, xfw->height); xf_send_rail_client_event(channels, RDP_EVENT_TYPE_RAIL_CLIENT_WINDOW_MOVE, &window_move); // Send synthetic button up event to the RDP server. This is per the RDP spec to // indicate a local move has finished. x = xfw->left + xfw->local_move.window_x; y = xfw->top + xfw->local_move.window_y; input->MouseEvent(input, PTR_FLAGS_BUTTON1, x, y); // Proactively update the RAIL window dimensions. There is a race condition where // we can start to receive GDI orders for the new window dimensions before we // receive the RAIL ORDER for the new window size. This avoids that race condition. window->windowOffsetX = xfw->left; window->windowOffsetY = xfw->top; window->windowWidth = xfw->width; window->windowHeight = xfw->height; xfw->local_move.state = LMS_TERMINATING; } void xf_process_rail_get_sysparams_event(xfInfo* xfi, rdpChannels* channels, RDP_EVENT* event) { RAIL_SYSPARAM_ORDER* sysparam; sysparam = (RAIL_SYSPARAM_ORDER*) event->user_data; sysparam->workArea.left = xfi->workArea.x; sysparam->workArea.top = xfi->workArea.y; sysparam->workArea.right = xfi->workArea.x + xfi->workArea.width; sysparam->workArea.bottom = xfi->workArea.y + xfi->workArea.height; sysparam->taskbarPos.left = 0; sysparam->taskbarPos.top = 0; sysparam->taskbarPos.right = 0; sysparam->taskbarPos.bottom = 0; sysparam->dragFullWindows = false; xf_send_rail_client_event(channels, RDP_EVENT_TYPE_RAIL_CLIENT_SET_SYSPARAMS, sysparam); } const char* error_code_names[] = { "RAIL_EXEC_S_OK", "RAIL_EXEC_E_HOOK_NOT_LOADED", "RAIL_EXEC_E_DECODE_FAILED", "RAIL_EXEC_E_NOT_IN_ALLOWLIST", "RAIL_EXEC_E_FILE_NOT_FOUND", "RAIL_EXEC_E_FAIL", "RAIL_EXEC_E_SESSION_LOCKED" }; void xf_process_rail_exec_result_event(xfInfo* xfi, rdpChannels* channels, RDP_EVENT* event) { RAIL_EXEC_RESULT_ORDER* exec_result; exec_result = (RAIL_EXEC_RESULT_ORDER*) event->user_data; if (exec_result->execResult != RAIL_EXEC_S_OK) { printf("RAIL exec error: execResult=%s NtError=0x%X\n", error_code_names[exec_result->execResult], exec_result->rawResult); xfi->disconnect = True; } else { xf_rail_enable_remoteapp_mode(xfi); } } void xf_process_rail_server_sysparam_event(xfInfo* xfi, rdpChannels* channels, RDP_EVENT* event) { RAIL_SYSPARAM_ORDER* sysparam = (RAIL_SYSPARAM_ORDER*) event->user_data; switch (sysparam->param) { case SPI_SET_SCREEN_SAVE_ACTIVE: break; case SPI_SET_SCREEN_SAVE_SECURE: break; } } void xf_process_rail_server_minmaxinfo_event(xfInfo* xfi, rdpChannels* channels, RDP_EVENT* event) { rdpRail* rail; rdpWindow* rail_window = NULL; RAIL_MINMAXINFO_ORDER* minmax = (RAIL_MINMAXINFO_ORDER*) event->user_data; rail = ((rdpContext*) xfi->context)->rail; rail_window = window_list_get_by_id(rail->list, minmax->windowId); if (rail_window != NULL) { xfWindow * window = NULL; window = (xfWindow *) rail_window->extra; DEBUG_X11_LMS("windowId=0x%X maxWidth=%d maxHeight=%d maxPosX=%d maxPosY=%d " "minTrackWidth=%d minTrackHeight=%d maxTrackWidth=%d maxTrackHeight=%d", minmax->windowId, minmax->maxWidth, minmax->maxHeight, (sint16)minmax->maxPosX, (sint16)minmax->maxPosY, minmax->minTrackWidth, minmax->minTrackHeight, minmax->maxTrackWidth, minmax->maxTrackHeight); xf_SetWindowMinMaxInfo(xfi, window, minmax->maxWidth, minmax->maxHeight, minmax->maxPosX, minmax->maxPosY, minmax->minTrackWidth, minmax->minTrackHeight, minmax->maxTrackWidth, minmax->maxTrackHeight); } } const char* movetype_names[] = { "(invalid)", "RAIL_WMSZ_LEFT", "RAIL_WMSZ_RIGHT", "RAIL_WMSZ_TOP", "RAIL_WMSZ_TOPLEFT", "RAIL_WMSZ_TOPRIGHT", "RAIL_WMSZ_BOTTOM", "RAIL_WMSZ_BOTTOMLEFT", "RAIL_WMSZ_BOTTOMRIGHT", "RAIL_WMSZ_MOVE", "RAIL_WMSZ_KEYMOVE", "RAIL_WMSZ_KEYSIZE" }; void xf_process_rail_server_localmovesize_event(xfInfo* xfi, rdpChannels* channels, RDP_EVENT* event) { rdpRail* rail; rdpWindow* rail_window = NULL; RAIL_LOCALMOVESIZE_ORDER* movesize = (RAIL_LOCALMOVESIZE_ORDER*) event->user_data; int direction = 0; Window child_window; int x,y; rail = ((rdpContext*) xfi->context)->rail; rail_window = window_list_get_by_id(rail->list, movesize->windowId); if (rail_window != NULL) { xfWindow* xfw = NULL; xfw = (xfWindow*) rail_window->extra; DEBUG_X11_LMS("windowId=0x%X isMoveSizeStart=%d moveSizeType=%s PosX=%d PosY=%d", movesize->windowId, movesize->isMoveSizeStart, movetype_names[movesize->moveSizeType], (sint16) movesize->posX, (sint16) movesize->posY); switch (movesize->moveSizeType) { case RAIL_WMSZ_LEFT: //0x1 direction = _NET_WM_MOVERESIZE_SIZE_LEFT; x = movesize->posX; y = movesize->posY; break; case RAIL_WMSZ_RIGHT: //0x2 direction = _NET_WM_MOVERESIZE_SIZE_RIGHT; x = movesize->posX; y = movesize->posY; break; case RAIL_WMSZ_TOP: //0x3 direction = _NET_WM_MOVERESIZE_SIZE_TOP; x = movesize->posX; y = movesize->posY; break; case RAIL_WMSZ_TOPLEFT: //0x4 direction = _NET_WM_MOVERESIZE_SIZE_TOPLEFT; x = movesize->posX; y = movesize->posY; break; case RAIL_WMSZ_TOPRIGHT: //0x5 direction = _NET_WM_MOVERESIZE_SIZE_TOPRIGHT; x = movesize->posX; y = movesize->posY; break; case RAIL_WMSZ_BOTTOM: //0x6 direction = _NET_WM_MOVERESIZE_SIZE_BOTTOM; x = movesize->posX; y = movesize->posY; break; case RAIL_WMSZ_BOTTOMLEFT: //0x7 direction = _NET_WM_MOVERESIZE_SIZE_BOTTOMLEFT; x = movesize->posX; y = movesize->posY; break; case RAIL_WMSZ_BOTTOMRIGHT: //0x8 direction = _NET_WM_MOVERESIZE_SIZE_BOTTOMRIGHT; x = movesize->posX; y = movesize->posY; break; case RAIL_WMSZ_MOVE: //0x9 direction = _NET_WM_MOVERESIZE_MOVE; XTranslateCoordinates(xfi->display, xfw->handle, RootWindowOfScreen(xfi->screen), movesize->posX, movesize->posY, &x, &y, &child_window); break; case RAIL_WMSZ_KEYMOVE: //0xA direction = _NET_WM_MOVERESIZE_MOVE_KEYBOARD; x = movesize->posX; y = movesize->posY; break; case RAIL_WMSZ_KEYSIZE: //0xB direction = _NET_WM_MOVERESIZE_SIZE_KEYBOARD; x = movesize->posX; y = movesize->posY; break; } if (movesize->isMoveSizeStart) { xf_StartLocalMoveSize(xfi, xfw, direction, x, y); } else { xf_EndLocalMoveSize(xfi, xfw); } } } void xf_process_rail_appid_resp_event(xfInfo* xfi, rdpChannels* channels, RDP_EVENT* event) { RAIL_GET_APPID_RESP_ORDER* appid_resp = (RAIL_GET_APPID_RESP_ORDER*)event->user_data; printf("Server Application ID Response PDU: windowId=0x%X " "applicationId=(length=%d dump)\n", appid_resp->windowId, appid_resp->applicationId.length); freerdp_hexdump(appid_resp->applicationId.string, appid_resp->applicationId.length); } void xf_process_rail_langbarinfo_event(xfInfo* xfi, rdpChannels* channels, RDP_EVENT* event) { RAIL_LANGBAR_INFO_ORDER* langbar = (RAIL_LANGBAR_INFO_ORDER*) event->user_data; printf("Language Bar Information PDU: languageBarStatus=0x%X\n", langbar->languageBarStatus); } void xf_process_rail_event(xfInfo* xfi, rdpChannels* channels, RDP_EVENT* event) { switch (event->event_type) { case RDP_EVENT_TYPE_RAIL_CHANNEL_GET_SYSPARAMS: xf_process_rail_get_sysparams_event(xfi, channels, event); break; case RDP_EVENT_TYPE_RAIL_CHANNEL_EXEC_RESULTS: xf_process_rail_exec_result_event(xfi, channels, event); break; case RDP_EVENT_TYPE_RAIL_CHANNEL_SERVER_SYSPARAM: xf_process_rail_server_sysparam_event(xfi, channels, event); break; case RDP_EVENT_TYPE_RAIL_CHANNEL_SERVER_MINMAXINFO: xf_process_rail_server_minmaxinfo_event(xfi, channels, event); break; case RDP_EVENT_TYPE_RAIL_CHANNEL_SERVER_LOCALMOVESIZE: xf_process_rail_server_localmovesize_event(xfi, channels, event); break; case RDP_EVENT_TYPE_RAIL_CHANNEL_APPID_RESP: xf_process_rail_appid_resp_event(xfi, channels, event); break; case RDP_EVENT_TYPE_RAIL_CHANNEL_LANGBARINFO: xf_process_rail_langbarinfo_event(xfi, channels, event); break; default: break; } } FreeRDP-1.0.2/client/X11/xf_rail.h000066400000000000000000000024421207112532300163630ustar00rootroot00000000000000/** * FreeRDP: A Remote Desktop Protocol Client * X11 RAIL * * Copyright 2011 Marc-Andre Moreau * * 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. */ #ifndef __XF_RAIL_H #define __XF_RAIL_H #include "xfreerdp.h" void xf_rail_paint(xfInfo* xfi, rdpRail* rail, sint32 uleft, sint32 utop, uint32 uright, uint32 ubottom); void xf_rail_register_callbacks(xfInfo* xfi, rdpRail* rail); void xf_rail_send_client_system_command(xfInfo* xfi, uint32 windowId, uint16 command); void xf_rail_send_activate(xfInfo* xfi, Window xwindow, boolean enabled); void xf_process_rail_event(xfInfo* xfi, rdpChannels* chanman, RDP_EVENT* event); void xf_rail_adjust_position(xfInfo* xfi, rdpWindow *window); void xf_rail_end_local_move(xfInfo* xfi, rdpWindow *window); #endif /* __XF_RAIL_H */ FreeRDP-1.0.2/client/X11/xf_tsmf.c000066400000000000000000000222011207112532300163730ustar00rootroot00000000000000/** * FreeRDP: A Remote Desktop Protocol Client * X11 Video Redirection * * Copyright 2010-2011 Vic Lee * * 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. */ #include #include #include #include #include #include #include #include #include #include #include #include #include "xf_tsmf.h" #ifdef WITH_XV #include #include typedef struct xf_xv_context xfXvContext; struct xf_xv_context { long xv_port; Atom xv_colorkey_atom; int xv_image_size; int xv_shmid; char* xv_shmaddr; uint32* xv_pixfmts; }; #ifdef WITH_DEBUG_XV #define DEBUG_XV(fmt, ...) DEBUG_CLASS(XV, fmt, ## __VA_ARGS__) #else #define DEBUG_XV(fmt, ...) DEBUG_NULL(fmt, ## __VA_ARGS__) #endif void xf_tsmf_init(xfInfo* xfi, long xv_port) { int ret; unsigned int i; unsigned int version; unsigned int release; unsigned int event_base; unsigned int error_base; unsigned int request_base; unsigned int num_adaptors; xfXvContext* xv; XvAdaptorInfo* ai; XvAttribute* attr; XvImageFormatValues* fo; xv = xnew(xfXvContext); xfi->xv_context = xv; xv->xv_colorkey_atom = None; xv->xv_image_size = 0; xv->xv_port = xv_port; if (!XShmQueryExtension(xfi->display)) { DEBUG_XV("no shmem available."); return; } ret = XvQueryExtension(xfi->display, &version, &release, &request_base, &event_base, &error_base); if (ret != Success) { DEBUG_XV("XvQueryExtension failed %d.", ret); return; } DEBUG_XV("version %u release %u", version, release); ret = XvQueryAdaptors(xfi->display, DefaultRootWindow(xfi->display), &num_adaptors, &ai); if (ret != Success) { DEBUG_XV("XvQueryAdaptors failed %d.", ret); return; } for (i = 0; i < num_adaptors; i++) { DEBUG_XV("adapter port %ld-%ld (%s)", ai[i].base_id, ai[i].base_id + ai[i].num_ports - 1, ai[i].name); if (xv->xv_port == 0 && i == num_adaptors - 1) xv->xv_port = ai[i].base_id; } if (num_adaptors > 0) XvFreeAdaptorInfo(ai); if (xv->xv_port == 0) { DEBUG_XV("no adapter selected, video frames will not be processed."); return; } DEBUG_XV("selected %ld", xv->xv_port); attr = XvQueryPortAttributes(xfi->display, xv->xv_port, &ret); for (i = 0; i < (unsigned int)ret; i++) { if (strcmp(attr[i].name, "XV_COLORKEY") == 0) { xv->xv_colorkey_atom = XInternAtom(xfi->display, "XV_COLORKEY", false); XvSetPortAttribute(xfi->display, xv->xv_port, xv->xv_colorkey_atom, attr[i].min_value + 1); break; } } XFree(attr); #ifdef WITH_DEBUG_XV printf("xf_tsmf_init: pixel format "); #endif fo = XvListImageFormats(xfi->display, xv->xv_port, &ret); if (ret > 0) { xv->xv_pixfmts = (uint32*) xzalloc((ret + 1) * sizeof(uint32)); for (i = 0; i < ret; i++) { xv->xv_pixfmts[i] = fo[i].id; #ifdef WITH_DEBUG_XV printf("%c%c%c%c ", ((char*)(xv->xv_pixfmts + i))[0], ((char*)(xv->xv_pixfmts + i))[1], ((char*)(xv->xv_pixfmts + i))[2], ((char*)(xv->xv_pixfmts + i))[3]); #endif } xv->xv_pixfmts[i] = 0; } XFree(fo); #ifdef WITH_DEBUG_XV printf("\n"); #endif } void xf_tsmf_uninit(xfInfo* xfi) { xfXvContext* xv = (xfXvContext*) xfi->xv_context; if (xv) { if (xv->xv_image_size > 0) { shmdt(xv->xv_shmaddr); shmctl(xv->xv_shmid, IPC_RMID, NULL); } if (xv->xv_pixfmts) { xfree(xv->xv_pixfmts); xv->xv_pixfmts = NULL; } xfree(xv); xfi->xv_context = NULL; } } static boolean xf_tsmf_is_format_supported(xfXvContext* xv, uint32 pixfmt) { int i; if (!xv->xv_pixfmts) return false; for (i = 0; xv->xv_pixfmts[i]; i++) { if (xv->xv_pixfmts[i] == pixfmt) return true; } return false; } static void xf_process_tsmf_video_frame_event(xfInfo* xfi, RDP_VIDEO_FRAME_EVENT* vevent) { int i; uint8* data1; uint8* data2; uint32 pixfmt; XvImage * image; int colorkey = 0; XShmSegmentInfo shminfo; xfXvContext* xv = (xfXvContext*) xfi->xv_context; if (xv->xv_port == 0) return; /* In case the player is minimized */ if (vevent->x < -2048 || vevent->y < -2048 || vevent->num_visible_rects <= 0) return; if (xv->xv_colorkey_atom != None) { XvGetPortAttribute(xfi->display, xv->xv_port, xv->xv_colorkey_atom, &colorkey); XSetFunction(xfi->display, xfi->gc, GXcopy); XSetFillStyle(xfi->display, xfi->gc, FillSolid); XSetForeground(xfi->display, xfi->gc, colorkey); for (i = 0; i < vevent->num_visible_rects; i++) { XFillRectangle(xfi->display, xfi->window->handle, xfi->gc, vevent->x + vevent->visible_rects[i].x, vevent->y + vevent->visible_rects[i].y, vevent->visible_rects[i].width, vevent->visible_rects[i].height); } } pixfmt = vevent->frame_pixfmt; image = XvShmCreateImage(xfi->display, xv->xv_port, pixfmt, 0, vevent->frame_width, vevent->frame_height, &shminfo); if (xv->xv_image_size != image->data_size) { if (xv->xv_image_size > 0) { shmdt(xv->xv_shmaddr); shmctl(xv->xv_shmid, IPC_RMID, NULL); } xv->xv_image_size = image->data_size; xv->xv_shmid = shmget(IPC_PRIVATE, image->data_size, IPC_CREAT | 0777); xv->xv_shmaddr = shmat(xv->xv_shmid, 0, 0); } shminfo.shmid = xv->xv_shmid; shminfo.shmaddr = image->data = xv->xv_shmaddr; shminfo.readOnly = false; if (!XShmAttach(xfi->display, &shminfo)) { XFree(image); DEBUG_XV("XShmAttach failed."); return; } /* The video driver may align each line to a different size and we need to convert our original image data. */ switch (pixfmt) { case RDP_PIXFMT_I420: case RDP_PIXFMT_YV12: if (!xf_tsmf_is_format_supported(xv, RDP_PIXFMT_I420) && !xf_tsmf_is_format_supported(xv, RDP_PIXFMT_YV12)) { DEBUG_XV("pixel format 0x%X not supported by hardware.", pixfmt); break; } /* Y */ if (image->pitches[0] == vevent->frame_width) { memcpy(image->data + image->offsets[0], vevent->frame_data, vevent->frame_width * vevent->frame_height); } else { for (i = 0; i < vevent->frame_height; i++) { memcpy(image->data + image->offsets[0] + i * image->pitches[0], vevent->frame_data + i * vevent->frame_width, vevent->frame_width); } } /* UV */ /* Conversion between I420 and YV12 is to simply swap U and V */ if (xf_tsmf_is_format_supported(xv, pixfmt)) { data1 = vevent->frame_data + vevent->frame_width * vevent->frame_height; data2 = vevent->frame_data + vevent->frame_width * vevent->frame_height + vevent->frame_width * vevent->frame_height / 4; } else { data2 = vevent->frame_data + vevent->frame_width * vevent->frame_height; data1 = vevent->frame_data + vevent->frame_width * vevent->frame_height + vevent->frame_width * vevent->frame_height / 4; image->id = pixfmt == RDP_PIXFMT_I420 ? RDP_PIXFMT_YV12 : RDP_PIXFMT_I420; } if (image->pitches[1] * 2 == vevent->frame_width) { memcpy(image->data + image->offsets[1], data1, vevent->frame_width * vevent->frame_height / 4); memcpy(image->data + image->offsets[2], data2, vevent->frame_width * vevent->frame_height / 4); } else { for (i = 0; i < vevent->frame_height / 2; i++) { memcpy(image->data + image->offsets[1] + i * image->pitches[1], data1 + i * vevent->frame_width / 2, vevent->frame_width / 2); memcpy(image->data + image->offsets[2] + i * image->pitches[2], data2 + i * vevent->frame_width / 2, vevent->frame_width / 2); } } break; default: memcpy(image->data, vevent->frame_data, image->data_size <= vevent->frame_size ? image->data_size : vevent->frame_size); break; } XvShmPutImage(xfi->display, xv->xv_port, xfi->window->handle, xfi->gc, image, 0, 0, image->width, image->height, vevent->x, vevent->y, vevent->width, vevent->height, false); XSync(xfi->display, false); XShmDetach(xfi->display, &shminfo); XFree(image); } static void xf_process_tsmf_redraw_event(xfInfo* xfi, RDP_REDRAW_EVENT* revent) { XSetFunction(xfi->display, xfi->gc, GXcopy); XSetFillStyle(xfi->display, xfi->gc, FillSolid); XCopyArea(xfi->display, xfi->primary, xfi->window->handle, xfi->gc, revent->x, revent->y, revent->width, revent->height, revent->x, revent->y); } void xf_process_tsmf_event(xfInfo* xfi, RDP_EVENT* event) { switch (event->event_type) { case RDP_EVENT_TYPE_TSMF_VIDEO_FRAME: xf_process_tsmf_video_frame_event(xfi, (RDP_VIDEO_FRAME_EVENT*) event); break; case RDP_EVENT_TYPE_TSMF_REDRAW: xf_process_tsmf_redraw_event(xfi, (RDP_REDRAW_EVENT*) event); break; } } #else /* WITH_XV */ void xf_tsmf_init(xfInfo* xfi, long xv_port) { } void xf_tsmf_uninit(xfInfo* xfi) { } void xf_process_tsmf_event(xfInfo* xfi, RDP_EVENT* event) { } #endif /* WITH_XV */ FreeRDP-1.0.2/client/X11/xf_tsmf.h000066400000000000000000000016041207112532300164040ustar00rootroot00000000000000/** * FreeRDP: A Remote Desktop Protocol Client * X11 Video Redirection * * Copyright 2010-2011 Vic Lee * * 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. */ #ifndef __XF_TSMF_H #define __XF_TSMF_H #include "xfreerdp.h" void xf_tsmf_init(xfInfo* xfi, long xv_port); void xf_tsmf_uninit(xfInfo* xfi); void xf_process_tsmf_event(xfInfo* xfi, RDP_EVENT* event); #endif /* __XF_TSMF_H */ FreeRDP-1.0.2/client/X11/xf_window.c000066400000000000000000000516331207112532300167440ustar00rootroot00000000000000/** * FreeRDP: A Remote Desktop Protocol Client * X11 Windows * * Copyright 2011 Marc-Andre Moreau * * 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. */ #include #include #include #include #include #include #ifdef WITH_XEXT #include #endif #include "FreeRDP_Icon_256px.h" #define xf_icon_prop FreeRDP_Icon_256px_prop #include "xf_window.h" /* Extended Window Manager Hints: http://standards.freedesktop.org/wm-spec/wm-spec-1.3.html */ /* bit definitions for MwmHints.flags */ #define MWM_HINTS_FUNCTIONS (1L << 0) #define MWM_HINTS_DECORATIONS (1L << 1) #define MWM_HINTS_INPUT_MODE (1L << 2) #define MWM_HINTS_STATUS (1L << 3) /* bit definitions for MwmHints.functions */ #define MWM_FUNC_ALL (1L << 0) #define MWM_FUNC_RESIZE (1L << 1) #define MWM_FUNC_MOVE (1L << 2) #define MWM_FUNC_MINIMIZE (1L << 3) #define MWM_FUNC_MAXIMIZE (1L << 4) #define MWM_FUNC_CLOSE (1L << 5) /* bit definitions for MwmHints.decorations */ #define MWM_DECOR_ALL (1L << 0) #define MWM_DECOR_BORDER (1L << 1) #define MWM_DECOR_RESIZEH (1L << 2) #define MWM_DECOR_TITLE (1L << 3) #define MWM_DECOR_MENU (1L << 4) #define MWM_DECOR_MINIMIZE (1L << 5) #define MWM_DECOR_MAXIMIZE (1L << 6) #define PROP_MOTIF_WM_HINTS_ELEMENTS 5 struct _PropMotifWmHints { unsigned long flags; unsigned long functions; unsigned long decorations; long inputMode; unsigned long status; }; typedef struct _PropMotifWmHints PropMotifWmHints; /** * Post an event from the client to the X server */ void xf_SendClientEvent(xfInfo *xfi, xfWindow* window, Atom atom, unsigned int numArgs, ...) { XEvent xevent; unsigned int i; va_list argp; va_start(argp, numArgs); xevent.xclient.type = ClientMessage; xevent.xclient.serial = 0; xevent.xclient.send_event = False; xevent.xclient.display = xfi->display; xevent.xclient.window = window->handle; xevent.xclient.message_type = atom; xevent.xclient.format = 32; for (i=0; idisplay, RootWindowOfScreen(xfi->screen), False, SubstructureRedirectMask | SubstructureNotifyMask, &xevent); XSync(xfi->display, False); va_end(argp); } void xf_SetWindowFullscreen(xfInfo* xfi, xfWindow* window, boolean fullscreen) { if (fullscreen) { xf_SetWindowDecorations(xfi, window, false); XMoveResizeWindow(xfi->display, window->handle, 0, 0, window->width, window->height); XMapRaised(xfi->display, window->handle); window->fullscreen = true; } } /* http://tronche.com/gui/x/xlib/window-information/XGetWindowProperty.html */ boolean xf_GetWindowProperty(xfInfo* xfi, Window window, Atom property, int length, unsigned long* nitems, unsigned long* bytes, uint8** prop) { int status; Atom actual_type; int actual_format; if (property == None) return false; status = XGetWindowProperty(xfi->display, window, property, 0, length, false, AnyPropertyType, &actual_type, &actual_format, nitems, bytes, prop); if (status != Success) return false; if (actual_type == None) { DEBUG_WARN("Property %lu does not exist", property); return false; } return true; } boolean xf_GetCurrentDesktop(xfInfo* xfi) { boolean status; unsigned long nitems; unsigned long bytes; unsigned char* prop; status = xf_GetWindowProperty(xfi, DefaultRootWindow(xfi->display), xfi->_NET_CURRENT_DESKTOP, 1, &nitems, &bytes, &prop); if (status != true) { return false; } xfi->current_desktop = (int) *prop; xfree(prop); return true; } boolean xf_GetWorkArea(xfInfo* xfi) { long* plong; boolean status; unsigned long nitems; unsigned long bytes; unsigned char* prop; status = xf_GetCurrentDesktop(xfi); if (status != true) return false; status = xf_GetWindowProperty(xfi, DefaultRootWindow(xfi->display), xfi->_NET_WORKAREA, 32 * 4, &nitems, &bytes, &prop); if (status != true) return false; if ((xfi->current_desktop * 4 + 3) >= nitems) { xfree(prop); return false; } plong = (long*) prop; xfi->workArea.x = plong[xfi->current_desktop * 4 + 0]; xfi->workArea.y = plong[xfi->current_desktop * 4 + 1]; xfi->workArea.width = plong[xfi->current_desktop * 4 + 2]; xfi->workArea.height = plong[xfi->current_desktop * 4 + 3]; xfree(prop); return true; } void xf_SetWindowDecorations(xfInfo* xfi, xfWindow* window, boolean show) { PropMotifWmHints hints; hints.decorations = (show) ? MWM_DECOR_ALL : 0; hints.functions = MWM_FUNC_ALL ; hints.flags = MWM_HINTS_DECORATIONS | MWM_HINTS_FUNCTIONS; XChangeProperty(xfi->display, window->handle, xfi->_MOTIF_WM_HINTS, xfi->_MOTIF_WM_HINTS, 32, PropModeReplace, (uint8*) &hints, PROP_MOTIF_WM_HINTS_ELEMENTS); } void xf_SetWindowUnlisted(xfInfo* xfi, xfWindow* window) { Atom window_state[2]; window_state[0] = xfi->_NET_WM_STATE_SKIP_PAGER; window_state[1] = xfi->_NET_WM_STATE_SKIP_TASKBAR; XChangeProperty(xfi->display, window->handle, xfi->_NET_WM_STATE, XA_ATOM, 32, PropModeReplace, (uint8*) &window_state, 2); } void xf_SetWindowStyle(xfInfo* xfi, xfWindow* window, uint32 style, uint32 ex_style) { Atom window_type; if ((ex_style & WS_EX_TOPMOST) || (ex_style & WS_EX_TOOLWINDOW)) { /* * These include tool tips, dropdown menus, etc. These won't work * correctly if the local window manager resizes or moves them. * Set override redirect to prevent this from occurring. */ XSetWindowAttributes attrs; attrs.override_redirect = True; XChangeWindowAttributes(xfi->display, window->handle, CWOverrideRedirect, &attrs); window->is_transient = true; xf_SetWindowUnlisted(xfi, window); window_type = xfi->_NET_WM_WINDOW_TYPE_POPUP; } else if (style & WS_POPUP) { /* this includes dialogs, popups, etc, that need to be full-fledged windows */ window_type = xfi->_NET_WM_WINDOW_TYPE_DIALOG; xf_SetWindowUnlisted(xfi, window); } else { window_type = xfi->_NET_WM_WINDOW_TYPE_NORMAL; } XChangeProperty(xfi->display, window->handle, xfi->_NET_WM_WINDOW_TYPE, XA_ATOM, 32, PropModeReplace, (uint8*) &window_type, 1); } xfWindow* xf_CreateDesktopWindow(xfInfo* xfi, char* name, int width, int height, boolean decorations) { xfWindow* window; XEvent xevent; window = (xfWindow*) xzalloc(sizeof(xfWindow)); if (window != NULL) { int input_mask; XClassHint* class_hints; window->width = width; window->height = height; window->fullscreen = false; window->decorations = decorations; window->local_move.state = LMS_NOT_ACTIVE; window->is_mapped = false; window->is_transient = false; window->handle = XCreateWindow(xfi->display, RootWindowOfScreen(xfi->screen), xfi->workArea.x, xfi->workArea.y, xfi->width, xfi->height, 0, xfi->depth, InputOutput, xfi->visual, CWBackPixel | CWBackingStore | CWOverrideRedirect | CWColormap | CWBorderPixel | CWWinGravity | CWBitGravity, &xfi->attribs); class_hints = XAllocClassHint(); if (class_hints != NULL) { class_hints->res_name = "xfreerdp"; class_hints->res_class = "xfreerdp"; XSetClassHint(xfi->display, window->handle, class_hints); XFree(class_hints); } xf_ResizeDesktopWindow(xfi, window, width, height); xf_SetWindowDecorations(xfi, window, decorations); input_mask = KeyPressMask | KeyReleaseMask | ButtonPressMask | ButtonReleaseMask | VisibilityChangeMask | FocusChangeMask | StructureNotifyMask | PointerMotionMask | ExposureMask | PropertyChangeMask; if (xfi->grab_keyboard) input_mask |= EnterWindowMask | LeaveWindowMask; XChangeProperty(xfi->display, window->handle, xfi->_NET_WM_ICON, XA_CARDINAL, 32, PropModeReplace, (uint8*) xf_icon_prop, sizeof(xf_icon_prop) / sizeof(long)); if (xfi->parent_window) XReparentWindow(xfi->display, window->handle, xfi->parent_window, 0, 0); XSelectInput(xfi->display, window->handle, input_mask); XMapWindow(xfi->display, window->handle); //NOTE: This must be done here to handle reparenting the window, so that we dont miss the event and hang waiting for the next one /* wait for VisibilityNotify */ do { XMaskEvent(xfi->display, VisibilityChangeMask, &xevent); } while (xevent.type != VisibilityNotify); } XStoreName(xfi->display, window->handle, name); return window; } void xf_ResizeDesktopWindow(xfInfo* xfi, xfWindow* window, int width, int height) { XSizeHints* size_hints; size_hints = XAllocSizeHints(); if (size_hints) { size_hints->flags = PMinSize | PMaxSize; size_hints->min_width = size_hints->max_width = xfi->width; size_hints->min_height = size_hints->max_height = xfi->height; XSetWMNormalHints(xfi->display, window->handle, size_hints); XFree(size_hints); } } void xf_FixWindowCoordinates(xfInfo* xfi, int* x, int* y, int* width, int* height) { int vscreen_width; int vscreen_height; vscreen_width = xfi->vscreen.area.right - xfi->vscreen.area.left + 1; vscreen_height = xfi->vscreen.area.bottom - xfi->vscreen.area.top + 1; if (*width < 1) { *width = 1; } if (*height < 1) { *height = 1; } if (*x < xfi->vscreen.area.left) { *width += *x; *x = xfi->vscreen.area.left; } if (*y < xfi->vscreen.area.top) { *height += *y; *y = xfi->vscreen.area.top; } if (*width > vscreen_width) { *width = vscreen_width; } if (*height > vscreen_height) { *height = vscreen_height; } } char rail_window_class[] = "RAIL:00000000"; xfWindow* xf_CreateWindow(xfInfo* xfi, rdpWindow* wnd, int x, int y, int width, int height, uint32 id) { xfWindow* window; window = (xfWindow*) xzalloc(sizeof(xfWindow)); xf_FixWindowCoordinates(xfi, &x, &y, &width, &height); window->left = x; window->top = y; window->right = x + width - 1; window->bottom = y + height - 1; window->width = width; window->height = height; XGCValues gcv; XClassHint* class_hints; int input_mask; window->decorations = false; window->fullscreen = false; window->window = wnd; window->local_move.state = LMS_NOT_ACTIVE; window->is_mapped = false; window->is_transient = false; window->handle = XCreateWindow(xfi->display, RootWindowOfScreen(xfi->screen), x, y, window->width, window->height, 0, xfi->depth, InputOutput, xfi->visual, CWBackPixel | CWBackingStore | CWOverrideRedirect | CWColormap | CWBorderPixel | CWWinGravity | CWBitGravity, &xfi->attribs); DEBUG_X11_LMS("Create window=0x%X rc={l=%d t=%d r=%d b=%d} w=%d h=%d rdp=0x%X", (uint32) window->handle, window->left, window->top, window->right, window->bottom, window->width, window->height, wnd->windowId); xf_SetWindowDecorations(xfi, window, window->decorations); xf_SetWindowStyle(xfi, window, wnd->style, wnd->extendedStyle); class_hints = XAllocClassHint(); if (class_hints != NULL) { char* class; class = xmalloc(sizeof(rail_window_class)); snprintf(class, sizeof(rail_window_class), "RAIL:%08X", id); class_hints->res_name = "RAIL"; class_hints->res_class = class; XSetClassHint(xfi->display, window->handle, class_hints); XFree(class_hints); xfree(class); } XSetWMProtocols(xfi->display, window->handle, &(xfi->WM_DELETE_WINDOW), 1); input_mask = KeyPressMask | KeyReleaseMask | ButtonPressMask | ButtonReleaseMask | EnterWindowMask | LeaveWindowMask | PointerMotionMask | Button1MotionMask | Button2MotionMask | Button3MotionMask | Button4MotionMask | Button5MotionMask | ButtonMotionMask | KeymapStateMask | ExposureMask | VisibilityChangeMask | StructureNotifyMask | SubstructureNotifyMask | SubstructureRedirectMask | FocusChangeMask | PropertyChangeMask | ColormapChangeMask | OwnerGrabButtonMask; XSelectInput(xfi->display, window->handle, input_mask); XMapWindow(xfi->display, window->handle); memset(&gcv, 0, sizeof(gcv)); window->gc = XCreateGC(xfi->display, window->handle, GCGraphicsExposures, &gcv); xf_MoveWindow(xfi, window, x, y, width, height); return window; } void xf_SetWindowMinMaxInfo(xfInfo* xfi, xfWindow* window, int maxWidth, int maxHeight, int maxPosX, int maxPosY, int minTrackWidth, int minTrackHeight, int maxTrackWidth, int maxTrackHeight) { XSizeHints* size_hints; size_hints = XAllocSizeHints(); if (size_hints) { size_hints->flags = PMinSize | PMaxSize | PResizeInc; size_hints->min_width = minTrackWidth; size_hints->min_height = minTrackHeight; size_hints->max_width = maxTrackWidth; size_hints->max_height = maxTrackHeight; /* to speedup window drawing we need to select optimal value for sizing step. */ size_hints->width_inc = size_hints->height_inc = 1; XSetWMNormalHints(xfi->display, window->handle, size_hints); XFree(size_hints); } } void xf_StartLocalMoveSize(xfInfo* xfi, xfWindow* window, int direction, int x, int y) { Window child_window; if (window->local_move.state != LMS_NOT_ACTIVE) return; DEBUG_X11_LMS("direction=%d window=0x%X rc={l=%d t=%d r=%d b=%d} w=%d h=%d " "RDP=0x%X rc={l=%d t=%d} w=%d h=%d mouse_x=%d mouse_y=%d", direction, (uint32) window->handle, window->left, window->top, window->right, window->bottom, window->width, window->height, window->window->windowId, window->window->windowOffsetX, window->window->windowOffsetY, window->window->windowWidth, window->window->windowHeight, x, y); window->local_move.root_x = x; window->local_move.root_y = y; window->local_move.state = LMS_STARTING; XTranslateCoordinates(xfi->display, RootWindowOfScreen(xfi->screen), window->handle, window->local_move.root_x, window->local_move.root_y, &window->local_move.window_x, &window->local_move.window_y, &child_window); XUngrabPointer(xfi->display, CurrentTime); xf_SendClientEvent(xfi, window, xfi->_NET_WM_MOVERESIZE, /* request X window manager to initiate a local move */ 5, /* 5 arguments to follow */ x, /* x relative to root window */ y, /* y relative to root window */ direction, /* extended ICCM direction flag */ 1, /* simulated mouse button 1 */ 1); /* 1 == application request per extended ICCM */ } void xf_EndLocalMoveSize(xfInfo *xfi, xfWindow *window) { DEBUG_X11_LMS("state=%d window=0x%X rc={l=%d t=%d r=%d b=%d} w=%d h=%d " "RDP=0x%X rc={l=%d t=%d} w=%d h=%d", window->local_move.state, (uint32) window->handle, window->left, window->top, window->right, window->bottom, window->width, window->height, window->window->windowId, window->window->windowOffsetX, window->window->windowOffsetY, window->window->windowWidth, window->window->windowHeight); if (window->local_move.state == LMS_NOT_ACTIVE) return; if (window->local_move.state == LMS_STARTING) { /* * The move never was property started. This can happen due to race * conditions between the mouse button up and the communications to the * RDP server for local moves. We must cancel the X window manager move. * Per ICCM, the X client can ask to cancel an active move. */ xf_SendClientEvent(xfi, window, xfi->_NET_WM_MOVERESIZE, /* request X window manager to abort a local move */ 5, /* 5 arguments to follow */ window->local_move.root_x, /* x relative to root window */ window->local_move.root_y, /* y relative to root window */ _NET_WM_MOVERESIZE_CANCEL, /* extended ICCM direction flag */ 1, /* simulated mouse button 1 */ 1); /* 1 == application request per extended ICCM */ } window->local_move.state = LMS_NOT_ACTIVE; } void xf_MoveWindow(xfInfo* xfi, xfWindow* window, int x, int y, int width, int height) { boolean resize = false; if ((width * height) < 1) return; if ((window->width != width) || (window->height != height)) resize = true; if (window->local_move.state == LMS_STARTING || window->local_move.state == LMS_ACTIVE) return; DEBUG_X11_LMS("window=0x%X rc={l=%d t=%d r=%d b=%d} w=%u h=%u " "new rc={l=%d t=%d r=%d b=%d} w=%u h=%u" " RDP=0x%X rc={l=%d t=%d} w=%d h=%d", (uint32) window->handle, window->left, window->top, window->right, window->bottom, window->width, window->height, x, y, x + width -1, y + height -1, width, height, window->window->windowId, window->window->windowOffsetX, window->window->windowOffsetY, window->window->windowWidth, window->window->windowHeight); window->left = x; window->top = y; window->right = x + width - 1; window->bottom = y + height - 1; window->width = width; window->height = height; if (resize) XMoveResizeWindow(xfi->display, window->handle, x, y, width, height); else XMoveWindow(xfi->display, window->handle, x, y); xf_UpdateWindowArea(xfi, window, 0, 0, width, height); } void xf_ShowWindow(xfInfo* xfi, xfWindow* window, uint8 state) { switch (state) { case WINDOW_HIDE: XWithdrawWindow(xfi->display, window->handle, xfi->screen_number); break; case WINDOW_SHOW_MINIMIZED: XIconifyWindow(xfi->display, window->handle, xfi->screen_number); break; case WINDOW_SHOW_MAXIMIZED: XRaiseWindow(xfi->display, window->handle); break; case WINDOW_SHOW: XMapWindow(xfi->display, window->handle); break; } XFlush(xfi->display); } void xf_SetWindowIcon(xfInfo* xfi, xfWindow* window, rdpIcon* icon) { int x, y; int pixels; int propsize; long* propdata; long* dstp; uint32* srcp; if (icon->big != true) return; pixels = icon->entry->width * icon->entry->height; propsize = 2 + pixels; propdata = xmalloc(propsize * sizeof(long)); propdata[0] = icon->entry->width; propdata[1] = icon->entry->height; dstp = &(propdata[2]); srcp = (uint32*) icon->extra; for (y = 0; y < icon->entry->height; y++) { for (x = 0; x < icon->entry->width; x++) { *dstp++ = *srcp++; } } XChangeProperty(xfi->display, window->handle, xfi->_NET_WM_ICON, XA_CARDINAL, 32, PropModeReplace, (uint8*) propdata, propsize); XFlush(xfi->display); } void xf_SetWindowRects(xfInfo* xfi, xfWindow* window, RECTANGLE_16* rects, int nrects) { int i; XRectangle* xrects; xrects = xmalloc(sizeof(XRectangle) * nrects); for (i = 0; i < nrects; i++) { xrects[i].x = rects[i].left; xrects[i].y = rects[i].top; xrects[i].width = rects[i].right - rects[i].left; xrects[i].height = rects[i].bottom - rects[i].top; } #ifdef WITH_XEXT XShapeCombineRectangles(xfi->display, window->handle, ShapeBounding, 0, 0, xrects, nrects, ShapeSet, 0); #endif xfree(xrects); } void xf_SetWindowVisibilityRects(xfInfo* xfi, xfWindow* window, RECTANGLE_16* rects, int nrects) { int i; XRectangle* xrects; xrects = xmalloc(sizeof(XRectangle) * nrects); for (i = 0; i < nrects; i++) { xrects[i].x = rects[i].left; xrects[i].y = rects[i].top; xrects[i].width = rects[i].right - rects[i].left; xrects[i].height = rects[i].bottom - rects[i].top; } #ifdef WITH_XEXT //XShapeCombineRectangles(xfi->display, window->handle, ShapeBounding, 0, 0, xrects, nrects, ShapeSet, 0); #endif xfree(xrects); } void xf_UpdateWindowArea(xfInfo* xfi, xfWindow* window, int x, int y, int width, int height) { int ax, ay; rdpWindow* wnd; wnd = window->window; ax = x + wnd->windowOffsetX; ay = y + wnd->windowOffsetY; if (ax + width > wnd->windowOffsetX + wnd->windowWidth) width = (wnd->windowOffsetX + wnd->windowWidth - 1) - ax; if (ay + height > wnd->windowOffsetY + wnd->windowHeight) height = (wnd->windowOffsetY + wnd->windowHeight - 1) - ay; if (xfi->sw_gdi) { XPutImage(xfi->display, xfi->primary, window->gc, xfi->image, ax, ay, ax, ay, width, height); } XCopyArea(xfi->display, xfi->primary, window->handle, window->gc, ax, ay, width, height, x, y); XFlush(xfi->display); } boolean xf_IsWindowBorder(xfInfo* xfi, xfWindow* xfw, int x, int y) { rdpWindow* wnd; boolean clientArea = false; boolean windowArea = false; wnd = xfw->window; if (((x > wnd->clientOffsetX) && (x < wnd->clientOffsetX + wnd->clientAreaWidth)) && ((y > wnd->clientOffsetY) && (y < wnd->clientOffsetY + wnd->clientAreaHeight))) clientArea = true; if (((x > wnd->windowOffsetX) && (x < wnd->windowOffsetX + wnd->windowWidth)) && ((y > wnd->windowOffsetY) && (y < wnd->windowOffsetY + wnd->windowHeight))) windowArea = true; return (windowArea && !(clientArea)); } void xf_DestroyWindow(xfInfo* xfi, xfWindow* window) { if (window == NULL) return; if (xfi->window == window) xfi->window = NULL; if (window->gc) XFreeGC(xfi->display, window->gc); if (window->handle) { XUnmapWindow(xfi->display, window->handle); XDestroyWindow(xfi->display, window->handle); } xfree(window); } FreeRDP-1.0.2/client/X11/xf_window.h000066400000000000000000000076021207112532300167460ustar00rootroot00000000000000/** * FreeRDP: A Remote Desktop Protocol Client * X11 Windows * * Copyright 2011 Marc-Andre Moreau * * 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. */ #ifndef __XF_WINDOW_H #define __XF_WINDOW_H #include #include #include typedef struct xf_localmove xfLocalMove; typedef struct xf_window xfWindow; #include "xfreerdp.h" // Extended ICCM flags http://standards.freedesktop.org/wm-spec/wm-spec-latest.html #define _NET_WM_MOVERESIZE_SIZE_TOPLEFT 0 #define _NET_WM_MOVERESIZE_SIZE_TOP 1 #define _NET_WM_MOVERESIZE_SIZE_TOPRIGHT 2 #define _NET_WM_MOVERESIZE_SIZE_RIGHT 3 #define _NET_WM_MOVERESIZE_SIZE_BOTTOMRIGHT 4 #define _NET_WM_MOVERESIZE_SIZE_BOTTOM 5 #define _NET_WM_MOVERESIZE_SIZE_BOTTOMLEFT 6 #define _NET_WM_MOVERESIZE_SIZE_LEFT 7 #define _NET_WM_MOVERESIZE_MOVE 8 /* movement only */ #define _NET_WM_MOVERESIZE_SIZE_KEYBOARD 9 /* size via keyboard */ #define _NET_WM_MOVERESIZE_MOVE_KEYBOARD 10 /* move via keyboard */ #define _NET_WM_MOVERESIZE_CANCEL 11 /* cancel operation */ enum xf_localmove_state { LMS_NOT_ACTIVE, LMS_STARTING, LMS_ACTIVE, LMS_TERMINATING }; struct xf_localmove { int root_x; // relative to root int root_y; int window_x; // relative to window int window_y; enum xf_localmove_state state; }; struct xf_window { GC gc; int left; int top; int right; int bottom; int width; int height; Window handle; boolean fullscreen; boolean decorations; rdpWindow* window; boolean is_mapped; boolean is_transient; xfLocalMove local_move; }; void xf_ewmhints_init(xfInfo* xfi); boolean xf_GetCurrentDesktop(xfInfo* xfi); boolean xf_GetWorkArea(xfInfo* xfi); void xf_SetWindowFullscreen(xfInfo* xfi, xfWindow* window, boolean fullscreen); void xf_SetWindowDecorations(xfInfo* xfi, xfWindow* window, boolean show); void xf_SetWindowUnlisted(xfInfo* xfi, xfWindow* window); xfWindow* xf_CreateDesktopWindow(xfInfo* xfi, char* name, int width, int height, boolean decorations); void xf_ResizeDesktopWindow(xfInfo* xfi, xfWindow* window, int width, int height); xfWindow* xf_CreateWindow(xfInfo* xfi, rdpWindow* wnd, int x, int y, int width, int height, uint32 id); void xf_MoveWindow(xfInfo* xfi, xfWindow* window, int x, int y, int width, int height); void xf_ShowWindow(xfInfo* xfi, xfWindow* window, uint8 state); void xf_SetWindowIcon(xfInfo* xfi, xfWindow* window, rdpIcon* icon); void xf_SetWindowRects(xfInfo* xfi, xfWindow* window, RECTANGLE_16* rects, int nrects); void xf_SetWindowVisibilityRects(xfInfo* xfi, xfWindow* window, RECTANGLE_16* rects, int nrects); void xf_SetWindowStyle(xfInfo* xfi, xfWindow* window, uint32 style, uint32 ex_style); void xf_UpdateWindowArea(xfInfo* xfi, xfWindow* window, int x, int y, int width, int height); boolean xf_IsWindowBorder(xfInfo* xfi, xfWindow* xfw, int x, int y); void xf_DestroyWindow(xfInfo* xfi, xfWindow* window); void xf_SetWindowMinMaxInfo(xfInfo* xfi, xfWindow* window, int maxWidth, int maxHeight, int maxPosX, int maxPosY, int minTrackWidth, int minTrackHeight, int maxTrackWidth, int maxTrackHeight); void xf_StartLocalMoveSize(xfInfo* xfi, xfWindow* window, int direction, int x, int y); void xf_EndLocalMoveSize(xfInfo *xfi, xfWindow *window); void xf_SendClientEvent(xfInfo *xfi, xfWindow* window, Atom atom, unsigned int numArgs, ...); #endif /* __XF_WINDOW_H */ FreeRDP-1.0.2/client/X11/xfreerdp.1.xml000066400000000000000000000426441207112532300172760ustar00rootroot00000000000000 2011-08-27 The FreeRDP Team xfreerdp 1 freerdp xfreerdp xfreerdp FreeRDP X11 client 2011-08-27 xfreerdp [options] server[:port] [[options] server[:port] …] 2011-08-27 DESCRIPTION xfreerdp is an X11 Remote Desktop Protocol (RDP) client which is part of the FreeRDP project. An RDP server is built-in to many editions of Windows. Alternative servers included xrdp and VRDP (VirtualBox). OPTIONS -0 Attach to the admin console of the server. -a bpp Sets the color depth for the connection to bpp bits per pixel. Valid values are 8, 15, 16, 24 and 32. The default value is the color depth of the FreeRDP-window. -c dir Sets the working-dir to dir. This parameter is only used when an AlternateShell () is requested. dir should contain the executable file specified in the AlternateShell. -D Removes the windows decorations. -d domain Set the domain used in authentication to domain. -f start in full screen mode. This mode can always be en- and disabled using Ctrl-Alt-Enter. -T text Sets the window title to text. -g geometry Sets the size of the FreeRDP window (and of the remote desktop, when establishing a new connection). geometry can have one of the following forms: WxH - in this case the resulting window will be of WxH pixels. P% - in this case the resulting window will be P% of your screen. The special keyword workarea - in this case the resulting window will be of the same size as your workarea. -h Print help. -k id Sets the keyboard-layout-id to id. -K Do not interfere with window manager bindings (don't grab keyboard). -n hostname Set the reported client hostname to hostname. Default is to automatically detect the hostname. -o Play audio on the console instead of redirecting to the client. -p password Password used in authentication. -s shell Sets the startup-shell to shell. This parameter should contain a complete path to the alternate shell. If the alternete shell requires a different working directory use . -t port Connect to port, instead of the default 3389. -u username Username used in authentication. -x flag Set the experience performance flags. flag can be one of: m - (modem): Equivalent to 15. b - (broadband): Equivalent to 1. l - (lan): Equivalent to 0. num - A hexadecimal number that represents a bit-mask, were numbers mean the following Taken from MS-RDPBCGR Section 2.2.1.11.1.1.1 - Extended Info Packet: 1: Disable desktop wallpaper. 2: Disable full-window drag (only the window outline is displayed when the window is moved). 4: Disable menu animations. 8: Disable user interface themes. 20: Disable mouse cursor shadows. 40: Disable cursor blinking. 80: Enable font smoothing. 100: Enable Desktop Composition. -X xid embed xfreerdp into window with xid. -z Enable compression. --app initialize a RemoteApp connection. This implies -g workarea. --no-auth Skips authentication. This is useful e.g. for the current FreeRDP server that doesn't yet support server-side authentication. --authonly Only authenticates. This is useful to test your credentials (username and password). Returns status code 0 if the client can connect. Requires a username, password and connection host at the command line. --no-bmp-cache Disable bitmap cache. --certificate-name name use name for the logon certificate, instead of the server name --composition Enable composition (RDVH only, not to be confused with remote composition). --ext extname load extension extname --no-fastpath Disables fast-path. Use slow-path packets instead, which have larger headers. It might be good for debugging certain issues when you suspect it might be linked to the parsing of one of the two header types. --from-stdin Prompts for unspecified arguments -u username, -p password, -d domain and connection host. This is useful to hide arguments from ps. Also useful for scripts that will feed these arguments to the client via (what else?) stdin. --disable-full-window-drag Disable full window drag. --gdi backend GDI (Graphics Device Interface) rendering backend. backend can be either sw (software) or hw (hardware). --help Print help. --ignore-certificate ignore verification of logon certificate. --kbd-list list all keyboard layout ids used by -k --disable-menu-animations Disable menu animations. --no-motion Don't send mouse motion events. --no-nla Disable network level authentication. --nsc Enable NSCodec. --no-osb Disable off screen bitmaps. --plugin pluginname load pluginname --no-rdp Disable Standard RDP encryption. --rfx Enable RemoteFX. --rfx-mode RemoteFX operational flags. flags can be either v[ideo], i[mage]), default is video. --ntlm version force NTLM protocol version to be version, which can be one of 1 or 2. --sec proto force protocol security. proto can be one of rdp, tls or nla. --secure-checksum Use salted checksums with Standard RDP encryption. --disable-theming Disable theming. --no-tls Disable TLS encryption. --version Print version information. --disable-wallpaper Disable wallpaper. LINKS http://www.freerdp.com/ FreeRDP-1.0.2/client/X11/xfreerdp.c000066400000000000000000000711571207112532300165620ustar00rootroot00000000000000/** * FreeRDP: A Remote Desktop Protocol Client * X11 Client * * Copyright 2011 Marc-Andre Moreau * * 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. */ #include #include #ifdef WITH_XCURSOR #include #endif #ifdef WITH_XINERAMA #include #endif #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include "xf_gdi.h" #include "xf_rail.h" #include "xf_tsmf.h" #include "xf_event.h" #include "xf_cliprdr.h" #include "xf_monitor.h" #include "xf_graphics.h" #include "xf_keyboard.h" #include "xfreerdp.h" static freerdp_sem g_sem; static int g_thread_count = 0; static uint8 g_disconnect_reason = 0; static long xv_port = 0; static const size_t password_size = 512; struct thread_data { freerdp* instance; }; int xf_process_client_args(rdpSettings* settings, const char* opt, const char* val, void* user_data); int xf_process_plugin_args(rdpSettings* settings, const char* name, RDP_PLUGIN_DATA* plugin_data, void* user_data); void xf_context_new(freerdp* instance, rdpContext* context) { context->channels = freerdp_channels_new(); } void xf_context_free(freerdp* instance, rdpContext* context) { } void xf_sw_begin_paint(rdpContext* context) { rdpGdi* gdi = context->gdi; gdi->primary->hdc->hwnd->invalid->null = 1; gdi->primary->hdc->hwnd->ninvalid = 0; } void xf_sw_end_paint(rdpContext* context) { rdpGdi* gdi; xfInfo* xfi; sint32 x, y; uint32 w, h; xfi = ((xfContext*) context)->xfi; gdi = context->gdi; if (xfi->remote_app != true) { if (xfi->complex_regions != true) { if (gdi->primary->hdc->hwnd->invalid->null) return; x = gdi->primary->hdc->hwnd->invalid->x; y = gdi->primary->hdc->hwnd->invalid->y; w = gdi->primary->hdc->hwnd->invalid->w; h = gdi->primary->hdc->hwnd->invalid->h; XPutImage(xfi->display, xfi->primary, xfi->gc, xfi->image, x, y, x, y, w, h); XCopyArea(xfi->display, xfi->primary, xfi->window->handle, xfi->gc, x, y, w, h, x, y); } else { int i; int ninvalid; HGDI_RGN cinvalid; if (gdi->primary->hdc->hwnd->ninvalid < 1) return; ninvalid = gdi->primary->hdc->hwnd->ninvalid; cinvalid = gdi->primary->hdc->hwnd->cinvalid; for (i = 0; i < ninvalid; i++) { x = cinvalid[i].x; y = cinvalid[i].y; w = cinvalid[i].w; h = cinvalid[i].h; XPutImage(xfi->display, xfi->primary, xfi->gc, xfi->image, x, y, x, y, w, h); XCopyArea(xfi->display, xfi->primary, xfi->window->handle, xfi->gc, x, y, w, h, x, y); } XFlush(xfi->display); } } else { if (gdi->primary->hdc->hwnd->invalid->null) return; x = gdi->primary->hdc->hwnd->invalid->x; y = gdi->primary->hdc->hwnd->invalid->y; w = gdi->primary->hdc->hwnd->invalid->w; h = gdi->primary->hdc->hwnd->invalid->h; xf_rail_paint(xfi, context->rail, x, y, x + w - 1, y + h - 1); } } void xf_sw_desktop_resize(rdpContext* context) { xfInfo* xfi; rdpSettings* settings; xfi = ((xfContext*) context)->xfi; settings = xfi->instance->settings; if (xfi->fullscreen != true) { rdpGdi* gdi = context->gdi; gdi_resize(gdi, xfi->width, xfi->height); if (xfi->image) { xfi->image->data = NULL; XDestroyImage(xfi->image); xfi->image = XCreateImage(xfi->display, xfi->visual, xfi->depth, ZPixmap, 0, (char*) gdi->primary_buffer, gdi->width, gdi->height, xfi->scanline_pad, 0); } } } void xf_hw_begin_paint(rdpContext* context) { xfInfo* xfi; xfi = ((xfContext*) context)->xfi; xfi->hdc->hwnd->invalid->null = 1; xfi->hdc->hwnd->ninvalid = 0; } void xf_hw_end_paint(rdpContext* context) { xfInfo* xfi; sint32 x, y; uint32 w, h; xfi = ((xfContext*) context)->xfi; if (xfi->remote_app) { if (xfi->hdc->hwnd->invalid->null) return; x = xfi->hdc->hwnd->invalid->x; y = xfi->hdc->hwnd->invalid->y; w = xfi->hdc->hwnd->invalid->w; h = xfi->hdc->hwnd->invalid->h; xf_rail_paint(xfi, context->rail, x, y, x + w - 1, y + h - 1); } } void xf_hw_desktop_resize(rdpContext* context) { xfInfo* xfi; boolean same; rdpSettings* settings; xfi = ((xfContext*) context)->xfi; settings = xfi->instance->settings; if (xfi->fullscreen != true) { xfi->width = settings->width; xfi->height = settings->height; if (xfi->window) xf_ResizeDesktopWindow(xfi, xfi->window, settings->width, settings->height); if (xfi->primary) { same = (xfi->primary == xfi->drawing) ? true : false; XFreePixmap(xfi->display, xfi->primary); xfi->primary = XCreatePixmap(xfi->display, xfi->drawable, xfi->width, xfi->height, xfi->depth); if (same) xfi->drawing = xfi->primary; } } } boolean xf_get_fds(freerdp* instance, void** rfds, int* rcount, void** wfds, int* wcount) { xfInfo* xfi = ((xfContext*) instance->context)->xfi; rfds[*rcount] = (void*)(long)(xfi->xfds); (*rcount)++; return true; } boolean xf_check_fds(freerdp* instance, fd_set* set) { XEvent xevent; xfInfo* xfi = ((xfContext*) instance->context)->xfi; while (XPending(xfi->display)) { memset(&xevent, 0, sizeof(xevent)); XNextEvent(xfi->display, &xevent); if (xf_event_process(instance, &xevent) != true) return false; } return true; } void xf_create_window(xfInfo* xfi) { XEvent xevent; char* win_title; int width, height; width = xfi->width; height = xfi->height; xfi->attribs.background_pixel = BlackPixelOfScreen(xfi->screen); xfi->attribs.border_pixel = WhitePixelOfScreen(xfi->screen); xfi->attribs.backing_store = xfi->primary ? NotUseful : Always; xfi->attribs.override_redirect = xfi->fullscreen; xfi->attribs.colormap = xfi->colormap; xfi->attribs.bit_gravity = NorthWestGravity; xfi->attribs.win_gravity = NorthWestGravity; if (xfi->instance->settings->window_title != NULL) { win_title = xstrdup(xfi->instance->settings->window_title); } else if (xfi->instance->settings->port == 3389) { win_title = xmalloc(1 + sizeof("FreeRDP: ") + strlen(xfi->instance->settings->hostname)); sprintf(win_title, "FreeRDP: %s", xfi->instance->settings->hostname); } else { win_title = xmalloc(1 + sizeof("FreeRDP: ") + strlen(xfi->instance->settings->hostname) + sizeof(":00000")); sprintf(win_title, "FreeRDP: %s:%i", xfi->instance->settings->hostname, xfi->instance->settings->port); } xfi->window = xf_CreateDesktopWindow(xfi, win_title, width, height, xfi->decorations); xfree(win_title); if (xfi->fullscreen) xf_SetWindowFullscreen(xfi, xfi->window, xfi->fullscreen); xfi->unobscured = (xevent.xvisibility.state == VisibilityUnobscured); XSetWMProtocols(xfi->display, xfi->window->handle, &(xfi->WM_DELETE_WINDOW), 1); xfi->drawable = xfi->window->handle; } void xf_toggle_fullscreen(xfInfo* xfi) { Pixmap contents = 0; contents = XCreatePixmap(xfi->display, xfi->window->handle, xfi->width, xfi->height, xfi->depth); XCopyArea(xfi->display, xfi->primary, contents, xfi->gc, 0, 0, xfi->width, xfi->height, 0, 0); XDestroyWindow(xfi->display, xfi->window->handle); xfi->fullscreen = (xfi->fullscreen) ? false : true; xf_create_window(xfi); XCopyArea(xfi->display, contents, xfi->primary, xfi->gc, 0, 0, xfi->width, xfi->height, 0, 0); XFreePixmap(xfi->display, contents); } boolean xf_get_pixmap_info(xfInfo* xfi) { int i; int vi_count; int pf_count; XVisualInfo* vi; XVisualInfo* vis; XVisualInfo template; XPixmapFormatValues* pf; XPixmapFormatValues* pfs; XWindowAttributes window_attributes; pfs = XListPixmapFormats(xfi->display, &pf_count); if (pfs == NULL) { printf("xf_get_pixmap_info: XListPixmapFormats failed\n"); return 1; } for (i = 0; i < pf_count; i++) { pf = pfs + i; if (pf->depth == xfi->depth) { xfi->bpp = pf->bits_per_pixel; xfi->scanline_pad = pf->scanline_pad; break; } } XFree(pfs); memset(&template, 0, sizeof(template)); template.class = TrueColor; template.screen = xfi->screen_number; if (XGetWindowAttributes(xfi->display, RootWindowOfScreen(xfi->screen), &window_attributes) == 0) { printf("xf_get_pixmap_info: XGetWindowAttributes failed\n"); return false; } vis = XGetVisualInfo(xfi->display, VisualClassMask | VisualScreenMask, &template, &vi_count); if (vis == NULL) { printf("xf_get_pixmap_info: XGetVisualInfo failed\n"); return false; } vi = NULL; for (i = 0; i < vi_count; i++) { vi = vis + i; if (vi->visual == window_attributes.visual) { xfi->visual = vi->visual; break; } } if (vi) { /* * Detect if the server visual has an inverted colormap * (BGR vs RGB, or red being the least significant byte) */ if (vi->red_mask & 0xFF) { xfi->clrconv->invert = true; } } XFree(vis); if ((xfi->visual == NULL) || (xfi->scanline_pad == 0)) { return false; } return true; } static int (*_def_error_handler)(Display*, XErrorEvent*); int xf_error_handler(Display* d, XErrorEvent* ev) { char buf[256]; int do_abort = true; XGetErrorText(d, ev->error_code, buf, sizeof(buf)); printf("%s", buf); if (do_abort) abort(); _def_error_handler(d, ev); return false; } int _xf_error_handler(Display* d, XErrorEvent* ev) { /* * ungrab the keyboard, in case a debugger is running in * another window. This make xf_error_handler() a potential * debugger breakpoint. */ XUngrabKeyboard(d, CurrentTime); return xf_error_handler(d, ev); } boolean xf_pre_connect(freerdp* instance) { xfInfo* xfi; boolean bitmap_cache; rdpSettings* settings; int arg_parse_result; xfi = (xfInfo*) xzalloc(sizeof(xfInfo)); ((xfContext*) instance->context)->xfi = xfi; xfi->_context = instance->context; xfi->context = (xfContext*) instance->context; xfi->context->settings = instance->settings; xfi->instance = instance; arg_parse_result = freerdp_parse_args(instance->settings, instance->context->argc,instance->context->argv, xf_process_plugin_args, instance->context->channels, xf_process_client_args, xfi); if (arg_parse_result < 0) { if (arg_parse_result == FREERDP_ARGS_PARSE_FAILURE) printf("failed to parse arguments.\n"); exit(XF_EXIT_PARSE_ARGUMENTS); } settings = instance->settings; bitmap_cache = settings->bitmap_cache; settings->os_major_type = OSMAJORTYPE_UNIX; settings->os_minor_type = OSMINORTYPE_NATIVE_XSERVER; settings->order_support[NEG_DSTBLT_INDEX] = true; settings->order_support[NEG_PATBLT_INDEX] = true; settings->order_support[NEG_SCRBLT_INDEX] = true; settings->order_support[NEG_OPAQUE_RECT_INDEX] = true; settings->order_support[NEG_DRAWNINEGRID_INDEX] = false; settings->order_support[NEG_MULTIDSTBLT_INDEX] = false; settings->order_support[NEG_MULTIPATBLT_INDEX] = false; settings->order_support[NEG_MULTISCRBLT_INDEX] = false; settings->order_support[NEG_MULTIOPAQUERECT_INDEX] = true; settings->order_support[NEG_MULTI_DRAWNINEGRID_INDEX] = false; settings->order_support[NEG_LINETO_INDEX] = true; settings->order_support[NEG_POLYLINE_INDEX] = true; settings->order_support[NEG_MEMBLT_INDEX] = bitmap_cache; settings->order_support[NEG_MEM3BLT_INDEX] = false; settings->order_support[NEG_MEMBLT_V2_INDEX] = bitmap_cache; settings->order_support[NEG_MEM3BLT_V2_INDEX] = false; settings->order_support[NEG_SAVEBITMAP_INDEX] = false; settings->order_support[NEG_GLYPH_INDEX_INDEX] = true; settings->order_support[NEG_FAST_INDEX_INDEX] = true; settings->order_support[NEG_FAST_GLYPH_INDEX] = true; settings->order_support[NEG_POLYGON_SC_INDEX] = false; settings->order_support[NEG_POLYGON_CB_INDEX] = false; settings->order_support[NEG_ELLIPSE_SC_INDEX] = false; settings->order_support[NEG_ELLIPSE_CB_INDEX] = false; freerdp_channels_pre_connect(xfi->_context->channels, instance); if (settings->authentication_only) { /* Check --authonly has a username and password. */ if (settings->username == NULL ) { fprintf(stderr, "--authonly, but no -u username. Please provide one.\n"); exit(1); } if (settings->password == NULL ) { fprintf(stderr, "--authonly, but no -p password. Please provide one.\n"); exit(1); } fprintf(stderr, "%s:%d: Authentication only. Don't connect to X.\n", __FILE__, __LINE__); // Avoid XWindows initialization and configuration below. return true; } xfi->display = XOpenDisplay(NULL); if (xfi->display == NULL) { printf("xf_pre_connect: failed to open display: %s\n", XDisplayName(NULL)); printf("Please check that the $DISPLAY environment variable is properly set.\n"); return false; } if (xfi->debug) { printf("Enabling X11 debug mode.\n"); XSynchronize(xfi->display, true); _def_error_handler = XSetErrorHandler(_xf_error_handler); } xfi->_NET_WM_ICON = XInternAtom(xfi->display, "_NET_WM_ICON", False); xfi->_MOTIF_WM_HINTS = XInternAtom(xfi->display, "_MOTIF_WM_HINTS", False); xfi->_NET_CURRENT_DESKTOP = XInternAtom(xfi->display, "_NET_CURRENT_DESKTOP", False); xfi->_NET_WORKAREA = XInternAtom(xfi->display, "_NET_WORKAREA", False); xfi->_NET_WM_STATE = XInternAtom(xfi->display, "_NET_WM_STATE", False); xfi->_NET_WM_STATE_FULLSCREEN = XInternAtom(xfi->display, "_NET_WM_STATE_FULLSCREEN", False); xfi->_NET_WM_WINDOW_TYPE = XInternAtom(xfi->display, "_NET_WM_WINDOW_TYPE", False); xfi->_NET_WM_WINDOW_TYPE_NORMAL = XInternAtom(xfi->display, "_NET_WM_WINDOW_TYPE_NORMAL", False); xfi->_NET_WM_WINDOW_TYPE_DIALOG = XInternAtom(xfi->display, "_NET_WM_WINDOW_TYPE_DIALOG", False); xfi->_NET_WM_WINDOW_TYPE_POPUP= XInternAtom(xfi->display, "_NET_WM_WINDOW_TYPE_POPUP", False); xfi->_NET_WM_WINDOW_TYPE_UTILITY = XInternAtom(xfi->display, "_NET_WM_WINDOW_TYPE_UTILITY", False); xfi->_NET_WM_WINDOW_TYPE_DROPDOWN_MENU = XInternAtom(xfi->display, "_NET_WM_WINDOW_TYPE_DROPDOWN_MENU", False); xfi->_NET_WM_STATE_SKIP_TASKBAR = XInternAtom(xfi->display, "_NET_WM_STATE_SKIP_TASKBAR", False); xfi->_NET_WM_STATE_SKIP_PAGER = XInternAtom(xfi->display, "_NET_WM_STATE_SKIP_PAGER", False); xfi->_NET_WM_MOVERESIZE = XInternAtom(xfi->display, "_NET_WM_MOVERESIZE", False); xfi->_NET_MOVERESIZE_WINDOW = XInternAtom(xfi->display, "_NET_MOVERESIZE_WINDOW", False); xfi->WM_PROTOCOLS = XInternAtom(xfi->display, "WM_PROTOCOLS", False); xfi->WM_DELETE_WINDOW = XInternAtom(xfi->display, "WM_DELETE_WINDOW", False); xf_kbd_init(xfi); xfi->clrconv = freerdp_clrconv_new(CLRCONV_ALPHA); instance->context->cache = cache_new(instance->settings); xfi->xfds = ConnectionNumber(xfi->display); xfi->screen_number = DefaultScreen(xfi->display); xfi->screen = ScreenOfDisplay(xfi->display, xfi->screen_number); xfi->depth = DefaultDepthOfScreen(xfi->screen); xfi->big_endian = (ImageByteOrder(xfi->display) == MSBFirst); xfi->mouse_motion = settings->mouse_motion; xfi->complex_regions = true; xfi->decorations = settings->decorations; xfi->fullscreen = settings->fullscreen; xfi->grab_keyboard = settings->grab_keyboard; xfi->fullscreen_toggle = true; xfi->sw_gdi = settings->sw_gdi; xfi->parent_window = (Window) settings->parent_window_xid; xf_detect_monitors(xfi, settings); return true; } void cpuid(unsigned info, unsigned *eax, unsigned *ebx, unsigned *ecx, unsigned *edx) { #ifdef __GNUC__ #if defined(__i386__) || defined(__x86_64__) __asm volatile ( /* The EBX (or RBX register on x86_64) is used for the PIC base address and must not be corrupted by our inline assembly. */ #if defined(__i386__) "mov %%ebx, %%esi;" "cpuid;" "xchg %%ebx, %%esi;" #else "mov %%rbx, %%rsi;" "cpuid;" "xchg %%rbx, %%rsi;" #endif : "=a" (*eax), "=S" (*ebx), "=c" (*ecx), "=d" (*edx) : "0" (info) ); #endif #endif } uint32 xf_detect_cpu() { unsigned int eax, ebx, ecx, edx = 0; uint32 cpu_opt = 0; cpuid(1, &eax, &ebx, &ecx, &edx); if (edx & (1<<26)) { DEBUG("SSE2 detected"); cpu_opt |= CPU_SSE2; } return cpu_opt; } boolean xf_post_connect(freerdp* instance) { xfInfo* xfi; XGCValues gcv; rdpCache* cache; rdpChannels* channels; RFX_CONTEXT* rfx_context = NULL; xfi = ((xfContext*) instance->context)->xfi; cache = instance->context->cache; channels = xfi->_context->channels; if (instance->settings->authentication_only) return true; if (xf_get_pixmap_info(xfi) != true) return false; xf_register_graphics(instance->context->graphics); if (xfi->sw_gdi) { rdpGdi* gdi; uint32 flags; flags = CLRCONV_ALPHA; if (xfi->bpp > 16) flags |= CLRBUF_32BPP; else flags |= CLRBUF_16BPP; gdi_init(instance, flags, NULL); gdi = instance->context->gdi; xfi->primary_buffer = gdi->primary_buffer; rfx_context = gdi->rfx_context; } else { xfi->srcBpp = instance->settings->color_depth; xf_gdi_register_update_callbacks(instance->update); xfi->hdc = gdi_CreateDC(xfi->clrconv, xfi->bpp); if (instance->settings->rfx_codec) { rfx_context = (void*) rfx_context_new(); xfi->rfx_context = rfx_context; } if (instance->settings->ns_codec) xfi->nsc_context = (void*) nsc_context_new(); } if (rfx_context) { #ifdef WITH_SSE2 /* detect only if needed */ rfx_context_set_cpu_opt(rfx_context, xf_detect_cpu()); #endif } xfi->width = instance->settings->width; xfi->height = instance->settings->height; xf_create_window(xfi); memset(&gcv, 0, sizeof(gcv)); xfi->modifier_map = XGetModifierMapping(xfi->display); xfi->gc = XCreateGC(xfi->display, xfi->drawable, GCGraphicsExposures, &gcv); xfi->primary = XCreatePixmap(xfi->display, xfi->drawable, xfi->width, xfi->height, xfi->depth); xfi->drawing = xfi->primary; xfi->bitmap_mono = XCreatePixmap(xfi->display, xfi->drawable, 8, 8, 1); xfi->gc_mono = XCreateGC(xfi->display, xfi->bitmap_mono, GCGraphicsExposures, &gcv); XSetForeground(xfi->display, xfi->gc, BlackPixelOfScreen(xfi->screen)); XFillRectangle(xfi->display, xfi->primary, xfi->gc, 0, 0, xfi->width, xfi->height); xfi->image = XCreateImage(xfi->display, xfi->visual, xfi->depth, ZPixmap, 0, (char*) xfi->primary_buffer, xfi->width, xfi->height, xfi->scanline_pad, 0); xfi->bmp_codec_none = (uint8*) xmalloc(64 * 64 * 4); if (xfi->sw_gdi) { instance->update->BeginPaint = xf_sw_begin_paint; instance->update->EndPaint = xf_sw_end_paint; instance->update->DesktopResize = xf_sw_desktop_resize; } else { instance->update->BeginPaint = xf_hw_begin_paint; instance->update->EndPaint = xf_hw_end_paint; instance->update->DesktopResize = xf_hw_desktop_resize; } pointer_cache_register_callbacks(instance->update); if (xfi->sw_gdi != true) { glyph_cache_register_callbacks(instance->update); brush_cache_register_callbacks(instance->update); bitmap_cache_register_callbacks(instance->update); offscreen_cache_register_callbacks(instance->update); palette_cache_register_callbacks(instance->update); } instance->context->rail = rail_new(instance->settings); rail_register_update_callbacks(instance->context->rail, instance->update); xf_rail_register_callbacks(xfi, instance->context->rail); freerdp_channels_post_connect(channels, instance); xf_tsmf_init(xfi, xv_port); xf_cliprdr_init(xfi, channels); return true; } boolean xf_authenticate(freerdp* instance, char** username, char** password, char** domain) { *password = xmalloc(password_size * sizeof(char)); if (freerdp_passphrase_read("Password: ", *password, password_size, instance->settings->from_stdin) == NULL) return false; return true; } boolean xf_verify_certificate(freerdp* instance, char* subject, char* issuer, char* fingerprint) { char answer; printf("Certificate details:\n"); printf("\tSubject: %s\n", subject); printf("\tIssuer: %s\n", issuer); printf("\tThumbprint: %s\n", fingerprint); printf("The above X.509 certificate could not be verified, possibly because you do not have " "the CA certificate in your certificate store, or the certificate has expired. " "Please look at the documentation on how to create local certificate store for a private CA.\n"); while (1) { printf("Do you trust the above certificate? (Y/N) "); answer = fgetc(stdin); if (feof(stdin)) { printf("\nError: Could not read answer from stdin."); if (instance->settings->from_stdin) printf(" - Run without parameter \"--from-stdin\" to set trust."); printf("\n"); return false; } if (answer == 'y' || answer == 'Y') { return true; } else if (answer == 'n' || answer == 'N') { break; } printf("\n"); } return false; } int xf_process_client_args(rdpSettings* settings, const char* opt, const char* val, void* user_data) { int argc = 0; xfInfo* xfi = (xfInfo*) user_data; if (strcmp("--kbd-list", opt) == 0) { int i; rdpKeyboardLayout* layouts; layouts = freerdp_kbd_get_layouts(RDP_KEYBOARD_LAYOUT_TYPE_STANDARD); printf("\nKeyboard Layouts\n"); for (i = 0; layouts[i].code; i++) printf("0x%08X\t%s\n", layouts[i].code, layouts[i].name); free(layouts); layouts = freerdp_kbd_get_layouts(RDP_KEYBOARD_LAYOUT_TYPE_VARIANT); printf("\nKeyboard Layout Variants\n"); for (i = 0; layouts[i].code; i++) printf("0x%08X\t%s\n", layouts[i].code, layouts[i].name); free(layouts); layouts = freerdp_kbd_get_layouts(RDP_KEYBOARD_LAYOUT_TYPE_IME); printf("\nKeyboard Input Method Editors (IMEs)\n"); for (i = 0; layouts[i].code; i++) printf("0x%08X\t%s\n", layouts[i].code, layouts[i].name); free(layouts); exit(0); } else if (strcmp("--xv-port", opt) == 0) { xv_port = atoi(val); argc = 2; } else if (strcmp("--dbg-x11", opt) == 0) { xfi->debug = true; argc = 1; } return argc; } int xf_process_plugin_args(rdpSettings* settings, const char* name, RDP_PLUGIN_DATA* plugin_data, void* user_data) { rdpChannels* channels = (rdpChannels*) user_data; printf("loading plugin %s\n", name); freerdp_channels_load_plugin(channels, settings, name, plugin_data); return 1; } int xf_receive_channel_data(freerdp* instance, int channelId, uint8* data, int size, int flags, int total_size) { return freerdp_channels_data(instance, channelId, data, size, flags, total_size); } void xf_process_channel_event(rdpChannels* chanman, freerdp* instance) { xfInfo* xfi; RDP_EVENT* event; xfi = ((xfContext*) instance->context)->xfi; event = freerdp_channels_pop_event(chanman); if (event) { switch (event->event_class) { case RDP_EVENT_CLASS_RAIL: xf_process_rail_event(xfi, chanman, event); break; case RDP_EVENT_CLASS_TSMF: xf_process_tsmf_event(xfi, event); break; case RDP_EVENT_CLASS_CLIPRDR: xf_process_cliprdr_event(xfi, event); break; default: break; } freerdp_event_free(event); } } void xf_window_free(xfInfo* xfi) { rdpContext* context = xfi->instance->context; XFreeModifiermap(xfi->modifier_map); xfi->modifier_map = 0; XFreeGC(xfi->display, xfi->gc); xfi->gc = 0; XFreeGC(xfi->display, xfi->gc_mono); xfi->gc_mono = 0; if (xfi->window != NULL) { xf_DestroyWindow(xfi, xfi->window); xfi->window = NULL; } if (xfi->primary) { XFreePixmap(xfi->display, xfi->primary); xfi->primary = 0; } if (xfi->image) { xfi->image->data = NULL; XDestroyImage(xfi->image); xfi->image = NULL; } if (context != NULL) { cache_free(context->cache); context->cache = NULL; rail_free(context->rail); context->rail = NULL; } if (xfi->rfx_context) { rfx_context_free(xfi->rfx_context); xfi->rfx_context = NULL; } freerdp_clrconv_free(xfi->clrconv); if (xfi->hdc) gdi_DeleteDC(xfi->hdc); xf_tsmf_uninit(xfi); xf_cliprdr_uninit(xfi); } void xf_free(xfInfo* xfi) { xf_window_free(xfi); xfree(xfi->bmp_codec_none); XCloseDisplay(xfi->display); xfree(xfi); } int xfreerdp_run(freerdp* instance) { int i; int fds; xfInfo* xfi; int max_fds; int rcount; int wcount; int ret = 0; void* rfds[32]; void* wfds[32]; fd_set rfds_set; fd_set wfds_set; int select_status; rdpChannels* channels; struct timeval timeout; memset(rfds, 0, sizeof(rfds)); memset(wfds, 0, sizeof(wfds)); memset(&timeout, 0, sizeof(struct timeval)); if (!freerdp_connect(instance)) return XF_EXIT_CONN_FAILED; if (instance->settings->authentication_only) { freerdp_disconnect(instance); freerdp_free(instance); return ret; } xfi = ((xfContext*) instance->context)->xfi; channels = instance->context->channels; while (!xfi->disconnect && !freerdp_shall_disconnect(instance)) { rcount = 0; wcount = 0; if (freerdp_get_fds(instance, rfds, &rcount, wfds, &wcount) != true) { printf("Failed to get FreeRDP file descriptor\n"); ret = XF_EXIT_CONN_FAILED; break; } if (freerdp_channels_get_fds(channels, instance, rfds, &rcount, wfds, &wcount) != true) { printf("Failed to get channel manager file descriptor\n"); ret = XF_EXIT_CONN_FAILED; break; } if (xf_get_fds(instance, rfds, &rcount, wfds, &wcount) != true) { printf("Failed to get xfreerdp file descriptor\n"); ret = XF_EXIT_CONN_FAILED; break; } max_fds = 0; FD_ZERO(&rfds_set); FD_ZERO(&wfds_set); for (i = 0; i < rcount; i++) { fds = (int)(long)(rfds[i]); if (fds > max_fds) max_fds = fds; FD_SET(fds, &rfds_set); } if (max_fds == 0) break; timeout.tv_sec = 5; select_status = select(max_fds + 1, &rfds_set, &wfds_set, NULL, &timeout); if (select_status == 0) { //freerdp_send_keep_alive(instance); continue; } else if (select_status == -1) { /* these are not really errors */ if (!((errno == EAGAIN) || (errno == EWOULDBLOCK) || (errno == EINPROGRESS) || (errno == EINTR))) /* signal occurred */ { printf("xfreerdp_run: select failed\n"); break; } } if (freerdp_check_fds(instance) != true) { printf("Failed to check FreeRDP file descriptor\n"); break; } if (xf_check_fds(instance, &rfds_set) != true) { printf("Failed to check xfreerdp file descriptor\n"); break; } if (freerdp_channels_check_fds(channels, instance) != true) { printf("Failed to check channel manager file descriptor\n"); break; } xf_process_channel_event(channels, instance); } if (!ret) ret = freerdp_error_info(instance); freerdp_channels_close(channels, instance); freerdp_channels_free(channels); freerdp_disconnect(instance); gdi_free(instance); xf_free(xfi); freerdp_free(instance); return ret; } void* thread_func(void* param) { struct thread_data* data; data = (struct thread_data*) param; g_disconnect_reason = xfreerdp_run(data->instance); xfree(data); pthread_detach(pthread_self()); g_thread_count--; if (g_thread_count < 1) freerdp_sem_signal(g_sem); pthread_exit(NULL); } static uint8 exit_code_from_disconnect_reason(uint32 reason) { if (reason == 0 || (reason >= XF_EXIT_PARSE_ARGUMENTS && reason <= XF_EXIT_CONN_FAILED)) return reason; /* Licence error set */ else if (reason >= 0x100 && reason <= 0x10A) reason -= 0x100 + XF_EXIT_LICENSE_INTERNAL; /* RDP protocol error set */ else if (reason >= 0x10c9 && reason <= 0x1193) reason = XF_EXIT_RDP; /* There's no need to test protocol-independent codes: they match */ else if (!(reason <= 0xB)) reason = XF_EXIT_UNKNOWN; return reason; } int main(int argc, char* argv[]) { pthread_t thread; freerdp* instance; struct thread_data* data; freerdp_handle_signals(); setlocale(LC_ALL, ""); freerdp_channels_global_init(); g_sem = freerdp_sem_new(1); instance = freerdp_new(); instance->PreConnect = xf_pre_connect; instance->PostConnect = xf_post_connect; instance->Authenticate = xf_authenticate; instance->VerifyCertificate = xf_verify_certificate; instance->ReceiveChannelData = xf_receive_channel_data; instance->context_size = sizeof(xfContext); instance->ContextNew = (pContextNew) xf_context_new; instance->ContextFree = (pContextFree) xf_context_free; freerdp_context_new(instance); instance->context->argc = argc; instance->context->argv = argv; instance->settings->sw_gdi = false; data = (struct thread_data*) xzalloc(sizeof(struct thread_data)); data->instance = instance; g_thread_count++; pthread_create(&thread, 0, thread_func, data); while (g_thread_count > 0) { freerdp_sem_wait(g_sem); } freerdp_channels_global_uninit(); return exit_code_from_disconnect_reason(g_disconnect_reason); } FreeRDP-1.0.2/client/X11/xfreerdp.h000066400000000000000000000112541207112532300165570ustar00rootroot00000000000000/** * FreeRDP: A Remote Desktop Protocol Client * X11 Client * * Copyright 2011 Marc-Andre Moreau * * 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. */ #ifndef __XFREERDP_H #define __XFREERDP_H #include #include #include #include #include #include #include typedef struct xf_info xfInfo; #include "xf_window.h" #include "xf_monitor.h" struct xf_WorkArea { uint32 x; uint32 y; uint32 width; uint32 height; }; typedef struct xf_WorkArea xfWorkArea; struct xf_pointer { rdpPointer pointer; Cursor cursor; }; typedef struct xf_pointer xfPointer; struct xf_bitmap { rdpBitmap bitmap; Pixmap pixmap; }; typedef struct xf_bitmap xfBitmap; struct xf_glyph { rdpGlyph glyph; Pixmap pixmap; }; typedef struct xf_glyph xfGlyph; struct xf_context { rdpContext _p; xfInfo* xfi; rdpSettings* settings; }; typedef struct xf_context xfContext; struct xf_info { freerdp* instance; xfContext* context; rdpContext* _context; GC gc; int bpp; int xfds; int depth; int width; int height; int srcBpp; GC gc_mono; Screen* screen; XImage* image; Pixmap primary; Pixmap drawing; Visual* visual; Display* display; Drawable drawable; Pixmap bitmap_mono; Colormap colormap; int screen_number; int scanline_pad; boolean big_endian; boolean fullscreen; boolean grab_keyboard; boolean unobscured; boolean decorations; boolean debug; xfWindow* window; xfWorkArea workArea; int current_desktop; boolean remote_app; boolean disconnect; HCLRCONV clrconv; Window parent_window; HGDI_DC hdc; boolean sw_gdi; uint8* primary_buffer; boolean focused; boolean mouse_active; boolean mouse_motion; boolean fullscreen_toggle; uint32 keyboard_layout_id; boolean pressed_keys[256]; XModifierKeymap* modifier_map; XSetWindowAttributes attribs; boolean complex_regions; VIRTUAL_SCREEN vscreen; uint8* bmp_codec_none; uint8* bmp_codec_nsc; void* rfx_context; void* nsc_context; void* xv_context; void* clipboard_context; Atom _NET_WM_ICON; Atom _MOTIF_WM_HINTS; Atom _NET_CURRENT_DESKTOP; Atom _NET_WORKAREA; Atom _NET_WM_STATE; Atom _NET_WM_STATE_FULLSCREEN; Atom _NET_WM_STATE_SKIP_TASKBAR; Atom _NET_WM_STATE_SKIP_PAGER; Atom _NET_WM_WINDOW_TYPE; Atom _NET_WM_WINDOW_TYPE_NORMAL; Atom _NET_WM_WINDOW_TYPE_DIALOG; Atom _NET_WM_WINDOW_TYPE_UTILITY; Atom _NET_WM_WINDOW_TYPE_POPUP; Atom _NET_WM_WINDOW_TYPE_DROPDOWN_MENU; Atom _NET_WM_MOVERESIZE; Atom _NET_MOVERESIZE_WINDOW; Atom WM_PROTOCOLS; Atom WM_DELETE_WINDOW; }; void xf_toggle_fullscreen(xfInfo* xfi); boolean xf_post_connect(freerdp* instance); enum XF_EXIT_CODE { /* section 0-15: protocol-independent codes */ XF_EXIT_SUCCESS = 0, XF_EXIT_DISCONNECT = 1, XF_EXIT_LOGOFF = 2, XF_EXIT_IDLE_TIMEOUT = 3, XF_EXIT_LOGON_TIMEOUT = 4, XF_EXIT_CONN_REPLACED = 5, XF_EXIT_OUT_OF_MEMORY = 6, XF_EXIT_CONN_DENIED = 7, XF_EXIT_CONN_DENIED_FIPS = 8, XF_EXIT_USER_PRIVILEGES = 9, XF_EXIT_FRESH_CREDENTIALS_REQUIRED = 10, XF_EXIT_DISCONNECT_BY_USER = 11, /* section 16-31: license error set */ XF_EXIT_LICENSE_INTERNAL = 16, XF_EXIT_LICENSE_NO_LICENSE_SERVER = 17, XF_EXIT_LICENSE_NO_LICENSE = 18, XF_EXIT_LICENSE_BAD_CLIENT_MSG = 19, XF_EXIT_LICENSE_HWID_DOESNT_MATCH = 20, XF_EXIT_LICENSE_BAD_CLIENT = 21, XF_EXIT_LICENSE_CANT_FINISH_PROTOCOL = 22, XF_EXIT_LICENSE_CLIENT_ENDED_PROTOCOL = 23, XF_EXIT_LICENSE_BAD_CLIENT_ENCRYPTION = 24, XF_EXIT_LICENSE_CANT_UPGRADE = 25, XF_EXIT_LICENSE_NO_REMOTE_CONNECTIONS = 26, /* section 32-127: RDP protocol error set */ XF_EXIT_RDP = 32, /* section 128-254: xfreerdp specific exit codes */ XF_EXIT_PARSE_ARGUMENTS = 128, XF_EXIT_MEMORY = 129, XF_EXIT_PROTOCOL = 130, XF_EXIT_CONN_FAILED = 131, XF_EXIT_UNKNOWN = 255, }; #ifdef WITH_DEBUG_X11 #define DEBUG_X11(fmt, ...) DEBUG_CLASS(X11, fmt, ## __VA_ARGS__) #else #define DEBUG_X11(fmt, ...) DEBUG_NULL(fmt, ## __VA_ARGS__) #endif #ifdef WITH_DEBUG_X11_LOCAL_MOVESIZE #define DEBUG_X11_LMS(fmt, ...) DEBUG_CLASS(X11_LMS, fmt, ## __VA_ARGS__) #else #define DEBUG_X11_LMS(fmt, ...) DEBUG_NULL(fmt, ## __VA_ARGS__) #endif #endif /* __XFREERDP_H */ FreeRDP-1.0.2/client/test/000077500000000000000000000000001207112532300151725ustar00rootroot00000000000000FreeRDP-1.0.2/client/test/CMakeLists.txt000066400000000000000000000020401207112532300177260ustar00rootroot00000000000000# FreeRDP: A Remote Desktop Protocol Client # FreeRDP Test UI cmake build script # # Copyright 2011 O.S. Systems Software Ltda. # Copyright 2011 Otavio Salvador # Copyright 2011 Marc-Andre Moreau # # 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. add_executable(freerdp-test freerdp.c) target_link_libraries(freerdp-test freerdp-core) target_link_libraries(freerdp-test freerdp-gdi) target_link_libraries(freerdp-test freerdp-utils) target_link_libraries(freerdp-test freerdp-channels ${CMAKE_DL_LIBS}) FreeRDP-1.0.2/client/test/freerdp.c000066400000000000000000000175461207112532300170020ustar00rootroot00000000000000/** * FreeRDP: A Remote Desktop Protocol Client * FreeRDP Test UI * * Copyright 2011 Marc-Andre Moreau * * 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. */ #ifndef _WIN32 #include #include #include #else #include #include #include #endif #include #include #include #include #include #include #include #include #include #include #include struct tf_info { void* data; }; typedef struct tf_info tfInfo; struct tf_context { rdpContext _p; tfInfo* tfi; }; typedef struct tf_context tfContext; freerdp_sem g_sem; static int g_thread_count = 0; struct thread_data { freerdp* instance; }; #include #include void tf_context_new(freerdp* instance, rdpContext* context) { context->channels = freerdp_channels_new(); } void tf_context_free(freerdp* instance, rdpContext* context) { } void tf_begin_paint(rdpContext* context) { rdpGdi* gdi = context->gdi; gdi->primary->hdc->hwnd->invalid->null = 1; } void tf_end_paint(rdpContext* context) { rdpGdi* gdi = context->gdi; if (gdi->primary->hdc->hwnd->invalid->null) return; } int tf_receive_channel_data(freerdp* instance, int channelId, uint8* data, int size, int flags, int total_size) { return freerdp_channels_data(instance, channelId, data, size, flags, total_size); } int tf_process_plugin_args(rdpSettings* settings, const char* name, RDP_PLUGIN_DATA* plugin_data, void* user_data) { rdpChannels* channels = (rdpChannels*) user_data; printf("Load plugin %s\n", name); freerdp_channels_load_plugin(channels, settings, name, plugin_data); return 1; } void tf_process_cb_monitor_ready_event(rdpChannels* channels, freerdp* instance) { RDP_EVENT* event; RDP_CB_FORMAT_LIST_EVENT* format_list_event; event = freerdp_event_new(RDP_EVENT_CLASS_CLIPRDR, RDP_EVENT_TYPE_CB_FORMAT_LIST, NULL, NULL); format_list_event = (RDP_CB_FORMAT_LIST_EVENT*) event; format_list_event->num_formats = 0; freerdp_channels_send_event(channels, event); } void tf_process_channel_event(rdpChannels* channels, freerdp* instance) { RDP_EVENT* event; event = freerdp_channels_pop_event(channels); if (event) { switch (event->event_type) { case RDP_EVENT_TYPE_CB_MONITOR_READY: tf_process_cb_monitor_ready_event(channels, instance); break; default: printf("tf_process_channel_event: unknown event type %d\n", event->event_type); break; } freerdp_event_free(event); } } boolean tf_pre_connect(freerdp* instance) { tfInfo* tfi; tfContext* context; rdpSettings* settings; context = (tfContext*) instance->context; tfi = (tfInfo*) xzalloc(sizeof(tfInfo)); context->tfi = tfi; settings = instance->settings; settings->order_support[NEG_DSTBLT_INDEX] = true; settings->order_support[NEG_PATBLT_INDEX] = true; settings->order_support[NEG_SCRBLT_INDEX] = true; settings->order_support[NEG_OPAQUE_RECT_INDEX] = true; settings->order_support[NEG_DRAWNINEGRID_INDEX] = true; settings->order_support[NEG_MULTIDSTBLT_INDEX] = true; settings->order_support[NEG_MULTIPATBLT_INDEX] = true; settings->order_support[NEG_MULTISCRBLT_INDEX] = true; settings->order_support[NEG_MULTIOPAQUERECT_INDEX] = true; settings->order_support[NEG_MULTI_DRAWNINEGRID_INDEX] = true; settings->order_support[NEG_LINETO_INDEX] = true; settings->order_support[NEG_POLYLINE_INDEX] = true; settings->order_support[NEG_MEMBLT_INDEX] = true; settings->order_support[NEG_MEM3BLT_INDEX] = true; settings->order_support[NEG_SAVEBITMAP_INDEX] = true; settings->order_support[NEG_GLYPH_INDEX_INDEX] = true; settings->order_support[NEG_FAST_INDEX_INDEX] = true; settings->order_support[NEG_FAST_GLYPH_INDEX] = true; settings->order_support[NEG_POLYGON_SC_INDEX] = true; settings->order_support[NEG_POLYGON_CB_INDEX] = true; settings->order_support[NEG_ELLIPSE_SC_INDEX] = true; settings->order_support[NEG_ELLIPSE_CB_INDEX] = true; freerdp_channels_pre_connect(instance->context->channels, instance); return true; } boolean tf_post_connect(freerdp* instance) { rdpGdi* gdi; gdi_init(instance, CLRCONV_ALPHA | CLRCONV_INVERT | CLRBUF_16BPP | CLRBUF_32BPP, NULL); gdi = instance->context->gdi; instance->update->BeginPaint = tf_begin_paint; instance->update->EndPaint = tf_end_paint; freerdp_channels_post_connect(instance->context->channels, instance); return true; } int tfreerdp_run(freerdp* instance) { int i; int fds; int max_fds; int rcount; int wcount; void* rfds[32]; void* wfds[32]; fd_set rfds_set; fd_set wfds_set; rdpChannels* channels; memset(rfds, 0, sizeof(rfds)); memset(wfds, 0, sizeof(wfds)); channels = instance->context->channels; freerdp_connect(instance); while (1) { rcount = 0; wcount = 0; if (freerdp_get_fds(instance, rfds, &rcount, wfds, &wcount) != true) { printf("Failed to get FreeRDP file descriptor\n"); break; } if (freerdp_channels_get_fds(channels, instance, rfds, &rcount, wfds, &wcount) != true) { printf("Failed to get channel manager file descriptor\n"); break; } max_fds = 0; FD_ZERO(&rfds_set); for (i = 0; i < rcount; i++) { fds = (int)(long)(rfds[i]); if (fds > max_fds) max_fds = fds; FD_SET(fds, &rfds_set); } if (max_fds == 0) break; if (select(max_fds + 1, &rfds_set, &wfds_set, NULL, NULL) == -1) { /* these are not really errors */ if (!((errno == EAGAIN) || (errno == EWOULDBLOCK) || (errno == EINPROGRESS) || (errno == EINTR))) /* signal occurred */ { printf("tfreerdp_run: select failed\n"); break; } } if (freerdp_check_fds(instance) != true) { printf("Failed to check FreeRDP file descriptor\n"); break; } if (freerdp_channels_check_fds(channels, instance) != true) { printf("Failed to check channel manager file descriptor\n"); break; } tf_process_channel_event(channels, instance); } freerdp_channels_close(channels, instance); freerdp_channels_free(channels); freerdp_free(instance); return 0; } void* thread_func(void* param) { struct thread_data* data; data = (struct thread_data*) param; tfreerdp_run(data->instance); xfree(data); pthread_detach(pthread_self()); g_thread_count--; if (g_thread_count < 1) freerdp_sem_signal(&g_sem); return NULL; } int main(int argc, char* argv[]) { pthread_t thread; freerdp* instance; struct thread_data* data; rdpChannels* channels; freerdp_channels_global_init(); g_sem = freerdp_sem_new(1); instance = freerdp_new(); instance->PreConnect = tf_pre_connect; instance->PostConnect = tf_post_connect; instance->ReceiveChannelData = tf_receive_channel_data; instance->context_size = sizeof(tfContext); instance->ContextNew = tf_context_new; instance->ContextFree = tf_context_free; freerdp_context_new(instance); channels = instance->context->channels; freerdp_parse_args(instance->settings, argc, argv, tf_process_plugin_args, channels, NULL, NULL); data = (struct thread_data*) xzalloc(sizeof(struct thread_data)); data->instance = instance; g_thread_count++; pthread_create(&thread, 0, thread_func, data); while (g_thread_count > 0) { freerdp_sem_wait(g_sem); } freerdp_channels_global_uninit(); return 0; } FreeRDP-1.0.2/cmake/000077500000000000000000000000001207112532300140155ustar00rootroot00000000000000FreeRDP-1.0.2/cmake/AutoVersioning.cmake000066400000000000000000000036231207112532300177770ustar00rootroot00000000000000# - AutoVersioning # Gather version from tarball or SCM # # This module defines the following variables: # PRODUCT_VERSION - Version of product # #============================================================================= # Copyright 2011 O.S. Systems Software Ltda. # Copyright 2011 Otavio Salvador # # 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. #============================================================================= if(EXISTS "${CMAKE_SOURCE_DIR}/.version" ) file(READ ${CMAKE_SOURCE_DIR}/.version PRODUCT_VERSION) string(STRIP ${PRODUCT_VERSION} PRODUCT_VERSION) else() execute_process(COMMAND git describe --match "v[0-9]*" --abbrev=4 OUTPUT_VARIABLE PRODUCT_VERSION OUTPUT_STRIP_TRAILING_WHITESPACE ERROR_QUIET) if(PRODUCT_VERSION) string(REGEX REPLACE "^v(.*)" "\\1" PRODUCT_VERSION ${PRODUCT_VERSION}) else() # GIT is the default version set(PRODUCT_VERSION GIT) endif() # Check if has not commited changes execute_process(COMMAND git update-index -q --refresh) execute_process(COMMAND git diff-index --name-only HEAD -- OUTPUT_VARIABLE CHANGED_SOURCE OUTPUT_STRIP_TRAILING_WHITESPACE ERROR_QUIET) if(CHANGED_SOURCE) set(PRODUCT_VERSION ${PRODUCT_VERSION}-dirty) endif() endif() message(STATUS "${CMAKE_PROJECT_NAME} ${PRODUCT_VERSION}") FreeRDP-1.0.2/cmake/ConfigOptions.cmake000066400000000000000000000032751207112532300176070ustar00rootroot00000000000000option(WITH_DEBUG_TRANSPORT "Print transport debug messages." OFF) option(WITH_DEBUG_CHANNELS "Print channel manager debug messages." OFF) option(WITH_DEBUG_SVC "Print static virtual channel debug messages." OFF) option(WITH_DEBUG_DVC "Print dynamic virtual channel debug messages." OFF) option(WITH_DEBUG_KBD "Print keyboard related debug messages." OFF) option(WITH_DEBUG_NLA "Print authentication related debug messages." OFF) option(WITH_DEBUG_NEGO "Print negotiation related debug messages." OFF) option(WITH_DEBUG_CERTIFICATE "Print certificate related debug messages." OFF) option(WITH_DEBUG_LICENSE "Print license debug messages." OFF) option(WITH_DEBUG_GDI "Print graphics debug messages." OFF) option(WITH_DEBUG_RFX "Print RemoteFX debug messages." OFF) option(WITH_DEBUG_X11 "Print X11 Client debug messages" OFF) option(WITH_DEBUG_X11_CLIPRDR "Print X11 clipboard redirection debug messages" OFF) option(WITH_DEBUG_X11_LOCAL_MOVESIZE "Print X11 Client local movesize debug messages" OFF) option(WITH_DEBUG_RAIL "Print RemoteApp debug messages" OFF) option(WITH_DEBUG_XV "Print XVideo debug messages" OFF) option(WITH_DEBUG_SCARD "Print smartcard debug messages" OFF) option(WITH_DEBUG_ORDERS "Print drawing orders debug messages" OFF) option(WITH_MANPAGES "Generate manpages." ON) option(WITH_PROFILER "Compile profiler." OFF) option(WITH_SSE2 "Use SSE2 optimization." OFF) option(WITH_SSE2_TARGET "Allow compiler to generate SSE2 instructions." OFF) option(WITH_DEBUG_REDIR "Redirection debug messages" OFF) option(WITH_DEBUG_CLIPRDR "Print clipboard redirection debug messages" OFF) option(WITH_DEBUG_WND "Print window order debug messages" OFF) option(WITH_NEON "Enable NEON optimization for rfx decoder" OFF) FreeRDP-1.0.2/cmake/FindCUnit.cmake000066400000000000000000000032351207112532300166450ustar00rootroot00000000000000# - Find CUnit # Find the CUnit libraries # # This module defines the following variables: # CUNIT_FOUND - true if CUNIT_INCLUDE_DIR & CUNIT_LIBRARY are found # CUNIT_LIBRARIES - Set when CUNIT_LIBRARY is found # CUNIT_INCLUDE_DIRS - Set when CUNIT_INCLUDE_DIR is found # # CUNIT_INCLUDE_DIR - where to find CUnit.h, etc. # CUNIT_LIBRARY - the cunit library # #============================================================================= # Copyright 2011 O.S. Systems Software Ltda. # Copyright 2011 Otavio Salvador # # 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. #============================================================================= find_path(CUNIT_INCLUDE_DIR NAMES CUnit.h PATH_SUFFIXES CUnit DOC "The CUnit include directory" ) find_library(CUNIT_LIBRARY NAMES cunit DOC "The CUnit library" ) include(FindPackageHandleStandardArgs) FIND_PACKAGE_HANDLE_STANDARD_ARGS(CUnit DEFAULT_MSG CUNIT_LIBRARY CUNIT_INCLUDE_DIR) if(CUNIT_FOUND) set( CUNIT_LIBRARIES ${CUNIT_LIBRARY} ) set( CUNIT_INCLUDE_DIRS ${CUNIT_INCLUDE_DIR} ) endif() mark_as_advanced(CUNIT_INCLUDE_DIR CUNIT_LIBRARY) FreeRDP-1.0.2/cmake/FindDirectFB.cmake000066400000000000000000000034621207112532300172470ustar00rootroot00000000000000# - Find DirectFB # Find the DirectFB libraries # # This module defines the following variables: # DIRECTFB_FOUND - true if DIRECTFB_INCLUDE_DIR & DIRECTFB_LIBRARY are found # DIRECTFB_LIBRARIES - Set when DIRECTFB_LIBRARY is found # DIRECTFB_INCLUDE_DIRS - Set when DIRECTFB_INCLUDE_DIR is found # # DIRECTFB_INCLUDE_DIR - where to find CUnit.h, etc. # DIRECTFB_LIBRARY - the cunit library # #============================================================================= # Copyright 2011 O.S. Systems Software Ltda. # Copyright 2011 Otavio Salvador # Copyright 2011 Marc-Andre Moreau # # 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. #============================================================================= find_path(DIRECTFB_INCLUDE_DIR NAMES directfb.h PATH_SUFFIXES directfb DOC "The directfb include directory" ) find_library(DIRECTFB_LIBRARY NAMES directfb DOC "The DirectFB library" ) include(FindPackageHandleStandardArgs) FIND_PACKAGE_HANDLE_STANDARD_ARGS(DirectFB DEFAULT_MSG DIRECTFB_LIBRARY DIRECTFB_INCLUDE_DIR) if(DIRECTFB_FOUND) set( DIRECTFB_LIBRARIES ${DIRECTFB_LIBRARY} ) set( DIRECTFB_INCLUDE_DIRS ${DIRECTFB_INCLUDE_DIR} ) endif() mark_as_advanced(DIRECTFB_INCLUDE_DIR DIRECTFB_LIBRARY) FreeRDP-1.0.2/cmake/FindFFmpeg.cmake000066400000000000000000000022671207112532300167730ustar00rootroot00000000000000# - Try to find FFmpeg # Using Pkg-config if available for path # # FFMPEG_FOUND - all required ffmpeg components found on system # FFMPEG_INCLUDE_DIRS - combined include directories # FFMPEG_LIBRARIES - combined libraries to link include(FindPkgConfig) if (PKG_CONFIG_FOUND) pkg_check_modules(AVCODEC libavcodec) pkg_check_modules(AVUTIL libavutil) endif ( PKG_CONFIG_FOUND ) # avcodec find_path(AVCODEC_INCLUDE_DIR avcodec.h PATHS ${AVCODEC_INCLUDE_DIRS} PATH_SUFFIXES libavcodec ) find_library(AVCODEC_LIBRARY avcodec PATHS ${AVCODEC_LIBRARY_DIRS}) # avutil find_path(AVUTIL_INCLUDE_DIR avutil.h PATHS ${AVUTIL_INCLUDE_DIRS} PATH_SUFFIXES libavutil ) find_library(AVUTIL_LIBRARY avutil PATHS ${AVUTIL_LIBRARY_DIRS}) if(AVCODEC_INCLUDE_DIR AND AVCODEC_LIBRARY) set(AVCODEC_FOUND TRUE) endif() if(AVUTIL_INCLUDE_DIR AND AVUTIL_LIBRARY) set(AVUTIL_FOUND TRUE) endif() FIND_PACKAGE_HANDLE_STANDARD_ARGS(FFmpeg DEFAULT_MSG AVUTIL_FOUND AVCODEC_FOUND) if(FFMPEG_FOUND) set(FFMPEG_INCLUDE_DIRS ${AVCODEC_INCLUDE_DIR} ${AVUTIL_INCLUDE_DIR}) set(FFMPEG_LIBRARIES ${AVCODEC_LIBRARY} ${AVUTIL_LIBRARY}) endif() mark_as_advanced(FFMPEG_INCLUDE_DIRS FFMPEG_LIBRARYS) FreeRDP-1.0.2/cmake/FindOptionalPackage.cmake000066400000000000000000000042431207112532300206640ustar00rootroot00000000000000# - FindOptionalPackage # Enable or disable optional packages. Also force optional packages. # # This module defines the following macros: # find_required_package : find a required package, can not be disabled # find_suggested_package : find a suggested package - required but can be disabled # find_optional_package : find an optional package - required only if enabled # #============================================================================= # Copyright 2011 Nils Andresen # # 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. #============================================================================= macro(find_required_package _normal_package) find_package(${_normal_package} REQUIRED) endmacro(find_required_package) macro(find_suggested_package _normal_package) string(TOUPPER ${_normal_package} _upper_package) option(WITH_${_upper_package} "Add dependency to ${_normal_package} - recommended" ON) if(WITH_${_upper_package}) message(STATUS "Finding suggested package ${_normal_package}.") message(STATUS " Disable this using \"-DWITH_${_upper_package}=OFF\".") find_package(${_normal_package} REQUIRED) endif(WITH_${_upper_package}) endmacro(find_suggested_package) macro(find_optional_package _normal_package) string(TOUPPER ${_normal_package} _upper_package) option(WITH_${_upper_package} "Add dependency to ${_normal_package}" OFF) if(WITH_${_upper_package}) find_package(${_normal_package} REQUIRED) else(WITH_${_upper_package}) message(STATUS "Skipping optional package ${_normal_package}.") message(STATUS " Enable this using \"-DWITH_${_upper_package}=ON\".") endif(WITH_${_upper_package}) endmacro(find_optional_package) FreeRDP-1.0.2/cmake/FindPCSC.cmake000066400000000000000000000006001207112532300163440ustar00rootroot00000000000000include(FindPkgConfig) if (PKG_CONFIG_FOUND) pkg_check_modules(PCSC libpcsclite) endif() find_path(PCSC_INCLUDE_DIR pcsclite.h PATHS ${PCSC_INCLUDE_DIRS} PATH_SUFFIXES PCSC ) find_library(PCSC_LIBRARY pcsclite PATHS ${PCSC_LIBRARY_DIRS}) FIND_PACKAGE_HANDLE_STANDARD_ARGS(PCSC DEFAULT_MSG PCSC_INCLUDE_DIR PCSC_LIBRARY) mark_as_advanced(PCSC_INCLUDE_DIR PCSC_LIBRARY) FreeRDP-1.0.2/cmake/FindPulseAudio.cmake000066400000000000000000000006561207112532300177010ustar00rootroot00000000000000include(FindPkgConfig) if (PKG_CONFIG_FOUND) pkg_check_modules(PULSEAUDIO libpulse) endif() find_path(PULSEAUDIO_INCLUDE_DIR pulseaudio.h PATHS ${PULSEAUDIO_INCLUDE_DIRS} PATH_SUFFIXES pulse ) find_library(PULSEAUDIO_LIBRARY pulse PATHS ${PULSEAUDIO_LIBRARY_DIRS}) FIND_PACKAGE_HANDLE_STANDARD_ARGS(PulseAudio DEFAULT_MSG PULSEAUDIO_INCLUDE_DIR PULSEAUDIO_LIBRARY) mark_as_advanced(PULSEAUDIO_INCLUDE_DIR PULSEAUDIO_LIBRARY) FreeRDP-1.0.2/cmake/FindX11.cmake000066400000000000000000000032501207112532300161710ustar00rootroot00000000000000# - Find X11 # Find the X11 libraries # # This module defines the following variables: # X11_FOUND - true if X11_INCLUDE_DIR & X11_LIBRARY are found # X11_LIBRARIES - Set when X11_LIBRARY is found # X11_INCLUDE_DIRS - Set when X11_INCLUDE_DIR is found # # X11_INCLUDE_DIR - where to find Xlib.h, etc. # X11_LIBRARY - the X11 library # #============================================================================= # Copyright 2011 O.S. Systems Software Ltda. # Copyright 2011 Otavio Salvador # Copyright 2011 Marc-Andre Moreau # # 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. #============================================================================= find_path(X11_INCLUDE_DIR NAMES X11/Xlib.h PATH_SUFFIXES X11 DOC "The X11 include directory" ) find_library(X11_LIBRARY NAMES X11 DOC "The X11 library" ) include(FindPackageHandleStandardArgs) FIND_PACKAGE_HANDLE_STANDARD_ARGS(X11 DEFAULT_MSG X11_LIBRARY X11_INCLUDE_DIR) if(X11_FOUND) set( X11_LIBRARIES ${X11_LIBRARY} ) set( X11_INCLUDE_DIRS ${X11_INCLUDE_DIR} ) endif() mark_as_advanced(X11_INCLUDE_DIR X11_LIBRARY) FreeRDP-1.0.2/cmake/FindXKBFile.cmake000066400000000000000000000034601207112532300170470ustar00rootroot00000000000000# - Find XKBFILE # Find the XKBFILE libraries # # This module defines the following variables: # XKBFILE_FOUND - true if XKBFILE_INCLUDE_DIR & XKBFILE_LIBRARY are found # XKBFILE_LIBRARIES - Set when XKBFILE_LIBRARY is found # XKBFILE_INCLUDE_DIRS - Set when XKBFILE_INCLUDE_DIR is found # # XKBFILE_INCLUDE_DIR - where to find XKBfile.h, etc. # XKBFILE_LIBRARY - the xkbfile library # #============================================================================= # Copyright 2011 O.S. Systems Software Ltda. # Copyright 2011 Otavio Salvador # Copyright 2011 Marc-Andre Moreau # # 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. #============================================================================= find_path(XKBFILE_INCLUDE_DIR NAMES X11/extensions/XKBfile.h PATH_SUFFIXES X11/extensions DOC "The XKBFile include directory" ) find_library(XKBFILE_LIBRARY NAMES xkbfile DOC "The XKBFile library" ) include(FindPackageHandleStandardArgs) FIND_PACKAGE_HANDLE_STANDARD_ARGS(XKBFile DEFAULT_MSG XKBFILE_LIBRARY XKBFILE_INCLUDE_DIR) if(XKBFILE_FOUND) set( XKBFILE_LIBRARIES ${XKBFILE_LIBRARY} ) set( XKBFILE_INCLUDE_DIRS ${XKBFILE_INCLUDE_DIR} ) endif() mark_as_advanced(XKBFILE_INCLUDE_DIR XKBFILE_LIBRARY) FreeRDP-1.0.2/cmake/FindXShm.cmake000066400000000000000000000033311207112532300164770ustar00rootroot00000000000000# - Find XSHM # Find the XSHM libraries # # This module defines the following variables: # XSHM_FOUND - true if XSHM_INCLUDE_DIR & XSHM_LIBRARY are found # XSHM_LIBRARIES - Set when XSHM_LIBRARY is found # XSHM_INCLUDE_DIRS - Set when XSHM_INCLUDE_DIR is found # # XSHM_INCLUDE_DIR - where to find XShm.h, etc. # XSHM_LIBRARY - the XSHM library # #============================================================================= # Copyright 2011 O.S. Systems Software Ltda. # Copyright 2011 Otavio Salvador # Copyright 2011 Marc-Andre Moreau # # 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. #============================================================================= find_path(XSHM_INCLUDE_DIR NAMES X11/extensions/XShm.h PATH_SUFFIXES X11/extensions DOC "The XShm include directory" ) find_library(XSHM_LIBRARY NAMES Xext DOC "The XShm library" ) include(FindPackageHandleStandardArgs) FIND_PACKAGE_HANDLE_STANDARD_ARGS(XShm DEFAULT_MSG XSHM_LIBRARY XSHM_INCLUDE_DIR) if(XSHM_FOUND) set( XSHM_LIBRARIES ${XSHM_LIBRARY} ) set( XSHM_INCLUDE_DIRS ${XSHM_INCLUDE_DIR} ) endif() mark_as_advanced(XSHM_INCLUDE_DIR XSHM_LIBRARY) FreeRDP-1.0.2/cmake/FindXTest.cmake000066400000000000000000000033651207112532300166760ustar00rootroot00000000000000# - Find XTEST # Find the XTEST libraries # # This module defines the following variables: # XTEST_FOUND - true if XTEST_INCLUDE_DIR & XTEST_LIBRARY are found # XTEST_LIBRARIES - Set when XTEST_LIBRARY is found # XTEST_INCLUDE_DIRS - Set when XTEST_INCLUDE_DIR is found # # XTEST_INCLUDE_DIR - where to find XTest.h, etc. # XTEST_LIBRARY - the XTEST library # #============================================================================= # Copyright 2011 O.S. Systems Software Ltda. # Copyright 2011 Otavio Salvador # Copyright 2011 Marc-Andre Moreau # # 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. #============================================================================= find_path(XTEST_INCLUDE_DIR NAMES X11/extensions/XTest.h PATH_SUFFIXES X11/extensions DOC "The XTest include directory" ) find_library(XTEST_LIBRARY NAMES Xtst DOC "The XTest library" ) include(FindPackageHandleStandardArgs) FIND_PACKAGE_HANDLE_STANDARD_ARGS(XTest DEFAULT_MSG XTEST_LIBRARY XTEST_INCLUDE_DIR) if(XTEST_FOUND) set( XTEST_LIBRARIES ${XTEST_LIBRARY} ) set( XTEST_INCLUDE_DIRS ${XTEST_INCLUDE_DIR} ) endif() mark_as_advanced(XTEST_INCLUDE_DIR XTEST_LIBRARY) FreeRDP-1.0.2/cmake/FindXcursor.cmake000066400000000000000000000034521207112532300172710ustar00rootroot00000000000000# - Find Xcursor # Find the Xcursor libraries # # This module defines the following variables: # XCURSOR_FOUND - true if XCURSOR_INCLUDE_DIR & XCURSOR_LIBRARY are found # XCURSOR_LIBRARIES - Set when XCURSOR_LIBRARY is found # XCURSOR_INCLUDE_DIRS - Set when XCURSOR_INCLUDE_DIR is found # # XCURSOR_INCLUDE_DIR - where to find Xcursor.h, etc. # XCURSOR_LIBRARY - the Xcursor library # #============================================================================= # Copyright 2011 O.S. Systems Software Ltda. # Copyright 2011 Otavio Salvador # Copyright 2011 Marc-Andre Moreau # # 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. #============================================================================= find_path(XCURSOR_INCLUDE_DIR NAMES X11/Xcursor/Xcursor.h PATH_SUFFIXES X11/Xcursor DOC "The Xcursor include directory" ) find_library(XCURSOR_LIBRARY NAMES Xcursor DOC "The Xcursor library" ) include(FindPackageHandleStandardArgs) FIND_PACKAGE_HANDLE_STANDARD_ARGS(Xcursor DEFAULT_MSG XCURSOR_LIBRARY XCURSOR_INCLUDE_DIR) if(XCURSOR_FOUND) set( XCURSOR_LIBRARIES ${XCURSOR_LIBRARY} ) set( XCURSOR_INCLUDE_DIRS ${XCURSOR_INCLUDE_DIR} ) endif() mark_as_advanced(XCURSOR_INCLUDE_DIR XCURSOR_LIBRARY) FreeRDP-1.0.2/cmake/FindXdamage.cmake000066400000000000000000000034601207112532300171710ustar00rootroot00000000000000# - Find XDAMAGE # Find the XDAMAGE libraries # # This module defines the following variables: # XDAMAGE_FOUND - true if XDAMAGE_INCLUDE_DIR & XDAMAGE_LIBRARY are found # XDAMAGE_LIBRARIES - Set when XDAMAGE_LIBRARY is found # XDAMAGE_INCLUDE_DIRS - Set when XDAMAGE_INCLUDE_DIR is found # # XDAMAGE_INCLUDE_DIR - where to find Xdamage.h, etc. # XDAMAGE_LIBRARY - the XDAMAGE library # #============================================================================= # Copyright 2011 O.S. Systems Software Ltda. # Copyright 2011 Otavio Salvador # Copyright 2011 Marc-Andre Moreau # # 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. #============================================================================= find_path(XDAMAGE_INCLUDE_DIR NAMES X11/extensions/Xdamage.h PATH_SUFFIXES X11/extensions DOC "The Xdamage include directory" ) find_library(XDAMAGE_LIBRARY NAMES Xdamage DOC "The Xdamage library" ) include(FindPackageHandleStandardArgs) FIND_PACKAGE_HANDLE_STANDARD_ARGS(Xdamage DEFAULT_MSG XDAMAGE_LIBRARY XDAMAGE_INCLUDE_DIR) if(XDAMAGE_FOUND) set( XDAMAGE_LIBRARIES ${XDAMAGE_LIBRARY} ) set( XDAMAGE_INCLUDE_DIRS ${XDAMAGE_INCLUDE_DIR} ) endif() mark_as_advanced(XDAMAGE_INCLUDE_DIR XDAMAGE_LIBRARY) FreeRDP-1.0.2/cmake/FindXext.cmake000066400000000000000000000033311207112532300165500ustar00rootroot00000000000000# - Find Xext # Find the Xext libraries # # This module defines the following variables: # Xext_FOUND - true if Xext_INCLUDE_DIR & Xext_LIBRARY are found # Xext_LIBRARIES - Set when Xext_LIBRARY is found # Xext_INCLUDE_DIRS - Set when Xext_INCLUDE_DIR is found # # Xext_INCLUDE_DIR - where to find Xext.h, etc. # Xext_LIBRARY - the Xext library # #============================================================================= # Copyright 2011 O.S. Systems Software Ltda. # Copyright 2011 Otavio Salvador # Copyright 2011 Marc-Andre Moreau # # 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. #============================================================================= find_path(XEXT_INCLUDE_DIR NAMES X11/extensions/Xext.h PATH_SUFFIXES X11/extensions DOC "The Xext include directory" ) find_library(XEXT_LIBRARY NAMES Xext DOC "The Xext library" ) include(FindPackageHandleStandardArgs) FIND_PACKAGE_HANDLE_STANDARD_ARGS(Xext DEFAULT_MSG XEXT_LIBRARY XEXT_INCLUDE_DIR) if(XEXT_FOUND) set( XEXT_LIBRARIES ${XEXT_LIBRARY} ) set( XEXT_INCLUDE_DIRS ${XEXT_INCLUDE_DIR} ) endif() mark_as_advanced(XEXT_INCLUDE_DIR XEXT_LIBRARY) FreeRDP-1.0.2/cmake/FindXfixes.cmake000066400000000000000000000034231207112532300170700ustar00rootroot00000000000000# - Find XFIXES # Find the XFIXES libraries # # This module defines the following variables: # XFIXES_FOUND - true if XFIXES_INCLUDE_DIR & XFIXES_LIBRARY are found # XFIXES_LIBRARIES - Set when XFIXES_LIBRARY is found # XFIXES_INCLUDE_DIRS - Set when XFIXES_INCLUDE_DIR is found # # XFIXES_INCLUDE_DIR - where to find Xfixes.h, etc. # XFIXES_LIBRARY - the XFIXES library # #============================================================================= # Copyright 2011 O.S. Systems Software Ltda. # Copyright 2011 Otavio Salvador # Copyright 2011 Marc-Andre Moreau # # 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. #============================================================================= find_path(XFIXES_INCLUDE_DIR NAMES X11/extensions/Xfixes.h PATH_SUFFIXES X11/extensions DOC "The Xfixes include directory" ) find_library(XFIXES_LIBRARY NAMES Xfixes DOC "The Xfixes library" ) include(FindPackageHandleStandardArgs) FIND_PACKAGE_HANDLE_STANDARD_ARGS(Xfixes DEFAULT_MSG XFIXES_LIBRARY XFIXES_INCLUDE_DIR) if(XFIXES_FOUND) set( XFIXES_LIBRARIES ${XFIXES_LIBRARY} ) set( XFIXES_INCLUDE_DIRS ${XFIXES_INCLUDE_DIR} ) endif() mark_as_advanced(XFIXES_INCLUDE_DIR XFIXES_LIBRARY) FreeRDP-1.0.2/cmake/FindXinerama.cmake000066400000000000000000000035151207112532300173700ustar00rootroot00000000000000# - Find XINERAMA # Find the XINERAMA libraries # # This module defines the following variables: # XINERAMA_FOUND - true if XINERAMA_INCLUDE_DIR & XINERAMA_LIBRARY are found # XINERAMA_LIBRARIES - Set when XINERAMA_LIBRARY is found # XINERAMA_INCLUDE_DIRS - Set when XINERAMA_INCLUDE_DIR is found # # XINERAMA_INCLUDE_DIR - where to find Xinerama.h, etc. # XINERAMA_LIBRARY - the XINERAMA library # #============================================================================= # Copyright 2011 O.S. Systems Software Ltda. # Copyright 2011 Otavio Salvador # Copyright 2011 Marc-Andre Moreau # # 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. #============================================================================= find_path(XINERAMA_INCLUDE_DIR NAMES X11/extensions/Xinerama.h PATH_SUFFIXES X11/extensions DOC "The Xinerama include directory" ) find_library(XINERAMA_LIBRARY NAMES Xinerama DOC "The Xinerama library" ) include(FindPackageHandleStandardArgs) FIND_PACKAGE_HANDLE_STANDARD_ARGS(Xinerama DEFAULT_MSG XINERAMA_LIBRARY XINERAMA_INCLUDE_DIR) if(XINERAMA_FOUND) set( XINERAMA_LIBRARIES ${XINERAMA_LIBRARY} ) set( XINERAMA_INCLUDE_DIRS ${XINERAMA_INCLUDE_DIR} ) endif() mark_as_advanced(XINERAMA_INCLUDE_DIR XINERAMA_LIBRARY) FreeRDP-1.0.2/cmake/FindXmlto.cmake000066400000000000000000000023021207112532300167200ustar00rootroot00000000000000# - Find xmlto # Find the xmlto docbook xslt frontend # # This module defines the following variables: # XMLTO_FOUND - true if xmlto was found # XMLTO_EXECUTABLE - Path to xmlto, if xmlto was found # #============================================================================= # Copyright 2011 Nils Andresen # # 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(XMLTO_FOUND false) find_program(XMLTO_EXECUTABLE NAMES xmlto DOC "docbook xslt frontend") if(XMLTO_EXECUTABLE) set(XMLTO_FOUND true) message(STATUS "Found XMLTO: ${XMLTO_EXECUTABLE}") endif() mark_as_advanced(XMLTO_EXECUTABLE) FreeRDP-1.0.2/cmake/FindXv.cmake000066400000000000000000000032371207112532300162220ustar00rootroot00000000000000# - Find Xv # Find the Xv libraries # # This module defines the following variables: # XV_FOUND - true if XV_INCLUDE_DIR & XV_LIBRARY are found # XV_LIBRARIES - Set when XV_LIBRARY is found # XV_INCLUDE_DIRS - Set when XV_INCLUDE_DIR is found # # XV_INCLUDE_DIR - where to find Xv.h, etc. # XV_LIBRARY - the Xv library # #============================================================================= # Copyright 2011 O.S. Systems Software Ltda. # Copyright 2011 Otavio Salvador # Copyright 2011 Marc-Andre Moreau # # 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. #============================================================================= find_path(XV_INCLUDE_DIR NAMES X11/extensions/Xv.h PATH_SUFFIXES X11/extensions DOC "The Xv include directory" ) find_library(XV_LIBRARY NAMES Xv DOC "The Xv library" ) include(FindPackageHandleStandardArgs) FIND_PACKAGE_HANDLE_STANDARD_ARGS(Xv DEFAULT_MSG XV_LIBRARY XV_INCLUDE_DIR) if(XV_FOUND) set( XV_LIBRARIES ${XV_LIBRARY} ) set( XV_INCLUDE_DIRS ${XV_INCLUDE_DIR} ) endif() mark_as_advanced(XV_INCLUDE_DIR XV_LIBRARY) FreeRDP-1.0.2/cmake/GNUInstallDirsWrapper.cmake000066400000000000000000000007541207112532300211700ustar00rootroot00000000000000# GNUInstallDirs is a relatively new cmake module, so wrap it to avoid errors include(GNUInstallDirs OPTIONAL RESULT_VARIABLE GID_PATH) if(GID_PATH STREQUAL "NOTFOUND") if(NOT DEFINED CMAKE_INSTALL_BINDIR) set(CMAKE_INSTALL_BINDIR "bin" CACHE PATH "user executables (bin)") endif() if(NOT DEFINED CMAKE_INSTALL_LIBDIR) set(CMAKE_INSTALL_LIBDIR "lib${LIB_SUFFIX}" CACHE PATH "object code libraries (lib)") endif() mark_as_advanced(CMAKE_INSTALL_BINDIR CMAKE_INSTALL_LIBDIR) endif() FreeRDP-1.0.2/config.h.in000066400000000000000000000027111207112532300147610ustar00rootroot00000000000000#ifndef __CONFIG_H #define __CONFIG_H #define FREERDP_VERSION_MAJOR ${FREERDP_VERSION_MAJOR} #define FREERDP_VERSION_MINOR ${FREERDP_VERSION_MINOR} #define FREERDP_VERSION_REVISION ${FREERDP_VERSION_REVISION} #define FREERDP_VERSION_SUFFIX "${FREERDP_VERSION_SUFFIX}" #define FREERDP_VERSION "${FREERDP_VERSION}" #define FREERDP_VERSION_FULL "${FREERDP_VERSION_FULL}" /* Include files */ #cmakedefine HAVE_SYS_PARAM_H #cmakedefine HAVE_SYS_SOCKET_H #cmakedefine HAVE_NETDB_H #cmakedefine HAVE_FCNTL_H #cmakedefine HAVE_UNISTD_H #cmakedefine HAVE_LIMITS_H #cmakedefine HAVE_STDINT_H #cmakedefine HAVE_STDBOOL_H #cmakedefine HAVE_INTTYPES_H /* Endian */ #cmakedefine BIG_ENDIAN /* Options */ #cmakedefine WITH_DEBUG_TRANSPORT #cmakedefine WITH_DEBUG_CHANNELS #cmakedefine WITH_DEBUG_SVC #cmakedefine WITH_DEBUG_DVC #cmakedefine WITH_DEBUG_KBD #cmakedefine WITH_DEBUG_NLA #cmakedefine WITH_DEBUG_NEGO #cmakedefine WITH_DEBUG_CERTIFICATE #cmakedefine WITH_DEBUG_LICENSE #cmakedefine WITH_DEBUG_GDI #cmakedefine WITH_DEBUG_ASSERT #cmakedefine WITH_DEBUG_RFX #cmakedefine WITH_PROFILER #cmakedefine WITH_SSE2 #cmakedefine WITH_SSE2_TARGET #cmakedefine WITH_NEON #cmakedefine WITH_DEBUG_X11 #cmakedefine WITH_DEBUG_X11_CLIPRDR #cmakedefine WITH_DEBUG_X11_LOCAL_MOVESIZE #cmakedefine WITH_DEBUG_RAIL #cmakedefine WITH_DEBUG_XV #cmakedefine WITH_DEBUG_SCARD #cmakedefine WITH_DEBUG_ORDERS #cmakedefine WITH_DEBUG_REDIR #cmakedefine WITH_DEBUG_CLIPRDR #cmakedefine WITH_DEBUG_WND #endif FreeRDP-1.0.2/cunit/000077500000000000000000000000001207112532300140575ustar00rootroot00000000000000FreeRDP-1.0.2/cunit/CMakeLists.txt000066400000000000000000000037331207112532300166250ustar00rootroot00000000000000# FreeRDP: A Remote Desktop Protocol Client # cunit cmake build script # # Copyright 2011 O.S. Systems Software Ltda. # Copyright 2011 Otavio Salvador # Copyright 2011 Marc-Andre Moreau # # 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. include_directories(${CUNIT_INCLUDE_DIRS}) include_directories(${CMAKE_SOURCE_DIR}) # for some internal tests include_directories(../libfreerdp-core) include_directories(../libfreerdp-gdi) include_directories(../libfreerdp-cache) include_directories(../libfreerdp-codec) add_executable(test_freerdp test_per.c test_per.h test_ber.c test_ber.h test_gcc.c test_gcc.h test_mcs.c test_mcs.h test_color.c test_color.h test_bitmap.c test_bitmap.h test_libgdi.c test_libgdi.h test_list.c test_list.h test_orders.c test_orders.h test_pcap.c test_pcap.h test_license.c test_license.h test_stream.c test_stream.h test_utils.c test_utils.h test_channels.c test_channels.h test_cliprdr.c test_cliprdr.h test_drdynvc.c test_drdynvc.h test_librfx.c test_librfx.h test_freerdp.c test_freerdp.h test_rail.c test_rail.h test_mppc) target_link_libraries(test_freerdp ${CUNIT_LIBRARIES}) target_link_libraries(test_freerdp freerdp-core) target_link_libraries(test_freerdp freerdp-gdi) target_link_libraries(test_freerdp freerdp-utils) target_link_libraries(test_freerdp freerdp-channels) target_link_libraries(test_freerdp freerdp-codec) add_test(CUnitTests ${EXECUTABLE_OUTPUT_PATH}/test_freerdp) FreeRDP-1.0.2/cunit/test_ber.c000066400000000000000000000045661207112532300160450ustar00rootroot00000000000000/** * FreeRDP: A Remote Desktop Protocol Client * Basic Encoding Rules (BER) Unit Tests * * Copyright 2011 Marc-Andre Moreau * * 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. */ #include #include #include #include "test_ber.h" #include "libfreerdp-core/ber.h" int init_ber_suite(void) { return 0; } int clean_ber_suite(void) { return 0; } int add_ber_suite(void) { add_test_suite(ber); add_test_function(ber_write_length); add_test_function(ber_write_universal_tag); add_test_function(ber_write_application_tag); return 0; } uint8 ber_length_expected_1[1] = "\x40"; /* 64 */ uint8 ber_length_expected_2[3] = "\x82\x01\x94"; /* 404 */ void test_ber_write_length(void) { STREAM *s1, *s2; s1 = stream_new(sizeof(ber_length_expected_1)); s2 = stream_new(sizeof(ber_length_expected_2)); ber_write_length(s1, 64); ASSERT_STREAM(s1, (uint8*) ber_length_expected_1, sizeof(ber_length_expected_1)); ber_write_length(s2, 404); ASSERT_STREAM(s2, (uint8*) ber_length_expected_2, sizeof(ber_length_expected_2)); stream_free(s1); stream_free(s2); } /* BOOLEAN, length 1, without value */ uint8 ber_universal_tag_expected[1] = "\x01"; void test_ber_write_universal_tag(void) { STREAM* s; s = stream_new(sizeof(ber_universal_tag_expected)); ber_write_universal_tag(s, 1, false); ASSERT_STREAM(s, (uint8*) ber_universal_tag_expected, sizeof(ber_universal_tag_expected)); stream_free(s); } /* T.125 MCS Application 101 (Connect-Initial), length 404 */ uint8 ber_application_tag_expected[5] = "\x7F\x65\x82\x01\x94"; void test_ber_write_application_tag(void) { STREAM* s; s = stream_new(sizeof(ber_application_tag_expected)); ber_write_application_tag(s, 101, 404); ASSERT_STREAM(s, (uint8*) ber_application_tag_expected, sizeof(ber_application_tag_expected)); stream_free(s); } FreeRDP-1.0.2/cunit/test_ber.h000066400000000000000000000016611207112532300160430ustar00rootroot00000000000000/** * FreeRDP: A Remote Desktop Protocol Client * Basic Encoding Rules (BER) Unit Tests * * Copyright 2011 Marc-Andre Moreau * * 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. */ #include "test_freerdp.h" int init_ber_suite(void); int clean_ber_suite(void); int add_ber_suite(void); void test_ber_write_length(void); void test_ber_write_universal_tag(void); void test_ber_write_application_tag(void); FreeRDP-1.0.2/cunit/test_bitmap.c000066400000000000000000003132521207112532300165440ustar00rootroot00000000000000/** * FreeRDP: A Remote Desktop Protocol Client * Bitmap Unit Tests * * Copyright 2011 Jay Sorg * * 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. */ #include #include #include #include #include "test_bitmap.h" uint8 compressed_16x1x8[] = { 0x10 }; uint8 decompressed_16x1x8[] = { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }; uint8 compressed_32x32x8[] = { 0x00, 0x00, 0x00, 0x00, 0x80, 0x00, 0x06, 0x06, 0xed, 0x06, 0x06, 0x06, 0xed, 0x06, 0x06, 0x06, 0xec, 0x6c, 0x0e, 0x0e, 0x44, 0x0e, 0x0e, 0x0e, 0x13, 0x06, 0x06, 0x06, 0xed, 0x06, 0x06, 0x06, 0xed, 0x06, 0x06, 0x06, 0x00, 0x00, 0xe4, 0x04, 0x06, 0x8e, 0x60, 0x0e, 0x60, 0x8c, 0xb4, 0xb5, 0xdc, 0xdc, 0xbb, 0xb4, 0x8c, 0x66, 0x0b, 0x6c, 0xe4, 0x04, 0x06, 0x02, 0x8b, 0x06, 0x06, 0xed, 0x06, 0xed, 0x06, 0xf8, 0x0e, 0x66, 0xb4, 0xdc, 0x68, 0xe2, 0x97, 0xdd, 0xb4, 0xa7, 0x16, 0x06, 0x06, 0x06, 0xed, 0x06, 0xed, 0x06, 0x00, 0x00, 0x00, 0x06, 0x04, 0x06, 0x00, 0x06, 0x0b, 0xae, 0xdc, 0xe9, 0x6a, 0xdc, 0x96, 0xe9, 0xe9, 0xb4, 0x0e, 0x00, 0x06, 0x04, 0x06, 0x00, 0x06, 0x00, 0x00, 0x06, 0x06, 0xed, 0x06, 0x06, 0x0e, 0xae, 0xdc, 0xdb, 0xdb, 0xd0, 0x09, 0x07, 0xcf, 0x03, 0x95, 0xdb, 0xdb, 0xdc, 0xb4, 0x66, 0x6c, 0xed, 0x06, 0x06, 0x06, 0x00, 0x00, 0x04, 0x06, 0x04, 0x06, 0x0b, 0xae, 0xdb, 0xd4, 0xd5, 0x6c, 0xdb, 0x80, 0xaf, 0xd5, 0xd4, 0xdb, 0xb4, 0x66, 0x04, 0x06, 0x04, 0x06, 0x00, 0x00, 0xed, 0x06, 0xed, 0x66, 0xae, 0xd5, 0xad, 0xd4, 0xd4, 0xd5, 0xd5, 0xd5, 0xdb, 0xb4, 0xb4, 0xb4, 0xb4, 0xb4, 0xd5, 0xd5, 0xd5, 0xd4, 0xd4, 0xad, 0xd5, 0xb4, 0x0e, 0x06, 0x06, 0x06, 0x00, 0x00, 0x00, 0x06, 0x60, 0xa7, 0xb4, 0xad, 0xad, 0xad, 0xb3, 0xb3, 0xd4, 0xd4, 0xb3, 0x8c, 0xb6, 0x07, 0xb6, 0x8c, 0xb3, 0xd4, 0xb3, 0xb3, 0xad, 0xad, 0xad, 0xb4, 0xad, 0x66, 0x00, 0x06, 0x00, 0x00, 0x06, 0x06, 0x66, 0xae, 0xad, 0x8b, 0xad, 0xad, 0xad, 0xad, 0xad, 0xb3, 0xad, 0xb5, 0x07, 0x07, 0x07, 0xf0, 0x8b, 0xad, 0xad, 0xad, 0xad, 0xad, 0x8b, 0xa7, 0xae, 0xa7, 0x6c, 0x06, 0x00, 0x00, 0x04, 0x6c, 0xa7, 0xad, 0xa7, 0xa7, 0x8b, 0xad, 0xad, 0xad, 0xad, 0xad, 0xad, 0xb5, 0xbd, 0xbd, 0xbd, 0xbd, 0xf0, 0x8b, 0x8b, 0xad, 0x8b, 0x8b, 0xa7, 0xa7, 0xc8, 0xc8, 0x60, 0x06, 0x00, 0x00, 0x06, 0x66, 0xc8, 0xa7, 0x66, 0xa7, 0xa7, 0x8b, 0x8b, 0x8b, 0x8b, 0xad, 0x8b, 0x92, 0xf1, 0xf1, 0xf1, 0xf1, 0xf2, 0x07, 0xa7, 0xa7, 0x8b, 0xa7, 0xa7, 0x66, 0x66, 0xc8, 0x66, 0x06, 0x00, 0x00, 0x00, 0x60, 0xa7, 0x66, 0x66, 0x66, 0xa7, 0xa7, 0xa7, 0xa7, 0x8b, 0x8b, 0x8b, 0xa7, 0xb6, 0xf3, 0xf3, 0xf3, 0xf3, 0xf3, 0x07, 0x66, 0xa7, 0xa7, 0x66, 0x66, 0x66, 0xa7, 0xa7, 0x6c, 0x00, 0x00, 0x6c, 0x04, 0xa7, 0x60, 0x6b, 0x66, 0x99, 0xb6, 0xf5, 0xf5, 0xf5, 0xf5, 0xf5, 0xef, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0xa7, 0x66, 0x00, 0x00, 0x60, 0xa7, 0x66, 0x60, 0x66, 0x66, 0x8c, 0xf1, 0x6e, 0xff, 0x85, 0xbd, 0x66, 0x66, 0x66, 0x60, 0x05, 0x87, 0x13, 0x04, 0x66, 0x66, 0x66, 0x66, 0xf4, 0x70, 0xff, 0x84, 0xbd, 0x66, 0x66, 0x66, 0x05, 0x85, 0x0b, 0xa7, 0xb5, 0xae, 0x8c, 0xd0, 0x13, 0xc1, 0x01, 0x00, 0x08, 0x8e, 0x8c, 0xae, 0xb5, 0xae, 0x66, 0x00, 0x00, 0x6c, 0xae, 0xbc, 0xb5, 0xb5, 0xae, 0xb5, 0xd0, 0x0e, 0x0c, 0x01, 0x00, 0x90, 0xf2, 0xae, 0xae, 0xb5, 0xb5, 0xbc, 0xb5, 0x66, 0x00, 0x00, 0x04, 0xae, 0x0a, 0xb5, 0xb5, 0xb5, 0x68, 0xae, 0x82, 0x8c, 0x0a, 0x05, 0x8c, 0xf2, 0xae, 0xae, 0xb5, 0xb5, 0xb5, 0xbc, 0xb5, 0x6c, 0x00, 0x00, 0x06, 0x05, 0x81, 0xd0, 0x06, 0x9a, 0x8c, 0x0a, 0xff, 0xff, 0xff, 0xff, 0xff, 0xf2, 0xae, 0xae, 0xd0, 0xb5, 0xb5, 0xb5, 0x0a, 0xb5, 0x6c, 0x00, 0x00, 0x00, 0x8b, 0x0a, 0xbc, 0xb5, 0xb5, 0xb5, 0x06, 0x9b, 0xb6, 0xff, 0xff, 0xff, 0xff, 0xff, 0xf2, 0xae, 0xae, 0xae, 0xb5, 0xb5, 0xb5, 0xb6, 0x0a, 0x8c, 0x06, 0x00, 0x00, 0x06, 0x6c, 0xb5, 0x0a, 0xb6, 0xb5, 0xb5, 0xb5, 0x05, 0x80, 0x7d, 0xbc, 0xff, 0xff, 0xff, 0xff, 0xf2, 0xae, 0xae, 0xae, 0xb5, 0xb5, 0xb5, 0xb6, 0x0a, 0x0a, 0x8b, 0x06, 0x00, 0x00, 0x04, 0x06, 0x87, 0x0a, 0xbc, 0xb6, 0xb5, 0xb5, 0xb5, 0xd0, 0xae, 0xae, 0xae, 0xb6, 0xff, 0xff, 0xff, 0xf2, 0xd0, 0xae, 0xd0, 0xb5, 0xb5, 0xb5, 0xb6, 0xbc, 0x1a, 0xb5, 0x04, 0x06, 0x00, 0x00, 0xed, 0x06, 0x6e, 0xb5, 0x0a, 0xbc, 0xb6, 0xb5, 0xb5, 0xb5, 0xd0, 0xd0, 0xd0, 0xb5, 0xf4, 0xff, 0xf2, 0xd0, 0xd0, 0xd0, 0xb5, 0xb5, 0xb5, 0xb6, 0xbc, 0x0a, 0x0a, 0x8b, 0x06, 0x06, 0x00, 0x00, 0x00, 0x06, 0x04, 0x8b, 0xbc, 0x1a, 0x0a, 0xb6, 0xb6, 0xb5, 0xb5, 0xb5, 0xb5, 0xb5, 0xd0, 0xb5, 0xb5, 0xb5, 0xb5, 0xb5, 0xb5, 0xb6, 0xb6, 0x0a, 0xde, 0x0a, 0xa7, 0x06, 0x00, 0x06, 0x00, 0x00, 0x06, 0x06, 0xed, 0x06, 0x8b, 0xbc, 0xf2, 0x0a, 0xb6, 0xb6, 0xb6, 0xb6, 0xb5, 0xb5, 0xb5, 0xb5, 0xb5, 0xb5, 0xb6, 0xb6, 0xb6, 0xb6, 0x0a, 0xf2, 0x1a, 0x8c, 0xec, 0x06, 0x06, 0x06, 0x00, 0x00, 0x04, 0x06, 0x04, 0x06, 0x04, 0xa7, 0xbc, 0x1a, 0x0a, 0x0a, 0x6a, 0xb6, 0x96, 0x0a, 0x0a, 0xf2, 0x0a, 0x87, 0x06, 0x04, 0x06, 0x04, 0x06, 0x00, 0x00, 0x06, 0x06, 0xed, 0x06, 0xed, 0x06, 0x8c, 0xb6, 0xf4, 0xf2, 0xd0, 0x09, 0xbc, 0x87, 0x03, 0x80, 0x2c, 0xde, 0xf4, 0x0a, 0x8b, 0x06, 0x06, 0xed, 0x06, 0xed, 0x06, 0x00, 0x00, 0x00, 0x06, 0x04, 0x06, 0x00, 0x06, 0x04, 0x6c, 0x87, 0x0a, 0xf4, 0xf4, 0xf2, 0xde, 0xbd, 0xbd, 0xde, 0xf2, 0xf4, 0xf4, 0x0a, 0xd0, 0x04, 0x06, 0x00, 0x06, 0x04, 0x06, 0x00, 0x06, 0x00, 0x00, 0x06, 0x06, 0xed, 0x06, 0x06, 0x06, 0xed, 0x06, 0x06, 0x6c, 0x8c, 0xb5, 0xbc, 0x0a, 0xde, 0xf2, 0xbd, 0x0a, 0xb5, 0x8c, 0x6c, 0x06, 0xed, 0x06, 0x06, 0x06, 0xed, 0x06, 0x06, 0x06, 0x00, 0x00, 0xe6, 0x04, 0x06, 0x86, 0x04, 0x6c, 0x04, 0x8b, 0x04, 0x6c, 0xe6, 0x04, 0x06, 0x82, 0x00, 0x00 }; uint8 decompressed_32x32x8[] = { 0x04, 0x06, 0x04, 0x06, 0x04, 0x06, 0x04, 0x06, 0x04, 0x06, 0x04, 0x06, 0x04, 0x6c, 0x04, 0x8b, 0x04, 0x6c, 0x04, 0x06, 0x04, 0x06, 0x04, 0x06, 0x04, 0x06, 0x04, 0x06, 0x04, 0x06, 0x00, 0x00, 0x06, 0x06, 0xed, 0x06, 0x06, 0x06, 0xed, 0x06, 0x06, 0x6c, 0x8c, 0xb5, 0xbc, 0x0a, 0xde, 0xf2, 0xbd, 0x0a, 0xb5, 0x8c, 0x6c, 0x06, 0xed, 0x06, 0x06, 0x06, 0xed, 0x06, 0x06, 0x06, 0x00, 0x00, 0x00, 0x06, 0x04, 0x06, 0x00, 0x06, 0x04, 0x6c, 0x87, 0x0a, 0xf4, 0xf4, 0xf2, 0xde, 0xbd, 0xbd, 0xde, 0xf2, 0xf4, 0xf4, 0x0a, 0xd0, 0x04, 0x06, 0x00, 0x06, 0x04, 0x06, 0x00, 0x06, 0x00, 0x00, 0x06, 0x06, 0xed, 0x06, 0xed, 0x06, 0x8c, 0xb6, 0xf4, 0xf2, 0x0a, 0x0a, 0x0a, 0xb6, 0xb6, 0xb6, 0xb6, 0x0a, 0x0a, 0x0a, 0xde, 0xf4, 0x0a, 0x8b, 0x06, 0x06, 0xed, 0x06, 0xed, 0x06, 0x00, 0x00, 0x04, 0x06, 0x04, 0x06, 0x04, 0xa7, 0xbc, 0x1a, 0x0a, 0x0a, 0xb6, 0xb6, 0xb6, 0xb6, 0xb6, 0xb6, 0xb6, 0xb6, 0xb6, 0xb6, 0x0a, 0x0a, 0xf2, 0x0a, 0x87, 0x06, 0x04, 0x06, 0x04, 0x06, 0x00, 0x00, 0x06, 0x06, 0xed, 0x06, 0x8b, 0xbc, 0xf2, 0x0a, 0xb6, 0xb6, 0xb6, 0xb6, 0xb5, 0xb5, 0xb5, 0xb5, 0xb5, 0xb5, 0xb6, 0xb6, 0xb6, 0xb6, 0x0a, 0xf2, 0x1a, 0x8c, 0xec, 0x06, 0x06, 0x06, 0x00, 0x00, 0x00, 0x06, 0x04, 0x8b, 0xbc, 0x1a, 0x0a, 0xb6, 0xb6, 0xb5, 0xb5, 0xb5, 0xb5, 0xb5, 0xd0, 0xb5, 0xb5, 0xb5, 0xb5, 0xb5, 0xb5, 0xb6, 0xb6, 0x0a, 0xde, 0x0a, 0xa7, 0x06, 0x00, 0x06, 0x00, 0x00, 0xed, 0x06, 0x6e, 0xb5, 0x0a, 0xbc, 0xb6, 0xb5, 0xb5, 0xb5, 0xd0, 0xd0, 0xd0, 0xb5, 0xf4, 0xff, 0xf2, 0xd0, 0xd0, 0xd0, 0xb5, 0xb5, 0xb5, 0xb6, 0xbc, 0x0a, 0x0a, 0x8b, 0x06, 0x06, 0x00, 0x00, 0x04, 0x06, 0x87, 0x0a, 0xbc, 0xb6, 0xb5, 0xb5, 0xb5, 0xd0, 0xae, 0xae, 0xae, 0xb6, 0xff, 0xff, 0xff, 0xf2, 0xd0, 0xae, 0xd0, 0xb5, 0xb5, 0xb5, 0xb6, 0xbc, 0x1a, 0xb5, 0x04, 0x06, 0x00, 0x00, 0x06, 0x6c, 0xb5, 0x0a, 0xb6, 0xb5, 0xb5, 0xb5, 0xae, 0xae, 0xae, 0xae, 0xae, 0xbc, 0xff, 0xff, 0xff, 0xff, 0xf2, 0xae, 0xae, 0xae, 0xb5, 0xb5, 0xb5, 0xb6, 0x0a, 0x0a, 0x8b, 0x06, 0x00, 0x00, 0x00, 0x8b, 0x0a, 0xbc, 0xb5, 0xb5, 0xb5, 0xae, 0xae, 0xae, 0xae, 0xae, 0xae, 0xb6, 0xff, 0xff, 0xff, 0xff, 0xff, 0xf2, 0xae, 0xae, 0xae, 0xb5, 0xb5, 0xb5, 0xb6, 0x0a, 0x8c, 0x06, 0x00, 0x00, 0x06, 0xae, 0x0a, 0xb5, 0xb5, 0xb5, 0xd0, 0xae, 0xae, 0xae, 0xae, 0xae, 0xae, 0x8c, 0x0a, 0xff, 0xff, 0xff, 0xff, 0xff, 0xf2, 0xae, 0xae, 0xd0, 0xb5, 0xb5, 0xb5, 0x0a, 0xb5, 0x6c, 0x00, 0x00, 0x04, 0xae, 0x0a, 0xb5, 0xb5, 0xb5, 0xae, 0xae, 0xae, 0xae, 0xae, 0xae, 0xae, 0xae, 0x8c, 0x0a, 0xff, 0xff, 0xff, 0xff, 0xff, 0xf2, 0xae, 0xae, 0xb5, 0xb5, 0xb5, 0xbc, 0xb5, 0x6c, 0x00, 0x00, 0x6c, 0xae, 0xbc, 0xb5, 0xb5, 0xae, 0xb5, 0xf3, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xf2, 0xae, 0xae, 0xb5, 0xb5, 0xbc, 0xb5, 0x66, 0x00, 0x00, 0x0b, 0xa7, 0xb5, 0xae, 0x8c, 0xa7, 0xf4, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xbd, 0xa7, 0x8c, 0xae, 0xb5, 0xae, 0x66, 0x00, 0x00, 0x13, 0x04, 0x66, 0x66, 0x66, 0x66, 0xf4, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xbd, 0x66, 0x66, 0x66, 0x66, 0xa7, 0x66, 0x00, 0x00, 0x60, 0xa7, 0x66, 0x60, 0x66, 0x66, 0x8c, 0xf1, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xbd, 0x66, 0x66, 0x66, 0x60, 0x66, 0xa7, 0x66, 0x00, 0x00, 0x6c, 0x04, 0xa7, 0x60, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0xb6, 0xf5, 0xf5, 0xf5, 0xf5, 0xf5, 0xef, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0xa7, 0x66, 0x00, 0x00, 0x00, 0x60, 0xa7, 0x66, 0x66, 0x66, 0xa7, 0xa7, 0xa7, 0xa7, 0x8b, 0x8b, 0x8b, 0xa7, 0xb6, 0xf3, 0xf3, 0xf3, 0xf3, 0xf3, 0x07, 0x66, 0xa7, 0xa7, 0x66, 0x66, 0x66, 0xa7, 0xa7, 0x6c, 0x00, 0x00, 0x06, 0x66, 0xc8, 0xa7, 0x66, 0xa7, 0xa7, 0x8b, 0x8b, 0x8b, 0x8b, 0xad, 0x8b, 0x92, 0xf1, 0xf1, 0xf1, 0xf1, 0xf2, 0x07, 0xa7, 0xa7, 0x8b, 0xa7, 0xa7, 0x66, 0x66, 0xc8, 0x66, 0x06, 0x00, 0x00, 0x04, 0x6c, 0xa7, 0xad, 0xa7, 0xa7, 0x8b, 0xad, 0xad, 0xad, 0xad, 0xad, 0xad, 0xb5, 0xbd, 0xbd, 0xbd, 0xbd, 0xf0, 0x8b, 0x8b, 0xad, 0x8b, 0x8b, 0xa7, 0xa7, 0xc8, 0xc8, 0x60, 0x06, 0x00, 0x00, 0x06, 0x06, 0x66, 0xae, 0xad, 0x8b, 0xad, 0xad, 0xad, 0xad, 0xad, 0xb3, 0xad, 0xb5, 0x07, 0x07, 0x07, 0xf0, 0x8b, 0xad, 0xad, 0xad, 0xad, 0xad, 0x8b, 0xa7, 0xae, 0xa7, 0x6c, 0x06, 0x00, 0x00, 0x00, 0x06, 0x60, 0xa7, 0xb4, 0xad, 0xad, 0xad, 0xb3, 0xb3, 0xd4, 0xd4, 0xb3, 0x8c, 0xb6, 0x07, 0xb6, 0x8c, 0xb3, 0xd4, 0xb3, 0xb3, 0xad, 0xad, 0xad, 0xb4, 0xad, 0x66, 0x00, 0x06, 0x00, 0x00, 0xed, 0x06, 0xed, 0x66, 0xae, 0xd5, 0xad, 0xd4, 0xd4, 0xd5, 0xd5, 0xd5, 0xdb, 0xb4, 0xb4, 0xb4, 0xb4, 0xb4, 0xd5, 0xd5, 0xd5, 0xd4, 0xd4, 0xad, 0xd5, 0xb4, 0x0e, 0x06, 0x06, 0x06, 0x00, 0x00, 0x04, 0x06, 0x04, 0x06, 0x0b, 0xae, 0xdb, 0xd4, 0xd5, 0xdb, 0xdb, 0xdb, 0xdb, 0xdb, 0xdb, 0xdb, 0xdb, 0xdb, 0xdb, 0xdb, 0xdb, 0xd5, 0xd4, 0xdb, 0xb4, 0x66, 0x04, 0x06, 0x04, 0x06, 0x00, 0x00, 0x06, 0x06, 0xed, 0x06, 0x06, 0x0e, 0xae, 0xdc, 0xdb, 0xdb, 0xdb, 0xdb, 0xdb, 0xdb, 0xdc, 0xdc, 0xdb, 0xdb, 0xdb, 0xdb, 0xdb, 0xdb, 0xdc, 0xb4, 0x66, 0x6c, 0xed, 0x06, 0x06, 0x06, 0x00, 0x00, 0x00, 0x06, 0x04, 0x06, 0x00, 0x06, 0x0b, 0xae, 0xdc, 0xe9, 0xdc, 0xdc, 0xdc, 0xdc, 0xdc, 0xdc, 0xdc, 0xdc, 0xdc, 0xdc, 0xe9, 0xe9, 0xb4, 0x0e, 0x00, 0x06, 0x04, 0x06, 0x00, 0x06, 0x00, 0x00, 0x06, 0x06, 0xed, 0x06, 0xed, 0x06, 0xf8, 0x0e, 0x66, 0xb4, 0xdc, 0xe2, 0xe2, 0xe2, 0xe2, 0xe2, 0xe2, 0xe2, 0xe2, 0xdd, 0xb4, 0xa7, 0x16, 0x06, 0x06, 0x06, 0xed, 0x06, 0xed, 0x06, 0x00, 0x00, 0x04, 0x06, 0x04, 0x06, 0x04, 0x06, 0x04, 0x06, 0x60, 0x0e, 0x60, 0x8c, 0xb4, 0xb5, 0xdc, 0xdc, 0xbb, 0xb4, 0x8c, 0x66, 0x0b, 0x6c, 0x04, 0x06, 0x04, 0x06, 0x04, 0x06, 0x04, 0x06, 0x00, 0x00, 0x06, 0x06, 0xed, 0x06, 0x06, 0x06, 0xed, 0x06, 0x06, 0x06, 0xec, 0x6c, 0x0e, 0x0e, 0x44, 0x0e, 0x0e, 0x0e, 0x13, 0x06, 0x06, 0x06, 0xed, 0x06, 0x06, 0x06, 0xed, 0x06, 0x06, 0x06, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }; uint8 compressed_16x1x16[] = { 0x0c, 0x84, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }; uint8 decompressed_16x1x16[] = { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }; uint8 compressed_32x32x16[] = { 0x1c, 0x84, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xca, 0xef, 0x1a, 0x8a, 0xcf, 0x12, 0x4e, 0x12, 0xce, 0x09, 0xaf, 0x09, 0x8f, 0x01, 0x8f, 0x01, 0xaf, 0x09, 0xce, 0x09, 0x2e, 0x12, 0xaf, 0x12, 0x2a, 0x0a, 0x8e, 0x8f, 0x12, 0xae, 0x09, 0xd2, 0x01, 0x9b, 0x23, 0x1d, 0x5d, 0x1e, 0x86, 0xbf, 0x9e, 0xdf, 0xa6, 0x5f, 0x8e, 0x7e, 0x6d, 0xfc, 0x2b, 0x16, 0x02, 0x8f, 0x09, 0x4f, 0x12, 0x11, 0x91, 0xce, 0x09, 0x17, 0x02, 0x1e, 0x55, 0x5f, 0xaf, 0xff, 0xcf, 0xff, 0xc7, 0xff, 0xbf, 0xff, 0xb7, 0xff, 0xb7, 0xff, 0xb7, 0xff, 0xc7, 0xff, 0xcf, 0xbf, 0xb7, 0xbe, 0x6d, 0xba, 0x02, 0xae, 0x09, 0xcf, 0x12, 0x0d, 0x94, 0xcf, 0x12, 0x6f, 0x01, 0x1d, 0x2c, 0x7f, 0x9f, 0xff, 0xaf, 0xff, 0x97, 0xdf, 0x87, 0xbf, 0x8f, 0xbf, 0x97, 0xbf, 0x9f, 0xbf, 0x9f, 0xbf, 0x97, 0xbf, 0x8f, 0xdf, 0x87, 0xff, 0x8f, 0xff, 0xa7, 0xdf, 0xa7, 0xdd, 0x3c, 0x4f, 0x01, 0x8f, 0x12, 0x0b, 0x96, 0xaf, 0x12, 0x2f, 0x01, 0xbd, 0x34, 0xbf, 0x8f, 0x5f, 0x77, 0x5f, 0x6f, 0x9f, 0x77, 0x9f, 0x7f, 0xbf, 0x87, 0xbf, 0x87, 0xbf, 0x87, 0xbf, 0x87, 0xbf, 0x87, 0xbf, 0x87, 0x9f, 0x7f, 0x7f, 0x7f, 0x5f, 0x6f, 0x3f, 0x6f, 0xbf, 0x87, 0xbf, 0x55, 0x72, 0x01, 0x6f, 0x12, 0x09, 0x98, 0xcf, 0x12, 0x4f, 0x01, 0xde, 0x34, 0xff, 0x6e, 0x5f, 0x4e, 0xbf, 0x5e, 0x1f, 0x67, 0x3f, 0x6f, 0x5f, 0x6f, 0x5f, 0x6f, 0x5f, 0x77, 0x5f, 0x77, 0x5f, 0x77, 0x5f, 0x77, 0x5f, 0x6f, 0x5f, 0x6f, 0x3f, 0x6f, 0x1f, 0x67, 0xdf, 0x5e, 0x3f, 0x4e, 0xbf, 0x66, 0xdf, 0x4d, 0x72, 0x01, 0xaf, 0x12, 0x08, 0x99, 0x8e, 0x09, 0xfc, 0x1b, 0x3f, 0x4e, 0x3e, 0x25, 0xff, 0x3d, 0x5f, 0x4e, 0x9f, 0x56, 0xbf, 0x5e, 0xdf, 0x66, 0xdf, 0x5e, 0x3c, 0x56, 0x79, 0x4d, 0x17, 0x4d, 0x99, 0x4d, 0x5d, 0x5e, 0xdf, 0x66, 0xbf, 0x5e, 0x9f, 0x56, 0x5f, 0x4e, 0xff, 0x3d, 0x1e, 0x25, 0xdf, 0x3d, 0xfe, 0x34, 0x2f, 0x01, 0xcf, 0x12, 0x06, 0x80, 0xa6, 0x0f, 0x0a, 0xba, 0x02, 0x5f, 0x35, 0x5d, 0x0c, 0xbd, 0x14, 0x5e, 0x2d, 0xbe, 0x3d, 0xff, 0x3d, 0x1f, 0x46, 0x3f, 0x46, 0x1e, 0x4e, 0xd7, 0x44, 0xb7, 0xa5, 0xf7, 0xbd, 0x97, 0x95, 0xb7, 0x44, 0x9c, 0x45, 0x1f, 0x46, 0xff, 0x3d, 0xbf, 0x3d, 0x5e, 0x2d, 0xbd, 0x1c, 0x3d, 0x04, 0x1e, 0x25, 0xbc, 0x13, 0xae, 0x09, 0xef, 0x1a, 0xef, 0x1a, 0x00, 0x00, 0x00, 0x00, 0xef, 0x1a, 0xaf, 0x12, 0x31, 0x01, 0x7d, 0x24, 0xdc, 0x03, 0xfc, 0x03, 0x5d, 0x0c, 0xbd, 0x14, 0x1e, 0x25, 0x3e, 0x2d, 0x7e, 0x35, 0x9e, 0x35, 0xfb, 0x34, 0x17, 0x6d, 0x18, 0xc6, 0x18, 0xc6, 0x18, 0xc6, 0xb8, 0xa5, 0x57, 0x2c, 0xfb, 0x2c, 0x5e, 0x2d, 0x1e, 0x25, 0xbd, 0x14, 0x5d, 0x0c, 0xfd, 0x03, 0x7a, 0x03, 0x9e, 0x24, 0xd6, 0x01, 0x6f, 0x12, 0xef, 0x1a, 0x00, 0x00, 0x00, 0x00, 0xef, 0x1a, 0x2f, 0x0a, 0x79, 0x02, 0xdd, 0x0b, 0xf8, 0x02, 0x9b, 0x03, 0xfd, 0x03, 0x3d, 0x0c, 0x7d, 0x14, 0xbd, 0x1c, 0xdd, 0x1c, 0xfe, 0x24, 0x7a, 0x1c, 0x18, 0x6d, 0x79, 0xce, 0x79, 0xce, 0x79, 0xce, 0x79, 0xce, 0xd9, 0xad, 0xd7, 0x23, 0x5b, 0x14, 0x7d, 0x14, 0x3d, 0x0c, 0xfd, 0x03, 0x9b, 0x03, 0x18, 0x03, 0x7b, 0x03, 0x1b, 0x0b, 0xaf, 0x09, 0xef, 0x1a, 0x00, 0x00, 0x00, 0x00, 0xef, 0x1a, 0x6f, 0x01, 0xda, 0x0a, 0x97, 0x02, 0x96, 0x02, 0x19, 0x03, 0x9b, 0x03, 0xfd, 0x03, 0x1d, 0x0c, 0x3d, 0x0c, 0x3d, 0x0c, 0x5d, 0x14, 0x1a, 0x14, 0xd8, 0x5c, 0xba, 0xd6, 0xba, 0xd6, 0xba, 0xd6, 0xdb, 0xd6, 0xdb, 0xde, 0x1a, 0xae, 0x77, 0x13, 0xba, 0x03, 0xfd, 0x03, 0x9b, 0x03, 0x19, 0x03, 0xb7, 0x02, 0x54, 0x02, 0x1b, 0x0b, 0x31, 0x01, 0xcf, 0x12, 0x00, 0x00, 0x00, 0x00, 0xaf, 0x12, 0x52, 0x01, 0xba, 0x02, 0xf3, 0x01, 0x34, 0x02, 0xb7, 0x02, 0xf8, 0x02, 0x7b, 0x03, 0xbc, 0x03, 0xdc, 0x03, 0xfd, 0x03, 0xfd, 0x03, 0x1d, 0x0c, 0x99, 0x03, 0x9a, 0x8d, 0x3c, 0xe7, 0x3c, 0xe7, 0x3c, 0xe7, 0x3c, 0xe7, 0x3c, 0xe7, 0x5b, 0xb6, 0x36, 0x0b, 0x39, 0x03, 0xf8, 0x02, 0xb7, 0x02, 0x34, 0x02, 0xd2, 0x01, 0x99, 0x02, 0x97, 0x01, 0x4f, 0x12, 0x00, 0x00, 0x00, 0x00, 0x6f, 0x12, 0x95, 0x01, 0x77, 0x02, 0xd2, 0x01, 0x13, 0x02, 0x55, 0x02, 0x75, 0x02, 0x74, 0x02, 0x94, 0x02, 0xb5, 0x02, 0xd6, 0x02, 0xf6, 0x02, 0xf6, 0x02, 0xf6, 0x02, 0x17, 0x03, 0xbb, 0x8d, 0x9e, 0xf7, 0x9e, 0xf7, 0x9e, 0xf7, 0x9e, 0xf7, 0x9e, 0xf7, 0x7c, 0xbe, 0xb4, 0x0a, 0x75, 0x02, 0x55, 0x02, 0xf3, 0x01, 0xd2, 0x01, 0x35, 0x02, 0xf8, 0x01, 0xef, 0x09, 0x00, 0x00, 0x00, 0x00, 0x0e, 0x0a, 0xf6, 0x01, 0x14, 0x02, 0xd2, 0x01, 0xf3, 0x01, 0xf2, 0x01, 0x75, 0x43, 0xfd, 0xce, 0x6e, 0xff, 0xff, 0x91, 0xbc, 0xc6, 0x32, 0x12, 0xf2, 0x01, 0xf3, 0x01, 0xd2, 0x01, 0xd2, 0x01, 0x17, 0x02, 0x8e, 0x09, 0x00, 0x00, 0x00, 0x00, 0xef, 0x09, 0xf5, 0x01, 0x14, 0x02, 0xd2, 0x01, 0xd2, 0x01, 0xb0, 0x01, 0x5e, 0xe7, 0x70, 0xff, 0xff, 0x90, 0x9c, 0xc6, 0xf0, 0x09, 0xd2, 0x01, 0xd2, 0x01, 0x13, 0x02, 0x16, 0x02, 0x8f, 0x01, 0x00, 0x00, 0x00, 0x00, 0x0f, 0x0a, 0x3a, 0x1b, 0x9d, 0x75, 0xdb, 0x54, 0xfa, 0x33, 0xd5, 0x12, 0x7e, 0xe7, 0x10, 0x91, 0xbd, 0xc6, 0xf6, 0x1a, 0xfa, 0x33, 0xdb, 0x5c, 0xbd, 0x7d, 0x3b, 0x3c, 0x90, 0x01, 0x00, 0x00, 0x00, 0x00, 0x2f, 0x0a, 0x5b, 0x4c, 0xde, 0xae, 0xdd, 0x85, 0x7c, 0x75, 0xfb, 0x5c, 0x5b, 0x75, 0x3e, 0xdf, 0x0e, 0x80, 0xc6, 0x1e, 0xd7, 0x9a, 0x54, 0xfb, 0x5c, 0x7c, 0x75, 0xdd, 0x85, 0xbe, 0xa6, 0xbd, 0x7d, 0xf0, 0x09, 0x00, 0x00, 0x00, 0x00, 0xb0, 0x12, 0x9b, 0x4c, 0x1f, 0xb7, 0xfd, 0x8d, 0x7c, 0x7d, 0x3c, 0x6d, 0xdc, 0x5c, 0x9c, 0x4c, 0x7c, 0x44, 0x7c, 0x3c, 0x5c, 0x34, 0x3c, 0x34, 0x3c, 0x2c, 0x3c, 0x2c, 0x1c, 0x24, 0x7e, 0xa6, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x3f, 0xd7, 0xdc, 0x54, 0xdc, 0x5c, 0x3c, 0x6d, 0x7c, 0x7d, 0xdc, 0x8d, 0xde, 0xb6, 0xdd, 0x85, 0x71, 0x0a, 0x00, 0x00, 0x00, 0x00, 0xcf, 0x12, 0x5a, 0x44, 0x5f, 0xc7, 0x1d, 0x96, 0xbc, 0x85, 0x5c, 0x75, 0xfb, 0x64, 0xbc, 0x54, 0x9b, 0x4c, 0x7c, 0x44, 0x5c, 0x3c, 0x5c, 0x34, 0x3c, 0x34, 0x3c, 0x2c, 0x7e, 0xae, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x3f, 0xd7, 0xbc, 0x54, 0xbc, 0x54, 0x1c, 0x65, 0x5c, 0x75, 0xbc, 0x85, 0x1d, 0x96, 0x3f, 0xc7, 0xbd, 0x7d, 0x90, 0x12, 0x00, 0x00, 0x00, 0x00, 0xef, 0x1a, 0x57, 0x1b, 0x3f, 0xc7, 0x7d, 0xa6, 0xdc, 0x8d, 0x7c, 0x7d, 0x3c, 0x6d, 0xdc, 0x5c, 0xbb, 0x54, 0x7b, 0x4c, 0x7b, 0x44, 0x5b, 0x3c, 0x5c, 0x3c, 0xdd, 0x85, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x3f, 0xd7, 0xbc, 0x54, 0xbb, 0x54, 0xdb, 0x5c, 0x3c, 0x6d, 0x7c, 0x7d, 0xdc, 0x8d, 0x5d, 0xa6, 0x7f, 0xcf, 0x5a, 0x44, 0xef, 0x12, 0x00, 0x00, 0x00, 0x00, 0xef, 0x1a, 0xb1, 0x12, 0x3d, 0x96, 0x1e, 0xc7, 0xfc, 0x9d, 0xbc, 0x8d, 0x5c, 0x7d, 0x1b, 0x6d, 0xdb, 0x5c, 0x9b, 0x54, 0x7b, 0x4c, 0x7b, 0x44, 0x5b, 0x44, 0x1d, 0x9e, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x3e, 0xd7, 0xbb, 0x54, 0x9b, 0x54, 0xdb, 0x5c, 0x1c, 0x6d, 0x5c, 0x7d, 0xbc, 0x8d, 0x1d, 0x9e, 0xde, 0xbe, 0x1e, 0xbf, 0xf5, 0x0a, 0xef, 0x1a, 0x00, 0x00, 0x00, 0x00, 0xef, 0x1a, 0xcf, 0x12, 0xb8, 0x33, 0x7f, 0xd7, 0x7d, 0xae, 0xfc, 0x95, 0x9c, 0x85, 0x3b, 0x75, 0xfb, 0x64, 0xdb, 0x5c, 0x9b, 0x54, 0x9b, 0x54, 0x7b, 0x4c, 0xfd, 0x9d, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x3e, 0xd7, 0xbb, 0x5c, 0x9b, 0x54, 0xdb, 0x5c, 0xfb, 0x64, 0x3b, 0x75, 0x9c, 0x85, 0xdc, 0x95, 0x7d, 0xae, 0x9f, 0xdf, 0x1b, 0x65, 0xd0, 0x12, 0xef, 0x1a, 0x00, 0x00, 0x00, 0x00, 0xef, 0x1a, 0xef, 0x1a, 0xd1, 0x12, 0xbd, 0x85, 0x5f, 0xd7, 0x5d, 0xae, 0xdc, 0x95, 0x7c, 0x85, 0x3b, 0x7d, 0x1b, 0x6d, 0xdb, 0x64, 0xbb, 0x5c, 0xbb, 0x5c, 0xfb, 0x64, 0x7f, 0xe7, 0xff, 0xff, 0x1e, 0xd7, 0xdb, 0x64, 0xbb, 0x5c, 0xdb, 0x64, 0xfb, 0x6c, 0x3b, 0x7d, 0x9c, 0x85, 0xdc, 0x95, 0x3d, 0xae, 0x3e, 0xcf, 0xbe, 0xb6, 0xf4, 0x0a, 0xef, 0x1a, 0xef, 0x1a, 0x00, 0x00, 0x00, 0x00, 0xef, 0x1a, 0xef, 0x1a, 0xef, 0x1a, 0xd3, 0x0a, 0x5d, 0xa6, 0x5e, 0xd7, 0x5d, 0xae, 0xdc, 0x9d, 0x9c, 0x8d, 0x5b, 0x85, 0x3b, 0x7d, 0x1b, 0x75, 0xfb, 0x6c, 0xdb, 0x6c, 0xdb, 0x6c, 0x3b, 0x7d, 0xdb, 0x6c, 0xfb, 0x6c, 0x1b, 0x75, 0x3b, 0x7d, 0x5b, 0x85, 0x9c, 0x8d, 0xdc, 0x9d, 0x5d, 0xae, 0x3e, 0xd7, 0x3e, 0xcf, 0x36, 0x13, 0xef, 0x1a, 0x07, 0x98, 0xef, 0x1a, 0xd5, 0x0a, 0xbe, 0xb6, 0x5e, 0xdf, 0x5d, 0xae, 0xdc, 0x9d, 0xbc, 0x95, 0x7b, 0x8d, 0x5b, 0x85, 0x3b, 0x85, 0x3b, 0x7d, 0x1b, 0x7d, 0x1b, 0x7d, 0x3b, 0x7d, 0x3b, 0x85, 0x5b, 0x85, 0x9c, 0x8d, 0xbc, 0x95, 0xdc, 0x9d, 0x5d, 0xb6, 0x3e, 0xd7, 0x7f, 0xd7, 0x78, 0x23, 0xef, 0x12, 0x09, 0x97, 0xef, 0x1a, 0xd5, 0x0a, 0x7e, 0xae, 0x5e, 0xdf, 0x7d, 0xbe, 0x1c, 0xae, 0xdc, 0xa5, 0xbc, 0x9d, 0x9c, 0x95, 0x9b, 0x95, 0x9c, 0x8d, 0x9c, 0x8d, 0x9b, 0x95, 0x9c, 0x95, 0xbc, 0x9d, 0xdc, 0xa5, 0x1c, 0xae, 0x7d, 0xbe, 0x5e, 0xdf, 0x3e, 0xcf, 0x77, 0x23, 0xcf, 0x12, 0xef, 0x1a, 0x0a, 0x95, 0xef, 0x1a, 0xb3, 0x0a, 0xdd, 0x95, 0x9f, 0xe7, 0x1e, 0xd7, 0x9d, 0xbe, 0x3d, 0xae, 0x1c, 0xae, 0xfc, 0xa5, 0xdc, 0xa5, 0xdc, 0xa5, 0xfc, 0xa5, 0x1c, 0xae, 0x3d, 0xae, 0x7d, 0xbe, 0x1e, 0xd7, 0xbf, 0xef, 0x7d, 0xae, 0xf5, 0x12, 0xef, 0x12, 0xef, 0x1a, 0x0c, 0x93, 0xef, 0x1a, 0x90, 0x12, 0xd8, 0x3b, 0x7d, 0xae, 0x7f, 0xe7, 0x7f, 0xe7, 0x1e, 0xd7, 0xde, 0xce, 0xbd, 0xc6, 0xbd, 0xc6, 0xde, 0xce, 0x1e, 0xd7, 0x7f, 0xe7, 0x9f, 0xef, 0xde, 0xc6, 0x7a, 0x54, 0xb2, 0x0a, 0xef, 0x1a, 0xef, 0x1a, 0x0e, 0x8f, 0xef, 0x1a, 0xcf, 0x12, 0xb0, 0x12, 0x56, 0x1b, 0xda, 0x64, 0x1d, 0xa6, 0xbe, 0xbe, 0xfe, 0xce, 0xfe, 0xce, 0xde, 0xc6, 0x5d, 0xae, 0x3b, 0x7d, 0x97, 0x2b, 0xb2, 0x0a, 0xcf, 0x12, 0x68, 0xef, 0x1a, 0x0a, 0x8b, 0xef, 0x1a, 0xef, 0x1a, 0xef, 0x1a, 0xcf, 0x12, 0xb0, 0x12, 0x91, 0x0a, 0xb3, 0x0a, 0xb3, 0x0a, 0x91, 0x0a, 0xb0, 0x12, 0xcf, 0x12, 0x69, 0xef, 0x1a, 0x84, 0xef, 0x1a, 0xef, 0x1a, 0x00, 0x00, 0x00, 0x00 }; uint8 decompressed_32x32x16[] = { 0xef, 0x1a, 0xef, 0x1a, 0xef, 0x1a, 0xef, 0x1a, 0xef, 0x1a, 0xef, 0x1a, 0xef, 0x1a, 0xef, 0x1a, 0xef, 0x1a, 0xef, 0x1a, 0xef, 0x1a, 0xcf, 0x12, 0xb0, 0x12, 0x91, 0x0a, 0xb3, 0x0a, 0xb3, 0x0a, 0x91, 0x0a, 0xb0, 0x12, 0xcf, 0x12, 0xef, 0x1a, 0xef, 0x1a, 0xef, 0x1a, 0xef, 0x1a, 0xef, 0x1a, 0xef, 0x1a, 0xef, 0x1a, 0xef, 0x1a, 0xef, 0x1a, 0xef, 0x1a, 0xef, 0x1a, 0x00, 0x00, 0x00, 0x00, 0xef, 0x1a, 0xef, 0x1a, 0xef, 0x1a, 0xef, 0x1a, 0xef, 0x1a, 0xef, 0x1a, 0xef, 0x1a, 0xef, 0x1a, 0xcf, 0x12, 0xb0, 0x12, 0x56, 0x1b, 0xda, 0x64, 0x1d, 0xa6, 0xbe, 0xbe, 0xfe, 0xce, 0xfe, 0xce, 0xde, 0xc6, 0x5d, 0xae, 0x3b, 0x7d, 0x97, 0x2b, 0xb2, 0x0a, 0xcf, 0x12, 0xef, 0x1a, 0xef, 0x1a, 0xef, 0x1a, 0xef, 0x1a, 0xef, 0x1a, 0xef, 0x1a, 0xef, 0x1a, 0xef, 0x1a, 0x00, 0x00, 0x00, 0x00, 0xef, 0x1a, 0xef, 0x1a, 0xef, 0x1a, 0xef, 0x1a, 0xef, 0x1a, 0xef, 0x1a, 0xef, 0x1a, 0x90, 0x12, 0xd8, 0x3b, 0x7d, 0xae, 0x7f, 0xe7, 0x7f, 0xe7, 0x1e, 0xd7, 0xde, 0xce, 0xbd, 0xc6, 0xbd, 0xc6, 0xde, 0xce, 0x1e, 0xd7, 0x7f, 0xe7, 0x9f, 0xef, 0xde, 0xc6, 0x7a, 0x54, 0xb2, 0x0a, 0xef, 0x1a, 0xef, 0x1a, 0xef, 0x1a, 0xef, 0x1a, 0xef, 0x1a, 0xef, 0x1a, 0xef, 0x1a, 0x00, 0x00, 0x00, 0x00, 0xef, 0x1a, 0xef, 0x1a, 0xef, 0x1a, 0xef, 0x1a, 0xef, 0x1a, 0xef, 0x1a, 0xb3, 0x0a, 0xdd, 0x95, 0x9f, 0xe7, 0x1e, 0xd7, 0x9d, 0xbe, 0x3d, 0xae, 0x1c, 0xae, 0xfc, 0xa5, 0xdc, 0xa5, 0xdc, 0xa5, 0xfc, 0xa5, 0x1c, 0xae, 0x3d, 0xae, 0x7d, 0xbe, 0x1e, 0xd7, 0xbf, 0xef, 0x7d, 0xae, 0xf5, 0x12, 0xef, 0x12, 0xef, 0x1a, 0xef, 0x1a, 0xef, 0x1a, 0xef, 0x1a, 0xef, 0x1a, 0x00, 0x00, 0x00, 0x00, 0xef, 0x1a, 0xef, 0x1a, 0xef, 0x1a, 0xef, 0x1a, 0xef, 0x1a, 0xd5, 0x0a, 0x7e, 0xae, 0x5e, 0xdf, 0x7d, 0xbe, 0x1c, 0xae, 0xdc, 0xa5, 0xbc, 0x9d, 0x9c, 0x95, 0x9b, 0x95, 0x9c, 0x8d, 0x9c, 0x8d, 0x9b, 0x95, 0x9c, 0x95, 0xbc, 0x9d, 0xdc, 0xa5, 0x1c, 0xae, 0x7d, 0xbe, 0x5e, 0xdf, 0x3e, 0xcf, 0x77, 0x23, 0xcf, 0x12, 0xef, 0x1a, 0xef, 0x1a, 0xef, 0x1a, 0xef, 0x1a, 0x00, 0x00, 0x00, 0x00, 0xef, 0x1a, 0xef, 0x1a, 0xef, 0x1a, 0xef, 0x1a, 0xd5, 0x0a, 0xbe, 0xb6, 0x5e, 0xdf, 0x5d, 0xae, 0xdc, 0x9d, 0xbc, 0x95, 0x7b, 0x8d, 0x5b, 0x85, 0x3b, 0x85, 0x3b, 0x7d, 0x1b, 0x7d, 0x1b, 0x7d, 0x3b, 0x7d, 0x3b, 0x85, 0x5b, 0x85, 0x9c, 0x8d, 0xbc, 0x95, 0xdc, 0x9d, 0x5d, 0xb6, 0x3e, 0xd7, 0x7f, 0xd7, 0x78, 0x23, 0xef, 0x12, 0xef, 0x1a, 0xef, 0x1a, 0xef, 0x1a, 0x00, 0x00, 0x00, 0x00, 0xef, 0x1a, 0xef, 0x1a, 0xef, 0x1a, 0xd3, 0x0a, 0x5d, 0xa6, 0x5e, 0xd7, 0x5d, 0xae, 0xdc, 0x9d, 0x9c, 0x8d, 0x5b, 0x85, 0x3b, 0x7d, 0x1b, 0x75, 0xfb, 0x6c, 0xdb, 0x6c, 0xdb, 0x6c, 0x3b, 0x7d, 0xdb, 0x6c, 0xfb, 0x6c, 0x1b, 0x75, 0x3b, 0x7d, 0x5b, 0x85, 0x9c, 0x8d, 0xdc, 0x9d, 0x5d, 0xae, 0x3e, 0xd7, 0x3e, 0xcf, 0x36, 0x13, 0xef, 0x1a, 0xef, 0x1a, 0xef, 0x1a, 0x00, 0x00, 0x00, 0x00, 0xef, 0x1a, 0xef, 0x1a, 0xd1, 0x12, 0xbd, 0x85, 0x5f, 0xd7, 0x5d, 0xae, 0xdc, 0x95, 0x7c, 0x85, 0x3b, 0x7d, 0x1b, 0x6d, 0xdb, 0x64, 0xbb, 0x5c, 0xbb, 0x5c, 0xfb, 0x64, 0x7f, 0xe7, 0xff, 0xff, 0x1e, 0xd7, 0xdb, 0x64, 0xbb, 0x5c, 0xdb, 0x64, 0xfb, 0x6c, 0x3b, 0x7d, 0x9c, 0x85, 0xdc, 0x95, 0x3d, 0xae, 0x3e, 0xcf, 0xbe, 0xb6, 0xf4, 0x0a, 0xef, 0x1a, 0xef, 0x1a, 0x00, 0x00, 0x00, 0x00, 0xef, 0x1a, 0xcf, 0x12, 0xb8, 0x33, 0x7f, 0xd7, 0x7d, 0xae, 0xfc, 0x95, 0x9c, 0x85, 0x3b, 0x75, 0xfb, 0x64, 0xdb, 0x5c, 0x9b, 0x54, 0x9b, 0x54, 0x7b, 0x4c, 0xfd, 0x9d, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x3e, 0xd7, 0xbb, 0x5c, 0x9b, 0x54, 0xdb, 0x5c, 0xfb, 0x64, 0x3b, 0x75, 0x9c, 0x85, 0xdc, 0x95, 0x7d, 0xae, 0x9f, 0xdf, 0x1b, 0x65, 0xd0, 0x12, 0xef, 0x1a, 0x00, 0x00, 0x00, 0x00, 0xef, 0x1a, 0xb1, 0x12, 0x3d, 0x96, 0x1e, 0xc7, 0xfc, 0x9d, 0xbc, 0x8d, 0x5c, 0x7d, 0x1b, 0x6d, 0xdb, 0x5c, 0x9b, 0x54, 0x7b, 0x4c, 0x7b, 0x44, 0x5b, 0x44, 0x1d, 0x9e, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x3e, 0xd7, 0xbb, 0x54, 0x9b, 0x54, 0xdb, 0x5c, 0x1c, 0x6d, 0x5c, 0x7d, 0xbc, 0x8d, 0x1d, 0x9e, 0xde, 0xbe, 0x1e, 0xbf, 0xf5, 0x0a, 0xef, 0x1a, 0x00, 0x00, 0x00, 0x00, 0xef, 0x1a, 0x57, 0x1b, 0x3f, 0xc7, 0x7d, 0xa6, 0xdc, 0x8d, 0x7c, 0x7d, 0x3c, 0x6d, 0xdc, 0x5c, 0xbb, 0x54, 0x7b, 0x4c, 0x7b, 0x44, 0x5b, 0x3c, 0x5c, 0x3c, 0xdd, 0x85, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x3f, 0xd7, 0xbc, 0x54, 0xbb, 0x54, 0xdb, 0x5c, 0x3c, 0x6d, 0x7c, 0x7d, 0xdc, 0x8d, 0x5d, 0xa6, 0x7f, 0xcf, 0x5a, 0x44, 0xef, 0x12, 0x00, 0x00, 0x00, 0x00, 0xcf, 0x12, 0x5a, 0x44, 0x5f, 0xc7, 0x1d, 0x96, 0xbc, 0x85, 0x5c, 0x75, 0xfb, 0x64, 0xbc, 0x54, 0x9b, 0x4c, 0x7c, 0x44, 0x5c, 0x3c, 0x5c, 0x34, 0x3c, 0x34, 0x3c, 0x2c, 0x7e, 0xae, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x3f, 0xd7, 0xbc, 0x54, 0xbc, 0x54, 0x1c, 0x65, 0x5c, 0x75, 0xbc, 0x85, 0x1d, 0x96, 0x3f, 0xc7, 0xbd, 0x7d, 0x90, 0x12, 0x00, 0x00, 0x00, 0x00, 0xb0, 0x12, 0x9b, 0x4c, 0x1f, 0xb7, 0xfd, 0x8d, 0x7c, 0x7d, 0x3c, 0x6d, 0xdc, 0x5c, 0x9c, 0x4c, 0x7c, 0x44, 0x7c, 0x3c, 0x5c, 0x34, 0x3c, 0x34, 0x3c, 0x2c, 0x3c, 0x2c, 0x1c, 0x24, 0x7e, 0xa6, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x3f, 0xd7, 0xdc, 0x54, 0xdc, 0x5c, 0x3c, 0x6d, 0x7c, 0x7d, 0xdc, 0x8d, 0xde, 0xb6, 0xdd, 0x85, 0x71, 0x0a, 0x00, 0x00, 0x00, 0x00, 0x2f, 0x0a, 0x5b, 0x4c, 0xde, 0xae, 0xdd, 0x85, 0x7c, 0x75, 0xfb, 0x5c, 0x5b, 0x75, 0x3e, 0xdf, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x1e, 0xd7, 0x9a, 0x54, 0xfb, 0x5c, 0x7c, 0x75, 0xdd, 0x85, 0xbe, 0xa6, 0xbd, 0x7d, 0xf0, 0x09, 0x00, 0x00, 0x00, 0x00, 0x0f, 0x0a, 0x3a, 0x1b, 0x9d, 0x75, 0xdb, 0x54, 0xfa, 0x33, 0xd5, 0x12, 0x7e, 0xe7, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xbd, 0xc6, 0xf6, 0x1a, 0xfa, 0x33, 0xdb, 0x5c, 0xbd, 0x7d, 0x3b, 0x3c, 0x90, 0x01, 0x00, 0x00, 0x00, 0x00, 0xef, 0x09, 0xf5, 0x01, 0x14, 0x02, 0xd2, 0x01, 0xd2, 0x01, 0xb0, 0x01, 0x5e, 0xe7, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x9c, 0xc6, 0xf0, 0x09, 0xd2, 0x01, 0xd2, 0x01, 0x13, 0x02, 0x16, 0x02, 0x8f, 0x01, 0x00, 0x00, 0x00, 0x00, 0x0e, 0x0a, 0xf6, 0x01, 0x14, 0x02, 0xd2, 0x01, 0xf3, 0x01, 0xf2, 0x01, 0x75, 0x43, 0xfd, 0xce, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xbc, 0xc6, 0x32, 0x12, 0xf2, 0x01, 0xf3, 0x01, 0xd2, 0x01, 0xd2, 0x01, 0x17, 0x02, 0x8e, 0x09, 0x00, 0x00, 0x00, 0x00, 0x6f, 0x12, 0x95, 0x01, 0x77, 0x02, 0xd2, 0x01, 0x13, 0x02, 0x55, 0x02, 0x75, 0x02, 0x74, 0x02, 0x94, 0x02, 0xb5, 0x02, 0xd6, 0x02, 0xf6, 0x02, 0xf6, 0x02, 0xf6, 0x02, 0x17, 0x03, 0xbb, 0x8d, 0x9e, 0xf7, 0x9e, 0xf7, 0x9e, 0xf7, 0x9e, 0xf7, 0x9e, 0xf7, 0x7c, 0xbe, 0xb4, 0x0a, 0x75, 0x02, 0x55, 0x02, 0xf3, 0x01, 0xd2, 0x01, 0x35, 0x02, 0xf8, 0x01, 0xef, 0x09, 0x00, 0x00, 0x00, 0x00, 0xaf, 0x12, 0x52, 0x01, 0xba, 0x02, 0xf3, 0x01, 0x34, 0x02, 0xb7, 0x02, 0xf8, 0x02, 0x7b, 0x03, 0xbc, 0x03, 0xdc, 0x03, 0xfd, 0x03, 0xfd, 0x03, 0x1d, 0x0c, 0x99, 0x03, 0x9a, 0x8d, 0x3c, 0xe7, 0x3c, 0xe7, 0x3c, 0xe7, 0x3c, 0xe7, 0x3c, 0xe7, 0x5b, 0xb6, 0x36, 0x0b, 0x39, 0x03, 0xf8, 0x02, 0xb7, 0x02, 0x34, 0x02, 0xd2, 0x01, 0x99, 0x02, 0x97, 0x01, 0x4f, 0x12, 0x00, 0x00, 0x00, 0x00, 0xef, 0x1a, 0x6f, 0x01, 0xda, 0x0a, 0x97, 0x02, 0x96, 0x02, 0x19, 0x03, 0x9b, 0x03, 0xfd, 0x03, 0x1d, 0x0c, 0x3d, 0x0c, 0x3d, 0x0c, 0x5d, 0x14, 0x1a, 0x14, 0xd8, 0x5c, 0xba, 0xd6, 0xba, 0xd6, 0xba, 0xd6, 0xdb, 0xd6, 0xdb, 0xde, 0x1a, 0xae, 0x77, 0x13, 0xba, 0x03, 0xfd, 0x03, 0x9b, 0x03, 0x19, 0x03, 0xb7, 0x02, 0x54, 0x02, 0x1b, 0x0b, 0x31, 0x01, 0xcf, 0x12, 0x00, 0x00, 0x00, 0x00, 0xef, 0x1a, 0x2f, 0x0a, 0x79, 0x02, 0xdd, 0x0b, 0xf8, 0x02, 0x9b, 0x03, 0xfd, 0x03, 0x3d, 0x0c, 0x7d, 0x14, 0xbd, 0x1c, 0xdd, 0x1c, 0xfe, 0x24, 0x7a, 0x1c, 0x18, 0x6d, 0x79, 0xce, 0x79, 0xce, 0x79, 0xce, 0x79, 0xce, 0xd9, 0xad, 0xd7, 0x23, 0x5b, 0x14, 0x7d, 0x14, 0x3d, 0x0c, 0xfd, 0x03, 0x9b, 0x03, 0x18, 0x03, 0x7b, 0x03, 0x1b, 0x0b, 0xaf, 0x09, 0xef, 0x1a, 0x00, 0x00, 0x00, 0x00, 0xef, 0x1a, 0xaf, 0x12, 0x31, 0x01, 0x7d, 0x24, 0xdc, 0x03, 0xfc, 0x03, 0x5d, 0x0c, 0xbd, 0x14, 0x1e, 0x25, 0x3e, 0x2d, 0x7e, 0x35, 0x9e, 0x35, 0xfb, 0x34, 0x17, 0x6d, 0x18, 0xc6, 0x18, 0xc6, 0x18, 0xc6, 0xb8, 0xa5, 0x57, 0x2c, 0xfb, 0x2c, 0x5e, 0x2d, 0x1e, 0x25, 0xbd, 0x14, 0x5d, 0x0c, 0xfd, 0x03, 0x7a, 0x03, 0x9e, 0x24, 0xd6, 0x01, 0x6f, 0x12, 0xef, 0x1a, 0x00, 0x00, 0x00, 0x00, 0xef, 0x1a, 0xef, 0x1a, 0x0f, 0x0a, 0xba, 0x02, 0x5f, 0x35, 0x5d, 0x0c, 0xbd, 0x14, 0x5e, 0x2d, 0xbe, 0x3d, 0xff, 0x3d, 0x1f, 0x46, 0x3f, 0x46, 0x1e, 0x4e, 0xd7, 0x44, 0xb7, 0xa5, 0xf7, 0xbd, 0x97, 0x95, 0xb7, 0x44, 0x9c, 0x45, 0x1f, 0x46, 0xff, 0x3d, 0xbf, 0x3d, 0x5e, 0x2d, 0xbd, 0x1c, 0x3d, 0x04, 0x1e, 0x25, 0xbc, 0x13, 0xae, 0x09, 0xef, 0x1a, 0xef, 0x1a, 0x00, 0x00, 0x00, 0x00, 0xef, 0x1a, 0xef, 0x1a, 0xef, 0x1a, 0x8e, 0x09, 0xfc, 0x1b, 0x3f, 0x4e, 0x3e, 0x25, 0xff, 0x3d, 0x5f, 0x4e, 0x9f, 0x56, 0xbf, 0x5e, 0xdf, 0x66, 0xdf, 0x5e, 0x3c, 0x56, 0x79, 0x4d, 0x17, 0x4d, 0x99, 0x4d, 0x5d, 0x5e, 0xdf, 0x66, 0xbf, 0x5e, 0x9f, 0x56, 0x5f, 0x4e, 0xff, 0x3d, 0x1e, 0x25, 0xdf, 0x3d, 0xfe, 0x34, 0x2f, 0x01, 0xcf, 0x12, 0xef, 0x1a, 0xef, 0x1a, 0x00, 0x00, 0x00, 0x00, 0xef, 0x1a, 0xef, 0x1a, 0xef, 0x1a, 0xcf, 0x12, 0x4f, 0x01, 0xde, 0x34, 0xff, 0x6e, 0x5f, 0x4e, 0xbf, 0x5e, 0x1f, 0x67, 0x3f, 0x6f, 0x5f, 0x6f, 0x5f, 0x6f, 0x5f, 0x77, 0x5f, 0x77, 0x5f, 0x77, 0x5f, 0x77, 0x5f, 0x6f, 0x5f, 0x6f, 0x3f, 0x6f, 0x1f, 0x67, 0xdf, 0x5e, 0x3f, 0x4e, 0xbf, 0x66, 0xdf, 0x4d, 0x72, 0x01, 0xaf, 0x12, 0xef, 0x1a, 0xef, 0x1a, 0xef, 0x1a, 0x00, 0x00, 0x00, 0x00, 0xef, 0x1a, 0xef, 0x1a, 0xef, 0x1a, 0xef, 0x1a, 0xaf, 0x12, 0x2f, 0x01, 0xbd, 0x34, 0xbf, 0x8f, 0x5f, 0x77, 0x5f, 0x6f, 0x9f, 0x77, 0x9f, 0x7f, 0xbf, 0x87, 0xbf, 0x87, 0xbf, 0x87, 0xbf, 0x87, 0xbf, 0x87, 0xbf, 0x87, 0x9f, 0x7f, 0x7f, 0x7f, 0x5f, 0x6f, 0x3f, 0x6f, 0xbf, 0x87, 0xbf, 0x55, 0x72, 0x01, 0x6f, 0x12, 0xef, 0x1a, 0xef, 0x1a, 0xef, 0x1a, 0xef, 0x1a, 0x00, 0x00, 0x00, 0x00, 0xef, 0x1a, 0xef, 0x1a, 0xef, 0x1a, 0xef, 0x1a, 0xef, 0x1a, 0xcf, 0x12, 0x6f, 0x01, 0x1d, 0x2c, 0x7f, 0x9f, 0xff, 0xaf, 0xff, 0x97, 0xdf, 0x87, 0xbf, 0x8f, 0xbf, 0x97, 0xbf, 0x9f, 0xbf, 0x9f, 0xbf, 0x97, 0xbf, 0x8f, 0xdf, 0x87, 0xff, 0x8f, 0xff, 0xa7, 0xdf, 0xa7, 0xdd, 0x3c, 0x4f, 0x01, 0x8f, 0x12, 0xef, 0x1a, 0xef, 0x1a, 0xef, 0x1a, 0xef, 0x1a, 0xef, 0x1a, 0x00, 0x00, 0x00, 0x00, 0xef, 0x1a, 0xef, 0x1a, 0xef, 0x1a, 0xef, 0x1a, 0xef, 0x1a, 0xef, 0x1a, 0xef, 0x1a, 0xce, 0x09, 0x17, 0x02, 0x1e, 0x55, 0x5f, 0xaf, 0xff, 0xcf, 0xff, 0xc7, 0xff, 0xbf, 0xff, 0xb7, 0xff, 0xb7, 0xff, 0xb7, 0xff, 0xc7, 0xff, 0xcf, 0xbf, 0xb7, 0xbe, 0x6d, 0xba, 0x02, 0xae, 0x09, 0xcf, 0x12, 0xef, 0x1a, 0xef, 0x1a, 0xef, 0x1a, 0xef, 0x1a, 0xef, 0x1a, 0xef, 0x1a, 0x00, 0x00, 0x00, 0x00, 0xef, 0x1a, 0xef, 0x1a, 0xef, 0x1a, 0xef, 0x1a, 0xef, 0x1a, 0xef, 0x1a, 0xef, 0x1a, 0xef, 0x1a, 0x8f, 0x12, 0xae, 0x09, 0xd2, 0x01, 0x9b, 0x23, 0x1d, 0x5d, 0x1e, 0x86, 0xbf, 0x9e, 0xdf, 0xa6, 0x5f, 0x8e, 0x7e, 0x6d, 0xfc, 0x2b, 0x16, 0x02, 0x8f, 0x09, 0x4f, 0x12, 0xef, 0x1a, 0xef, 0x1a, 0xef, 0x1a, 0xef, 0x1a, 0xef, 0x1a, 0xef, 0x1a, 0xef, 0x1a, 0xef, 0x1a, 0x00, 0x00, 0x00, 0x00, 0xef, 0x1a, 0xef, 0x1a, 0xef, 0x1a, 0xef, 0x1a, 0xef, 0x1a, 0xef, 0x1a, 0xef, 0x1a, 0xef, 0x1a, 0xef, 0x1a, 0xef, 0x1a, 0xcf, 0x12, 0x4e, 0x12, 0xce, 0x09, 0xaf, 0x09, 0x8f, 0x01, 0x8f, 0x01, 0xaf, 0x09, 0xce, 0x09, 0x2e, 0x12, 0xaf, 0x12, 0xef, 0x1a, 0xef, 0x1a, 0xef, 0x1a, 0xef, 0x1a, 0xef, 0x1a, 0xef, 0x1a, 0xef, 0x1a, 0xef, 0x1a, 0xef, 0x1a, 0xef, 0x1a, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }; uint8 compressed_16x1x24[] = { 0x0c, 0x84, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }; uint8 decompressed_16x1x24[] = { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }; uint8 compressed_32x32x24[] = { 0x84, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xc0, 0xc0, 0xc0, 0xc0, 0xc0, 0xc0, 0x38, 0x8a, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x00, 0xc0, 0xc0, 0xc0, 0x1a, 0x87, 0xc0, 0xc0, 0xc0, 0xc0, 0xc0, 0xc0, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xc0, 0xc0, 0xc0, 0x80, 0x80, 0x00, 0x80, 0x80, 0x80, 0x1a, 0x87, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x80, 0x80, 0x80, 0x80, 0x80, 0x00, 0xc0, 0xc0, 0xc0, 0x1d, 0x84, 0xff, 0xff, 0xff, 0x80, 0x80, 0x80, 0x80, 0x80, 0x00, 0xc0, 0xc0, 0xc0, 0x18, 0x88, 0xc0, 0xc0, 0xc0, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xc0, 0xc0, 0xc0, 0x80, 0x80, 0x00, 0x80, 0x80, 0x80, 0x17, 0x8a, 0xff, 0xff, 0xff, 0xc0, 0xc0, 0xc0, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x80, 0x80, 0x80, 0x80, 0x80, 0x00, 0xc0, 0xc0, 0xc0, 0x1d, 0x83, 0xc0, 0xc0, 0xc0, 0x80, 0x80, 0x00, 0x80, 0x80, 0x00, 0x18, 0x89, 0xc0, 0xc0, 0xc0, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x80, 0x80, 0x80, 0x80, 0x80, 0x00, 0xc0, 0xc0, 0xc0, 0x16, 0x8a, 0xff, 0xff, 0xff, 0xc0, 0xc0, 0xc0, 0xc0, 0xc0, 0xc0, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xc0, 0xc0, 0xc0, 0x80, 0x80, 0x00, 0x80, 0x80, 0x00, 0x17, 0x8a, 0xff, 0xff, 0xff, 0xc0, 0xc0, 0xc0, 0xc0, 0xc0, 0xc0, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x80, 0x80, 0x80, 0x80, 0x80, 0x00, 0xc0, 0xc0, 0xc0, 0x17, 0x97, 0xff, 0xff, 0xff, 0x80, 0x80, 0x80, 0xc0, 0xc0, 0xc0, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xc0, 0xc0, 0xc0, 0x80, 0x80, 0x00, 0x80, 0x80, 0x80, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xc0, 0xc0, 0xc0, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0xc0, 0xc0, 0xc0, 0xc0, 0xc0, 0xc0, 0xc0, 0xc0, 0xc0, 0xc0, 0xc0, 0xc0, 0x80, 0x80, 0x80, 0xc0, 0xc0, 0xc0, 0x6b, 0xff, 0xff, 0xff, 0x01, 0x95, 0x80, 0x80, 0x80, 0xc0, 0xc0, 0xc0, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x80, 0x80, 0x00, 0x80, 0x80, 0x00, 0xc0, 0xc0, 0xc0, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xc0, 0xc0, 0xc0, 0x80, 0x80, 0x00, 0xc0, 0xc0, 0xc0, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x6c, 0xff, 0xff, 0xff, 0x86, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x00, 0x80, 0x80, 0x00, 0xc0, 0xc0, 0xc0, 0x6d, 0xff, 0xff, 0xff, 0x01, 0x81, 0xc0, 0xc0, 0xc0, 0x6d, 0xff, 0xff, 0xff, 0x88, 0xc0, 0xc0, 0xc0, 0x80, 0x80, 0x80, 0x80, 0x80, 0x00, 0x80, 0x80, 0x00, 0x80, 0x80, 0x00, 0x80, 0x80, 0x80, 0xc0, 0xc0, 0xc0, 0xc0, 0xc0, 0xc0, 0x09, 0x82, 0xc0, 0xc0, 0xc0, 0x80, 0x80, 0x80, 0x6f, 0xff, 0xff, 0xff, 0x02, 0x86, 0xc0, 0xc0, 0xc0, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xc0, 0xc0, 0xc0, 0xc0, 0xc0, 0xc0, 0xc0, 0xc0, 0xc0, 0x07, 0x82, 0x80, 0x80, 0x80, 0x80, 0x80, 0x00, 0x0f, 0x91, 0x80, 0x80, 0x80, 0x80, 0x80, 0x00, 0xc0, 0xc0, 0xc0, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xc0, 0xc0, 0xc0, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0xc0, 0xc0, 0xc0, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xc0, 0xc0, 0xc0, 0x80, 0x80, 0x00, 0x80, 0x80, 0x80, 0x0f, 0x81, 0xc0, 0xc0, 0xc0, 0x06, 0x8a, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x80, 0x80, 0x80, 0x80, 0x80, 0x00, 0xc0, 0xc0, 0xc0, 0xff, 0xff, 0xff, 0xc0, 0xc0, 0xc0, 0x80, 0x80, 0x00, 0x80, 0x80, 0x00, 0xc0, 0xc0, 0xc0, 0x0d, 0x85, 0x80, 0x80, 0x80, 0xc0, 0xc0, 0xc0, 0xc0, 0xc0, 0xc0, 0x80, 0x80, 0x00, 0x80, 0x80, 0x80, 0x06, 0x87, 0xc0, 0xc0, 0xc0, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0xc0, 0xc0, 0xc0, 0x80, 0x80, 0x00, 0x80, 0x80, 0x00, 0xc0, 0xc0, 0xc0, 0x6e, 0xff, 0xff, 0xff, 0x91, 0x80, 0x80, 0x00, 0x80, 0x80, 0x80, 0xff, 0xff, 0xff, 0x80, 0x80, 0x00, 0x80, 0x80, 0x00, 0xc0, 0xc0, 0xc0, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xc0, 0xc0, 0xc0, 0x80, 0x80, 0x00, 0x80, 0x80, 0x00, 0xc0, 0xc0, 0xc0, 0x6e, 0xff, 0xff, 0xff, 0x85, 0xc0, 0xc0, 0xc0, 0x80, 0x80, 0x00, 0xc0, 0xc0, 0xc0, 0xff, 0xff, 0xff, 0x80, 0x80, 0x80, 0x09, 0x83, 0x80, 0x80, 0x00, 0x80, 0x80, 0x00, 0xc0, 0xc0, 0xc0, 0x6f, 0xff, 0xff, 0xff, 0x01, 0x84, 0x80, 0x80, 0x80, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xc0, 0xc0, 0xc0, 0x08, 0x83, 0x80, 0x80, 0x80, 0x80, 0x80, 0x00, 0xc0, 0xc0, 0xc0, 0x70, 0xff, 0xff, 0xff, 0x06, 0x81, 0x80, 0x80, 0x80, 0x06, 0x82, 0x80, 0x80, 0x00, 0xc0, 0xc0, 0xc0, 0x71, 0xff, 0xff, 0xff, 0x13, 0x83, 0xc0, 0xc0, 0xc0, 0x80, 0x80, 0x00, 0xc0, 0xc0, 0xc0, 0x0e, 0x83, 0xff, 0xff, 0xff, 0x80, 0x80, 0x80, 0x80, 0x80, 0x00, 0x06, 0x8a, 0x80, 0x80, 0x80, 0xc0, 0xc0, 0xc0, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x80, 0x80, 0x80, 0x80, 0x80, 0x00, 0xc0, 0xc0, 0xc0, 0x16, 0x8a, 0xc0, 0xc0, 0xc0, 0x80, 0x80, 0x80, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x6a, 0xff, 0xff, 0xff, 0x0c, 0x89, 0xff, 0xff, 0xff, 0xc0, 0xc0, 0xc0, 0x80, 0x80, 0x80, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xc0, 0xc0, 0xc0, 0x18, 0x89, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xc0, 0xc0, 0xc0, 0xc0, 0xc0, 0xc0, 0xc0, 0xc0, 0xc0, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x80, 0x80, 0x80, 0xc0, 0xc0, 0xc0, 0x0a, 0x86, 0xc0, 0xc0, 0xc0, 0xc0, 0xc0, 0xc0, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x6b, 0xff, 0xff, 0xff, 0x01, 0x82, 0xc0, 0xc0, 0xc0, 0xc0, 0xc0, 0xc0, 0x6d, 0xff, 0xff, 0xff, 0x04, 0x81, 0xc0, 0xc0, 0xc0, 0x7c, 0xff, 0xff, 0xff, 0x83, 0xc0, 0xc0, 0xc0, 0xc0, 0xc0, 0xc0, 0x80, 0x80, 0x80, 0x60, 0x0e, 0xff, 0xff, 0xff, 0x84, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff }; uint8 decompressed_32x32x24[] = { 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xc0, 0xc0, 0xc0, 0xc0, 0xc0, 0xc0, 0x80, 0x80, 0x80, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xc0, 0xc0, 0xc0, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x80, 0x80, 0x80, 0xc0, 0xc0, 0xc0, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xc0, 0xc0, 0xc0, 0xc0, 0xc0, 0xc0, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xc0, 0xc0, 0xc0, 0xc0, 0xc0, 0xc0, 0xc0, 0xc0, 0xc0, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x80, 0x80, 0x80, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x80, 0x80, 0x80, 0x80, 0x80, 0x00, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xc0, 0xc0, 0xc0, 0xc0, 0xc0, 0xc0, 0xc0, 0xc0, 0xc0, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x80, 0x80, 0x80, 0xc0, 0xc0, 0xc0, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x80, 0x80, 0x80, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x80, 0x80, 0x80, 0x80, 0x80, 0x00, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xc0, 0xc0, 0xc0, 0x80, 0x80, 0x80, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xc0, 0xc0, 0xc0, 0x80, 0x80, 0x80, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xc0, 0xc0, 0xc0, 0x80, 0x80, 0x80, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x80, 0x80, 0x80, 0x80, 0x80, 0x00, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xc0, 0xc0, 0xc0, 0x80, 0x80, 0x80, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xc0, 0xc0, 0xc0, 0x80, 0x80, 0x80, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x80, 0x80, 0x80, 0x80, 0x80, 0x00, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x80, 0x80, 0x80, 0xc0, 0xc0, 0xc0, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x80, 0x80, 0x80, 0x80, 0x80, 0x00, 0xc0, 0xc0, 0xc0, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xc0, 0xc0, 0xc0, 0x80, 0x80, 0x80, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xc0, 0xc0, 0xc0, 0x80, 0x80, 0x00, 0x80, 0x80, 0x80, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x80, 0x80, 0x00, 0xc0, 0xc0, 0xc0, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xc0, 0xc0, 0xc0, 0x80, 0x80, 0x00, 0xc0, 0xc0, 0xc0, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xc0, 0xc0, 0xc0, 0x80, 0x80, 0x80, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xc0, 0xc0, 0xc0, 0x80, 0x80, 0x00, 0x80, 0x80, 0x80, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x80, 0x80, 0x00, 0xc0, 0xc0, 0xc0, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xc0, 0xc0, 0xc0, 0x80, 0x80, 0x80, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xc0, 0xc0, 0xc0, 0x80, 0x80, 0x00, 0xc0, 0xc0, 0xc0, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x80, 0x80, 0x80, 0x80, 0x80, 0x00, 0xc0, 0xc0, 0xc0, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xc0, 0xc0, 0xc0, 0x80, 0x80, 0x00, 0xc0, 0xc0, 0xc0, 0xff, 0xff, 0xff, 0x80, 0x80, 0x80, 0x80, 0x80, 0x00, 0xc0, 0xc0, 0xc0, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x80, 0x80, 0x00, 0x80, 0x80, 0x00, 0xc0, 0xc0, 0xc0, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x80, 0x80, 0x00, 0x80, 0x80, 0x80, 0xff, 0xff, 0xff, 0x80, 0x80, 0x00, 0x80, 0x80, 0x00, 0xc0, 0xc0, 0xc0, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xc0, 0xc0, 0xc0, 0x80, 0x80, 0x00, 0x80, 0x80, 0x00, 0xc0, 0xc0, 0xc0, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x80, 0x80, 0x80, 0xc0, 0xc0, 0xc0, 0xc0, 0xc0, 0xc0, 0x80, 0x80, 0x00, 0x80, 0x80, 0x80, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xc0, 0xc0, 0xc0, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0xc0, 0xc0, 0xc0, 0x80, 0x80, 0x00, 0x80, 0x80, 0x00, 0xc0, 0xc0, 0xc0, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xc0, 0xc0, 0xc0, 0x80, 0x80, 0x00, 0xc0, 0xc0, 0xc0, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x80, 0x80, 0x80, 0x80, 0x80, 0x00, 0xc0, 0xc0, 0xc0, 0xff, 0xff, 0xff, 0xc0, 0xc0, 0xc0, 0x80, 0x80, 0x00, 0x80, 0x80, 0x00, 0xc0, 0xc0, 0xc0, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x80, 0x80, 0x80, 0x80, 0x80, 0x00, 0xc0, 0xc0, 0xc0, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xc0, 0xc0, 0xc0, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0xc0, 0xc0, 0xc0, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xc0, 0xc0, 0xc0, 0x80, 0x80, 0x00, 0x80, 0x80, 0x80, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x80, 0x80, 0x00, 0x80, 0x80, 0x00, 0xc0, 0xc0, 0xc0, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xc0, 0xc0, 0xc0, 0xc0, 0xc0, 0xc0, 0xc0, 0xc0, 0xc0, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x80, 0x80, 0x80, 0x80, 0x80, 0x00, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xc0, 0xc0, 0xc0, 0x80, 0x80, 0x80, 0x80, 0x80, 0x00, 0x80, 0x80, 0x00, 0x80, 0x80, 0x00, 0x80, 0x80, 0x80, 0xc0, 0xc0, 0xc0, 0xc0, 0xc0, 0xc0, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xc0, 0xc0, 0xc0, 0x80, 0x80, 0x80, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x00, 0x80, 0x80, 0x00, 0xc0, 0xc0, 0xc0, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x80, 0x80, 0x80, 0xc0, 0xc0, 0xc0, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xc0, 0xc0, 0xc0, 0x80, 0x80, 0x80, 0xc0, 0xc0, 0xc0, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x80, 0x80, 0x00, 0x80, 0x80, 0x00, 0xc0, 0xc0, 0xc0, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xc0, 0xc0, 0xc0, 0x80, 0x80, 0x00, 0xc0, 0xc0, 0xc0, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x80, 0x80, 0x80, 0xc0, 0xc0, 0xc0, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xc0, 0xc0, 0xc0, 0x80, 0x80, 0x00, 0x80, 0x80, 0x80, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xc0, 0xc0, 0xc0, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0xc0, 0xc0, 0xc0, 0xc0, 0xc0, 0xc0, 0xc0, 0xc0, 0xc0, 0xc0, 0xc0, 0xc0, 0x80, 0x80, 0x80, 0xc0, 0xc0, 0xc0, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xc0, 0xc0, 0xc0, 0xc0, 0xc0, 0xc0, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x80, 0x80, 0x80, 0x80, 0x80, 0x00, 0xc0, 0xc0, 0xc0, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xc0, 0xc0, 0xc0, 0xc0, 0xc0, 0xc0, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xc0, 0xc0, 0xc0, 0x80, 0x80, 0x00, 0x80, 0x80, 0x00, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xc0, 0xc0, 0xc0, 0xc0, 0xc0, 0xc0, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x80, 0x80, 0x80, 0x80, 0x80, 0x00, 0xc0, 0xc0, 0xc0, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xc0, 0xc0, 0xc0, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xc0, 0xc0, 0xc0, 0x80, 0x80, 0x00, 0x80, 0x80, 0x00, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xc0, 0xc0, 0xc0, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x80, 0x80, 0x80, 0x80, 0x80, 0x00, 0xc0, 0xc0, 0xc0, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xc0, 0xc0, 0xc0, 0xc0, 0xc0, 0xc0, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xc0, 0xc0, 0xc0, 0x80, 0x80, 0x00, 0x80, 0x80, 0x80, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xc0, 0xc0, 0xc0, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x80, 0x80, 0x80, 0x80, 0x80, 0x00, 0xc0, 0xc0, 0xc0, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xc0, 0xc0, 0xc0, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x80, 0x80, 0x80, 0x80, 0x80, 0x00, 0xc0, 0xc0, 0xc0, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xc0, 0xc0, 0xc0, 0xc0, 0xc0, 0xc0, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xc0, 0xc0, 0xc0, 0x80, 0x80, 0x00, 0x80, 0x80, 0x80, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x00, 0xc0, 0xc0, 0xc0, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xc0, 0xc0, 0xc0, 0xc0, 0xc0, 0xc0, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff }; uint8 compressed_16x1x32[] = { 0x10, 0x01, 0x01, 0x01, 0x01 }; uint8 decompressed_16x1x32[] = { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }; uint8 compressed_32x32x32[] = { 0x10, 0x02, 0x02, 0x0a, 0xbb, 0x22, 0x8e, 0xf6, 0xb9, 0x91, 0x91, 0xa9, 0xf5, 0xaa, 0x3c, 0x00, 0x08, 0xf9, 0x5e, 0xd1, 0x59, 0x8f, 0xf7, 0xb8, 0x90, 0x90, 0xa8, 0xf4, 0xab, 0x59, 0xa3, 0x8c, 0x00, 0x06, 0x67, 0x02, 0xe7, 0x6d, 0xd0, 0x36, 0x00, 0x67, 0x1c, 0xa2, 0x8d, 0xb9, 0x20, 0x00, 0x05, 0x5c, 0x2c, 0x9b, 0xe6, 0x0e, 0x00, 0x46, 0xb8, 0x77, 0x66, 0x00, 0x04, 0x4f, 0x3c, 0x8b, 0x98, 0x00, 0x45, 0x56, 0x8b, 0x84, 0x00, 0x03, 0x4d, 0x20, 0x9b, 0x5e, 0x00, 0x04, 0x44, 0x24, 0xa5, 0x62, 0x00, 0x03, 0x3f, 0xd1, 0x5e, 0x00, 0x04, 0x43, 0x20, 0xb5, 0x1c, 0x00, 0x5f, 0x00, 0x00, 0xdc, 0xb0, 0x00, 0x06, 0x33, 0x52, 0xcf, 0x00, 0x4f, 0x00, 0x30, 0xfd, 0x00, 0x08, 0x50, 0xb2, 0x86, 0x00, 0x00, 0x00, 0x4f, 0x00, 0xb4, 0x20, 0x00, 0x09, 0x40, 0xd4, 0x00, 0x00, 0x00, 0x3f, 0x04, 0xae, 0x00, 0x0a, 0x40, 0x8a, 0x32, 0x00, 0x00, 0x3f, 0x3e, 0x5e, 0x00, 0x0a, 0x40, 0x1a, 0x74, 0x00, 0x00, 0x3f, 0x54, 0x0e, 0x00, 0x0b, 0x30, 0x64, 0x00, 0x00, 0x2f, 0x44, 0x00, 0x0c, 0x30, 0x44, 0x00, 0x00, 0x2f, 0x1c, 0x00, 0x0c, 0x30, 0x1e, 0x00, 0x00, 0x2f, 0x03, 0x00, 0x0c, 0x30, 0x03, 0x00, 0x00, 0x2f, 0x27, 0x00, 0x0c, 0x30, 0x29, 0x00, 0x00, 0x2f, 0x49, 0x00, 0x0c, 0x30, 0x4d, 0x00, 0x00, 0x3f, 0x53, 0x1d, 0x00, 0x0b, 0x30, 0x69, 0x00, 0x00, 0x3f, 0x2b, 0x79, 0x00, 0x0a, 0x40, 0x35, 0x6b, 0x00, 0x00, 0x3f, 0x00, 0xb9, 0x00, 0x0a, 0x40, 0xa5, 0x19, 0x00, 0x00, 0x4f, 0x00, 0x9d, 0x4f, 0x00, 0x08, 0x50, 0x0b, 0xd5, 0x00, 0x00, 0x00, 0x5f, 0x00, 0x0d, 0xf0, 0x01, 0x00, 0x07, 0x50, 0xe9, 0x4b, 0x00, 0x00, 0x00, 0x5f, 0x00, 0x00, 0x9d, 0xf6, 0x00, 0x06, 0x33, 0xa1, 0xfa, 0x00, 0x03, 0x3f, 0xf1, 0xbf, 0x00, 0x04, 0x43, 0x67, 0xc6, 0x01, 0x00, 0x04, 0x3d, 0xca, 0xc1, 0x00, 0x04, 0x44, 0x6f, 0x9c, 0x21, 0x00, 0x04, 0x4f, 0x07, 0xc4, 0xf4, 0x00, 0x45, 0xbd, 0x8e, 0x31, 0x00, 0x06, 0x4b, 0xf1, 0xaa, 0x5b, 0x00, 0x56, 0x33, 0xd8, 0xc0, 0x1b, 0x00, 0x07, 0x65, 0xa7, 0x6c, 0xae, 0x9d, 0x29, 0x00, 0x68, 0x15, 0x79, 0xde, 0x60, 0xd5, 0x00, 0x08, 0xf9, 0x0d, 0xab, 0xa0, 0x54, 0x7a, 0xc2, 0xec, 0xf0, 0xd0, 0x8e, 0x56, 0x7c, 0xdb, 0x29, 0x00, 0x02, 0x02, 0x19, 0x3a, 0xb9, 0x36, 0x2a, 0x1e, 0x14, 0x10, 0x10, 0x14, 0x1c, 0x26, 0x34, 0x3a, 0x20, 0x00, 0x00, 0x08, 0xf9, 0x09, 0x21, 0x2f, 0x16, 0x98, 0xf6, 0xd1, 0xcd, 0xf9, 0xb4, 0x38, 0x2f, 0x27, 0x0f, 0x00, 0x07, 0xf0, 0x1f, 0x2d, 0x8c, 0xb1, 0xaf, 0xd2, 0x6a, 0x26, 0x20, 0x54, 0xb2, 0xcd, 0x9b, 0xc2, 0x21, 0x37, 0x25, 0x03, 0x00, 0x05, 0xf0, 0x05, 0x27, 0x3e, 0xcb, 0xae, 0x33, 0x85, 0x6f, 0x4b, 0x33, 0x31, 0x45, 0x65, 0x85, 0x53, 0x66, 0x70, 0xbd, 0x6a, 0x2b, 0x0b, 0x00, 0x04, 0xf0, 0x05, 0x29, 0x56, 0xba, 0x4b, 0x75, 0x39, 0x13, 0x17, 0x23, 0x21, 0x21, 0x23, 0x1b, 0x11, 0x85, 0x21, 0x6d, 0x75, 0x8c, 0x98, 0x29, 0x0f, 0x00, 0x03, 0xf0, 0x03, 0x29, 0x62, 0x6e, 0x79, 0x31, 0x11, 0x11, 0x1b, 0x21, 0x1b, 0x25, 0x29, 0x1b, 0x21, 0xa4, 0x1d, 0x1d, 0x0b, 0x17, 0x79, 0x20, 0x98, 0x25, 0x0b, 0x00, 0x03, 0xf0, 0x21, 0x2a, 0x30, 0x8b, 0x19, 0x1b, 0x21, 0x1f, 0x19, 0x1f, 0x39, 0x49, 0x47, 0x49, 0x2d, 0xb3, 0x19, 0x1f, 0x21, 0x1f, 0x11, 0x7b, 0x1d, 0x60, 0x23, 0x03, 0x00, 0xf0, 0x00, 0x00, 0x19, 0x11, 0x2c, 0x87, 0x1d, 0x25, 0x2b, 0x29, 0x2b, 0x31, 0x2d, 0x25, 0xa2, 0xe3, 0xdc, 0x8c, 0x2f, 0x3f, 0x2b, 0x29, 0x29, 0x25, 0x13, 0x71, 0x19, 0x1c, 0x21, 0x00, 0xf0, 0x00, 0x05, 0x1b, 0x42, 0x5d, 0x11, 0x15, 0x29, 0x2b, 0x2b, 0x27, 0x27, 0x2f, 0x4e, 0x46, 0xf0, 0x0e, 0x5c, 0xc8, 0x21, 0x31, 0x29, 0x2d, 0x29, 0x1b, 0x09, 0x47, 0x1c, 0x11, 0x0f, 0x00, 0x20, 0x00, 0x00, 0xf0, 0x00, 0x13, 0x00, 0x2b, 0x00, 0x00, 0x0f, 0x17, 0x1d, 0x1f, 0x25, 0x23, 0x21, 0x08, 0x12, 0xf0, 0x12, 0x12, 0x50, 0xf2, 0x13, 0x25, 0x1d, 0x17, 0x0f, 0x00, 0x00, 0x3f, 0x16, 0x17, 0x00, 0x20, 0x00, 0x00, 0xf3, 0x00, 0x13, 0x0e, 0x15, 0x00, 0x00, 0x03, 0x0f, 0x15, 0x1b, 0x1d, 0x1f, 0x1b, 0x1f, 0x16, 0xe0, 0x60, 0xe7, 0x05, 0x17, 0x0f, 0x03, 0x00, 0x00, 0x00, 0x03, 0x0f, 0x05, 0x00, 0x00, 0x43, 0x07, 0x09, 0x0b, 0x00, 0xf0, 0x03, 0x0d, 0x11, 0x13, 0x15, 0x11, 0xaf, 0x9b, 0x1a, 0x1a, 0x1a, 0x18, 0x70, 0xbd, 0x0e, 0x23, 0x03, 0x00, 0x50, 0x11, 0x00, 0x0b, 0x00, 0x00, 0x45, 0x09, 0x00, 0x03, 0x00, 0x83, 0x01, 0x05, 0x09, 0x0f, 0x0b, 0xf2, 0xab, 0x18, 0x45, 0x7a, 0xa3, 0x1c, 0x00, 0x30, 0x0b, 0x00, 0x00, 0x24, 0x05, 0x00, 0xb3, 0x84, 0x63, 0x05, 0x07, 0x09, 0x09, 0x07, 0x09, 0x0b, 0xdc, 0x18, 0x54, 0x1a, 0x86, 0x91, 0x1e, 0x00, 0x30, 0x07, 0x00, 0x00, 0x24, 0x03, 0x00, 0x58, 0xbd, 0x60, 0x02, 0x04, 0x06, 0x73, 0x04, 0x00, 0x00, 0x72, 0x93, 0x18, 0x00, 0x30, 0x03, 0x00, 0x00, 0x8f, 0x00, 0x30, 0xe4, 0xac, 0x66, 0x20, 0x06, 0x00, 0x90, 0x05, 0x1e, 0x64, 0xae, 0xf2, 0x7c, 0x02, 0x00, 0x00, 0x9d, 0x06, 0x60, 0x6c, 0x56, 0x7e, 0x98, 0xdf, 0x4b, 0x00, 0xa0, 0x5d, 0xe3, 0x84, 0x7e, 0x54, 0x5a, 0x7c, 0x04, 0x00, 0x00, 0xf0, 0x08, 0x0a, 0x16, 0x12, 0x0a, 0x16, 0x3b, 0xe2, 0x86, 0x76, 0x6c, 0x62, 0x5a, 0x54, 0x50, 0x24, 0xb1, 0x00, 0xb0, 0x53, 0xf9, 0x10, 0x14, 0x0c, 0x10, 0x14, 0x0a, 0x08, 0x00, 0x00, 0xf0, 0x08, 0x0d, 0x18, 0x16, 0x16, 0x14, 0x12, 0x14, 0x0c, 0x10, 0x0c, 0x0e, 0x0a, 0x0c, 0xfb, 0x23, 0xb2, 0x00, 0xc0, 0x53, 0xf8, 0x02, 0x14, 0x14, 0x16, 0x18, 0x1e, 0x07, 0x0c, 0x00, 0x00, 0xf0, 0x06, 0x59, 0x00, 0x20, 0x12, 0x14, 0x18, 0x14, 0x14, 0x0e, 0x0e, 0x0c, 0x10, 0xb0, 0xac, 0x13, 0x00, 0xd0, 0x53, 0xfa, 0x00, 0x14, 0x16, 0x16, 0x12, 0x1c, 0x1c, 0x75, 0x0e, 0x00, 0x00, 0xf3, 0x00, 0x0d, 0x55, 0x34, 0x18, 0x18, 0x16, 0x16, 0x14, 0x12, 0x12, 0x10, 0x12, 0x26, 0x00, 0xe0, 0x53, 0xfd, 0x02, 0x16, 0x18, 0x16, 0x16, 0x18, 0x2c, 0x23, 0x67, 0x02, 0x00, 0x00, 0xf0, 0x00, 0x12, 0xc7, 0x22, 0x26, 0x18, 0x1a, 0x16, 0x16, 0x18, 0x16, 0x16, 0x14, 0x03, 0x00, 0xf0, 0x00, 0x00, 0x4f, 0xf5, 0x00, 0x16, 0x16, 0x16, 0x1a, 0x18, 0x24, 0x3c, 0xa9, 0x14, 0x00, 0x20, 0x00, 0x00, 0xf0, 0x00, 0x02, 0x39, 0x99, 0x4a, 0x28, 0x1e, 0x22, 0x24, 0x20, 0x1c, 0x1c, 0x1a, 0x63, 0x33, 0xf0, 0x00, 0x57, 0xe7, 0x08, 0x1c, 0x1e, 0x24, 0x24, 0x1e, 0x28, 0x48, 0x4d, 0xb1, 0x08, 0x00, 0x20, 0x00, 0x00, 0xf0, 0x00, 0x00, 0x12, 0xe9, 0x59, 0x58, 0x30, 0x2a, 0x2a, 0x2c, 0x2c, 0x28, 0x26, 0x06, 0xf9, 0xe3, 0xf6, 0xd3, 0x12, 0x28, 0x2c, 0x2e, 0x2a, 0x28, 0x30, 0x52, 0x07, 0xc8, 0x1e, 0x00, 0x03, 0xf0, 0x1c, 0xd8, 0x43, 0x58, 0x2a, 0x20, 0x24, 0x26, 0x26, 0x28, 0x26, 0x24, 0x00, 0x26, 0x28, 0xa4, 0x26, 0x28, 0x22, 0x20, 0x2a, 0x4e, 0x08, 0xb8, 0x0c, 0x00, 0x04, 0xf0, 0x1c, 0xb8, 0x5b, 0x5a, 0x36, 0x24, 0x26, 0x28, 0x26, 0x28, 0x2a, 0x2a, 0x28, 0x26, 0x28, 0x94, 0x24, 0x26, 0x34, 0x58, 0x0f, 0xa0, 0x17, 0x04, 0x00, 0x05, 0xf0, 0x1e, 0xc8, 0x91, 0x5a, 0x58, 0x3a, 0x2a, 0x2a, 0x28, 0x24, 0x24, 0x28, 0x2a, 0x2c, 0x36, 0x75, 0x54, 0x6c, 0x5b, 0x8e, 0x13, 0x06, 0x00, 0x06, 0xf0, 0x1c, 0xff, 0xa8, 0x49, 0x48, 0x6c, 0x5e, 0x4e, 0x4a, 0x4a, 0x4e, 0x5a, 0x6a, 0x5a, 0x1d, 0x56, 0xd2, 0xc6, 0x14, 0x04, 0x00, 0x07, 0xf0, 0x14, 0x3b, 0xc8, 0x80, 0xfb, 0x67, 0x17, 0x0e, 0x12, 0x0d, 0x53, 0xd7, 0x90, 0x9a, 0x77, 0x28, 0x18, 0x00, 0x08, 0xf9, 0x02, 0x14, 0x07, 0x95, 0xe6, 0xa6, 0x86, 0x80, 0x9a, 0xd4, 0xbd, 0x25, 0x1a, 0x04, 0x00, 0x02, 0x02, 0x19, 0xbe, 0xb9, 0xb6, 0x98, 0x76, 0x6a, 0x62, 0x62, 0x68, 0x74, 0x8e, 0xb0, 0xbe, 0x20, 0x00, 0x00, 0x08, 0xf9, 0x19, 0x51, 0x45, 0x48, 0xd0, 0xe5, 0xb5, 0xaf, 0xd7, 0xe6, 0x6c, 0x29, 0x5b, 0x23, 0x00, 0x07, 0xf0, 0x4b, 0x23, 0xd6, 0x9d, 0xe1, 0xb8, 0x7a, 0x52, 0x4c, 0x6e, 0xa4, 0xfb, 0x9d, 0xf3, 0x12, 0x37, 0x55, 0x07, 0x00, 0x05, 0xf0, 0x07, 0x5f, 0x92, 0xa3, 0xbc, 0x2c, 0x07, 0x0f, 0x11, 0x13, 0x13, 0x11, 0x0f, 0x09, 0x12, 0x66, 0x90, 0xb5, 0xc8, 0x65, 0x15, 0x00, 0x04, 0xa3, 0x0b, 0x65, 0xca, 0xea, 0x07, 0x2b, 0x1d, 0x0f, 0x05, 0x01, 0xa5, 0x05, 0x0d, 0x1b, 0x29, 0x27, 0xba, 0xe7, 0x4b, 0x1f, 0x00, 0x03, 0xf0, 0x03, 0x5f, 0xe6, 0x96, 0x5b, 0x27, 0x11, 0x15, 0x15, 0x11, 0x13, 0x11, 0x17, 0x13, 0x11, 0xa4, 0x15, 0x13, 0x13, 0x1d, 0x5d, 0x42, 0xe7, 0x43, 0x11, 0x00, 0x03, 0xf0, 0x53, 0xa6, 0x56, 0x75, 0x19, 0x17, 0x1f, 0x1d, 0x1d, 0x1f, 0x49, 0x79, 0x89, 0x71, 0x41, 0xb3, 0x1d, 0x1d, 0x1f, 0x1b, 0x11, 0x65, 0x00, 0xe2, 0x5d, 0x03, 0x00, 0xf0, 0x00, 0x00, 0x35, 0x44, 0x5c, 0x77, 0x1d, 0x23, 0x29, 0x27, 0x27, 0x27, 0x31, 0x5b, 0x0c, 0xe3, 0x32, 0x03, 0x67, 0x4f, 0x27, 0x27, 0x29, 0x25, 0x15, 0x65, 0x0a, 0x9a, 0x4f, 0x00, 0xf0, 0x00, 0x0b, 0x39, 0x72, 0x5f, 0x1b, 0x15, 0x27, 0x27, 0x29, 0x29, 0x29, 0x45, 0x12, 0x1e, 0xf0, 0x0e, 0x26, 0x42, 0x4f, 0x4b, 0x27, 0x27, 0x29, 0x19, 0x0f, 0x67, 0x3e, 0x06, 0x1f, 0x00, 0x20, 0x00, 0x00, 0xf0, 0x00, 0x23, 0x4a, 0x2b, 0x35, 0x13, 0x15, 0x1d, 0x23, 0x23, 0x29, 0x27, 0x21, 0x00, 0x12, 0xf0, 0x12, 0x12, 0x2a, 0x64, 0x45, 0x3f, 0x23, 0x1b, 0x15, 0x19, 0x1d, 0x4d, 0x54, 0x33, 0x00, 0x20, 0x00, 0x00, 0xf0, 0x01, 0x33, 0x1e, 0x4b, 0x17, 0x1f, 0x1d, 0x13, 0x1b, 0x1d, 0x21, 0x21, 0x1b, 0x11, 0x16, 0xf0, 0x16, 0x16, 0x18, 0x3a, 0x8e, 0x31, 0x2f, 0x13, 0x19, 0x1f, 0x17, 0x47, 0x01, 0x1b, 0x07, 0x20, 0x00, 0x00, 0xf0, 0x09, 0x09, 0x07, 0x29, 0x17, 0x1b, 0x21, 0x21, 0x17, 0x17, 0x15, 0x19, 0x02, 0x4f, 0x4d, 0xf0, 0x1a, 0x1a, 0x18, 0x18, 0x4a, 0xb2, 0x25, 0x31, 0x25, 0x1b, 0x19, 0x19, 0x1d, 0x18, 0x1f, 0x20, 0x00, 0x00, 0xf0, 0x13, 0x12, 0x13, 0x07, 0x0d, 0x17, 0x25, 0x3b, 0x45, 0x49, 0x45, 0x43, 0x45, 0x21, 0x9f, 0x23, 0x5d, 0x18, 0xc0, 0x54, 0xd4, 0x1f, 0x23, 0x17, 0x0f, 0x03, 0x1b, 0x16, 0x15, 0x00, 0x00, 0xf0, 0x1b, 0x16, 0x15, 0x00, 0x01, 0x13, 0x44, 0xe3, 0xa7, 0xaf, 0xb9, 0xbf, 0xc3, 0xc5, 0xc7, 0x23, 0x8e, 0x18, 0xc0, 0x1a, 0x62, 0xfd, 0x0b, 0x11, 0x00, 0x00, 0x13, 0x0a, 0x17, 0x00, 0x00, 0xb8, 0x05, 0x04, 0x02, 0x04, 0x0b, 0x13, 0xf8, 0x46, 0x02, 0x04, 0x06, 0xd0, 0x04, 0x00, 0x00, 0x54, 0xe7, 0x03, 0x0d, 0x04, 0x0c, 0x01, 0x03, 0x00, 0x00, 0x8f, 0x06, 0x4c, 0xde, 0xbc, 0x8c, 0x48, 0x08, 0x00, 0x90, 0x04, 0x42, 0x8a, 0xbc, 0xee, 0x88, 0x04, 0x00, 0x00, 0x9d, 0x0e, 0x4e, 0x50, 0x3e, 0x5e, 0x88, 0x89, 0x2f, 0x00, 0xa0, 0x3b, 0x89, 0x7e, 0x60, 0x3e, 0x40, 0x62, 0x18, 0x00, 0x00, 0xf0, 0x1a, 0x0c, 0x0c, 0x08, 0x02, 0x12, 0x1b, 0xa7, 0xdf, 0xe5, 0xeb, 0xef, 0xf1, 0xf5, 0xf7, 0x24, 0x65, 0x00, 0xb0, 0x31, 0x91, 0x16, 0x10, 0x04, 0x06, 0x08, 0x08, 0x1e, 0x00, 0x00, 0x93, 0x0e, 0x09, 0x10, 0x0c, 0x0c, 0x0a, 0x08, 0x08, 0x04, 0x53, 0x00, 0x02, 0x94, 0x66, 0x00, 0xc0, 0x31, 0x9f, 0x01, 0x0a, 0x0a, 0x0c, 0x0e, 0x16, 0x07, 0x0a, 0x00, 0x00, 0xf0, 0x06, 0x45, 0x03, 0x16, 0x08, 0x08, 0x0a, 0x08, 0x06, 0x02, 0x02, 0x02, 0x06, 0x66, 0x64, 0x13, 0x00, 0x43, 0x33, 0xa3, 0x03, 0x08, 0x60, 0x12, 0x12, 0x59, 0x14, 0x00, 0x00, 0xf3, 0x00, 0x21, 0x41, 0x28, 0x0c, 0x0c, 0x0c, 0x0a, 0x08, 0x08, 0x06, 0x04, 0x02, 0x12, 0x00, 0xe0, 0x33, 0x9d, 0x01, 0x08, 0x0c, 0x0c, 0x0c, 0x0e, 0x20, 0x19, 0x55, 0x02, 0x00, 0x00, 0xf0, 0x00, 0x0a, 0x9b, 0x1c, 0x1e, 0x10, 0x0e, 0x0a, 0x0a, 0x0a, 0x08, 0x08, 0x0a, 0x05, 0x00, 0xf0, 0x00, 0x00, 0x31, 0x9b, 0x05, 0x0a, 0x0a, 0x0a, 0x10, 0x0e, 0x1a, 0x2e, 0x7f, 0x09, 0x00, 0x20, 0x00, 0x00, 0xf0, 0x00, 0x04, 0x39, 0x71, 0x36, 0x18, 0x12, 0x14, 0x14, 0x10, 0x10, 0x0e, 0x0a, 0x41, 0x21, 0xf0, 0x00, 0x37, 0x97, 0x00, 0x10, 0x0e, 0x14, 0x14, 0x10, 0x18, 0x34, 0x37, 0x89, 0x0a, 0x00, 0x20, 0x00, 0x00, 0xf0, 0x00, 0x00, 0x0a, 0xb7, 0x3b, 0x42, 0x1c, 0x16, 0x16, 0x16, 0x14, 0x12, 0x10, 0x03, 0xa7, 0xe3, 0xb1, 0x8f, 0x04, 0x12, 0x14, 0x18, 0x16, 0x16, 0x1c, 0x3c, 0x01, 0xe3, 0x04, 0x00, 0x03, 0xf0, 0x0a, 0xdd, 0x29, 0x42, 0x1c, 0x12, 0x14, 0x14, 0x14, 0x16, 0x14, 0x12, 0x05, 0x14, 0x16, 0xa4, 0x14, 0x16, 0x12, 0x12, 0x1c, 0x3a, 0x0e, 0xef, 0x09, 0x00, 0x04, 0xf0, 0x06, 0xf5, 0x35, 0x44, 0x28, 0x18, 0x18, 0x18, 0x16, 0x16, 0x1a, 0x1a, 0x16, 0x16, 0x18, 0x85, 0x16, 0x1a, 0x24, 0x40, 0x01, 0xfd, 0x25, 0x00, 0x05, 0xf0, 0x0c, 0xed, 0x5d, 0x44, 0x42, 0x2a, 0x20, 0x1c, 0x1c, 0x16, 0x16, 0x1c, 0x1c, 0x20, 0x26, 0x75, 0x3e, 0x52, 0x37, 0xf4, 0x1d, 0x08, 0x00, 0x06, 0xf0, 0x10, 0xcb, 0xef, 0x2b, 0x38, 0x4e, 0x46, 0x38, 0x36, 0x36, 0x38, 0x44, 0x4c, 0x44, 0x0d, 0x56, 0xcf, 0xed, 0x02, 0x02, 0x00, 0x07, 0xf0, 0x14, 0x37, 0xed, 0xf8, 0xa9, 0x41, 0x0b, 0x0e, 0x10, 0x03, 0x33, 0x8f, 0xf9, 0xfc, 0x65, 0x28, 0x12, 0x00, 0x08, 0xf9, 0x04, 0x14, 0x11, 0x77, 0xd5, 0xff, 0xf2, 0xf2, 0xfa, 0xe3, 0x95, 0x27, 0x10, 0x08, 0x00, 0x02, 0x02, 0x19, 0xf4, 0xb9, 0xf2, 0xec, 0xe0, 0xf0, 0xfc, 0xfc, 0xf6, 0xe8, 0xea, 0xf2, 0xf4, 0x20, 0x00, 0x00, 0x08, 0xf9, 0x01, 0x07, 0x3c, 0xd0, 0xfe, 0xfe, 0xfa, 0xfa, 0xfc, 0xfe, 0xde, 0x74, 0x03, 0x03, 0x00, 0x07, 0xf0, 0x09, 0x7e, 0xf6, 0xd0, 0x42, 0x20, 0x10, 0x08, 0x08, 0x0c, 0x18, 0x36, 0x98, 0xfe, 0xbe, 0x37, 0x09, 0x01, 0x00, 0x05, 0xf0, 0x01, 0x05, 0xe6, 0x8e, 0x1c, 0x00, 0x00, 0x00, 0x01, 0x03, 0x03, 0x01, 0x00, 0x00, 0x00, 0x66, 0x10, 0x50, 0xf4, 0x06, 0x01, 0x00, 0x04, 0x54, 0x01, 0x03, 0xf0, 0x2e, 0x00, 0x54, 0x02, 0x04, 0x04, 0x02, 0x00, 0x55, 0x20, 0xf8, 0x36, 0x05, 0x00, 0x03, 0x66, 0x02, 0x03, 0xf4, 0x20, 0x01, 0x00, 0x25, 0x05, 0x00, 0x64, 0x03, 0x0e, 0xca, 0x3c, 0x02, 0x00, 0x03, 0xf0, 0x0b, 0xdc, 0x18, 0x11, 0x07, 0x03, 0x01, 0x00, 0x00, 0x00, 0x33, 0x6b, 0x81, 0x5f, 0x27, 0xa4, 0x00, 0x00, 0x00, 0x03, 0x07, 0x15, 0x02, 0xba, 0x01, 0x00, 0xf0, 0x00, 0x00, 0x05, 0xb8, 0x26, 0x1d, 0x0f, 0x09, 0x0b, 0x07, 0x07, 0x05, 0x0f, 0x51, 0x19, 0xe3, 0x02, 0x25, 0x5d, 0x37, 0x07, 0x09, 0x07, 0x07, 0x09, 0x19, 0x0a, 0xcc, 0x05, 0x00, 0xf0, 0x00, 0x01, 0x22, 0x3c, 0x21, 0x11, 0x01, 0x0b, 0x09, 0x0d, 0x0b, 0x0b, 0x35, 0x02, 0x0e, 0xf0, 0x0e, 0x0e, 0x0a, 0x51, 0x3b, 0x0d, 0x0d, 0x0b, 0x03, 0x09, 0x41, 0x26, 0x74, 0x03, 0x00, 0x20, 0x00, 0x00, 0xf0, 0x00, 0x06, 0x8c, 0x0d, 0x43, 0x15, 0x07, 0x05, 0x07, 0x07, 0x0b, 0x09, 0x0b, 0x0a, 0x12, 0xf0, 0x12, 0x12, 0x16, 0x1c, 0x49, 0x31, 0x07, 0x05, 0x07, 0x1b, 0x23, 0x27, 0x4e, 0x02, 0x00, 0x20, 0x00, 0x00, 0xf0, 0x00, 0x02, 0x10, 0x59, 0x1f, 0x1f, 0x19, 0x05, 0x07, 0x05, 0x05, 0x07, 0x02, 0x04, 0x16, 0xf0, 0x16, 0x16, 0x18, 0x20, 0x32, 0x43, 0x2f, 0x05, 0x15, 0x1f, 0x15, 0x71, 0x02, 0x22, 0x02, 0x20, 0x00, 0x00, 0xf0, 0x02, 0x30, 0x07, 0x43, 0x1d, 0x1d, 0x29, 0x1f, 0x0d, 0x09, 0x07, 0x07, 0x26, 0x10, 0x09, 0xf0, 0x1a, 0x1a, 0x18, 0x18, 0x28, 0x46, 0x3d, 0x41, 0x31, 0x1d, 0x23, 0x21, 0x21, 0x5e, 0x05, 0x20, 0x00, 0x00, 0xf0, 0x00, 0x30, 0x2b, 0x0b, 0x13, 0x23, 0x3b, 0x67, 0x77, 0x77, 0x6d, 0x67, 0x65, 0x29, 0x33, 0x23, 0x15, 0x18, 0xc0, 0x2e, 0x54, 0x49, 0x35, 0x23, 0x1b, 0x00, 0x3d, 0x10, 0x08, 0x00, 0x00, 0xf0, 0x0b, 0x10, 0x31, 0x01, 0x07, 0x2b, 0x01, 0x8c, 0xae, 0xa4, 0x96, 0x8e, 0x8a, 0x8a, 0x88, 0x23, 0x46, 0x18, 0xc0, 0x1a, 0x3c, 0x88, 0x31, 0x25, 0x00, 0x00, 0x27, 0x09, 0x09, 0x00, 0x00, 0xb8, 0x06, 0x11, 0x00, 0x02, 0x05, 0x21, 0x94, 0x28, 0x02, 0x04, 0x06, 0xd0, 0x04, 0x00, 0x00, 0x30, 0xa6, 0x21, 0x09, 0x03, 0x10, 0x15, 0x0a, 0x00, 0x00, 0x8f, 0x06, 0x48, 0x8c, 0x94, 0x82, 0x5a, 0x0a, 0x00, 0x90, 0x0e, 0x56, 0x7e, 0x94, 0x9a, 0x56, 0x0a, 0x00, 0x00, 0x9d, 0x06, 0x18, 0x1c, 0x16, 0x1e, 0x56, 0x33, 0x11, 0x00, 0xa0, 0x15, 0x31, 0x5a, 0x24, 0x16, 0x16, 0x20, 0x08, 0x00, 0x00, 0xf0, 0x04, 0x04, 0x02, 0x00, 0x01, 0x10, 0x08, 0x2b, 0x39, 0x39, 0x39, 0x37, 0x33, 0x33, 0x35, 0x24, 0x15, 0x00, 0xb0, 0x0b, 0x25, 0x1e, 0x0a, 0x01, 0x01, 0x00, 0x02, 0x08, 0x00, 0x00, 0xf0, 0x07, 0x0f, 0x04, 0x04, 0x02, 0x00, 0x03, 0x00, 0x05, 0x00, 0x01, 0x01, 0x07, 0x05, 0x1e, 0x23, 0x16, 0x00, 0xc0, 0x0b, 0x2f, 0x01, 0x01, 0x00, 0x02, 0x04, 0x06, 0x05, 0x0f, 0x00, 0x00, 0xf0, 0x03, 0x3b, 0x01, 0x08, 0x00, 0x00, 0x02, 0x00, 0x01, 0x07, 0x05, 0x05, 0x01, 0x14, 0x18, 0x13, 0x00, 0xd0, 0x0d, 0x31, 0x05, 0x01, 0x00, 0x00, 0x00, 0x08, 0x08, 0x2f, 0x07, 0x00, 0x00, 0xf3, 0x00, 0x57, 0x15, 0x10, 0x04, 0x04, 0x02, 0x01, 0x00, 0x01, 0x01, 0x03, 0x05, 0x04, 0x00, 0xe0, 0x0f, 0x31, 0x03, 0x00, 0x02, 0x02, 0x04, 0x06, 0x0c, 0x09, 0x4d, 0x05, 0x00, 0x00, 0xf0, 0x00, 0x21, 0x51, 0x0a, 0x0c, 0x02, 0x02, 0x00, 0x01, 0x00, 0x01, 0x00, 0x00, 0x05, 0x00, 0xf0, 0x00, 0x00, 0x0f, 0x2f, 0x05, 0x01, 0x01, 0x01, 0x02, 0x00, 0x08, 0x12, 0x31, 0x57, 0x00, 0x20, 0x00, 0x00, 0xf0, 0x00, 0x01, 0x73, 0x25, 0x16, 0x0a, 0x04, 0x02, 0x04, 0x00, 0x00, 0x01, 0x00, 0x17, 0x09, 0xf0, 0x00, 0x11, 0x2f, 0x05, 0x00, 0x01, 0x04, 0x04, 0x04, 0x0c, 0x16, 0x13, 0x71, 0x09, 0x00, 0x20, 0x00, 0x00, 0xf0, 0x00, 0x00, 0x21, 0x97, 0x13, 0x1a, 0x0c, 0x08, 0x04, 0x04, 0x02, 0x00, 0x03, 0x07, 0x3d, 0xe3, 0x3f, 0x35, 0x07, 0x00, 0x02, 0x06, 0x04, 0x08, 0x0a, 0x18, 0x00, 0x79, 0x55, 0x00, 0x03, 0xf0, 0x43, 0x81, 0x0d, 0x1a, 0x0c, 0x06, 0x06, 0x04, 0x02, 0x04, 0x04, 0x02, 0x05, 0x04, 0x04, 0xa4, 0x02, 0x08, 0x02, 0x04, 0x0a, 0x18, 0x04, 0x6d, 0x6d, 0x00, 0x04, 0xf0, 0x65, 0x8d, 0x0d, 0x1a, 0x10, 0x0a, 0x0a, 0x0a, 0x06, 0x04, 0x08, 0x08, 0x04, 0x06, 0x0a, 0x94, 0x06, 0x0c, 0x12, 0x1a, 0x02, 0x73, 0x85, 0x07, 0x00, 0x05, 0xf0, 0x5d, 0xaf, 0x1d, 0x1a, 0x1a, 0x12, 0x0c, 0x0c, 0x0c, 0x06, 0x06, 0x0c, 0x0c, 0x0c, 0x10, 0x75, 0x1a, 0x20, 0x0f, 0x91, 0x83, 0x05, 0x00, 0x06, 0xf0, 0x3b, 0xc3, 0x6d, 0x0b, 0x16, 0x20, 0x1c, 0x16, 0x18, 0x18, 0x16, 0x1a, 0x20, 0x1c, 0x00, 0x56, 0x57, 0xbb, 0x65, 0x03, 0x00, 0x07, 0xf0, 0x17, 0x8d, 0xcf, 0x87, 0x43, 0x11, 0x02, 0x08, 0x0a, 0x04, 0x0d, 0x35, 0x79, 0xbf, 0xa7, 0x28, 0x2d, 0x00, 0x08, 0xf9, 0x01, 0x17, 0x73, 0xb5, 0xd5, 0xcf, 0xb5, 0xb3, 0xc7, 0xd3, 0xc1, 0x85, 0x31, 0x03, 0x00 }; uint8 decompressed_32x32x32[] = { 0x7a, 0x5f, 0x1d, 0x00, 0x7a, 0x5f, 0x1d, 0x00, 0x7a, 0x5f, 0x1d, 0x00, 0x7a, 0x5f, 0x1d, 0x00, 0x7a, 0x5f, 0x1d, 0x00, 0x7a, 0x5f, 0x1d, 0x00, 0x7a, 0x5f, 0x1d, 0x00, 0x7a, 0x5f, 0x1d, 0x00, 0x7a, 0x5f, 0x1d, 0x00, 0x7a, 0x5f, 0x1d, 0x00, 0x7a, 0x5f, 0x1d, 0x00, 0x7b, 0x5c, 0x1b, 0x14, 0x80, 0x57, 0x16, 0x3c, 0x89, 0x54, 0x12, 0x60, 0x98, 0x56, 0x10, 0x75, 0x9a, 0x57, 0x0f, 0x77, 0x8e, 0x55, 0x11, 0x67, 0x82, 0x56, 0x15, 0x46, 0x7c, 0x59, 0x19, 0x1f, 0x7a, 0x5f, 0x1d, 0x00, 0x7a, 0x5f, 0x1d, 0x00, 0x7a, 0x5f, 0x1d, 0x00, 0x7a, 0x5f, 0x1d, 0x00, 0x7a, 0x5f, 0x1d, 0x00, 0x7a, 0x5f, 0x1d, 0x00, 0x7a, 0x5f, 0x1d, 0x00, 0x7a, 0x5f, 0x1d, 0x00, 0x7a, 0x5f, 0x1d, 0x00, 0x7a, 0x5f, 0x1d, 0x00, 0x7a, 0x5f, 0x1d, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x7a, 0x5f, 0x1d, 0x00, 0x7a, 0x5f, 0x1d, 0x00, 0x7a, 0x5f, 0x1d, 0x00, 0x7a, 0x5f, 0x1d, 0x00, 0x7a, 0x5f, 0x1d, 0x00, 0x7a, 0x5f, 0x1d, 0x00, 0x7a, 0x5f, 0x1d, 0x00, 0x7a, 0x5f, 0x1d, 0x00, 0x7b, 0x5d, 0x1c, 0x07, 0x86, 0x55, 0x13, 0x56, 0xb4, 0x68, 0x21, 0xb0, 0xd6, 0x98, 0x66, 0xea, 0xeb, 0xc2, 0xa3, 0xff, 0xf1, 0xd4, 0xbf, 0xff, 0xf3, 0xdd, 0xcd, 0xff, 0xf4, 0xde, 0xcf, 0xff, 0xf2, 0xd8, 0xc4, 0xff, 0xec, 0xc8, 0xab, 0xff, 0xdd, 0xa4, 0x78, 0xf4, 0xbd, 0x73, 0x30, 0xc2, 0x93, 0x57, 0x10, 0x6e, 0x7c, 0x5b, 0x1b, 0x15, 0x7a, 0x5f, 0x1d, 0x00, 0x7a, 0x5f, 0x1d, 0x00, 0x7a, 0x5f, 0x1d, 0x00, 0x7a, 0x5f, 0x1d, 0x00, 0x7a, 0x5f, 0x1d, 0x00, 0x7a, 0x5f, 0x1d, 0x00, 0x7a, 0x5f, 0x1d, 0x00, 0x7a, 0x5f, 0x1d, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x7a, 0x5f, 0x1d, 0x00, 0x7a, 0x5f, 0x1d, 0x00, 0x7a, 0x5f, 0x1d, 0x00, 0x7a, 0x5f, 0x1d, 0x00, 0x7a, 0x5f, 0x1d, 0x00, 0x7a, 0x5f, 0x1d, 0x00, 0x7a, 0x5f, 0x1d, 0x00, 0x86, 0x55, 0x13, 0x54, 0xc2, 0x79, 0x3a, 0xd1, 0xee, 0xcc, 0xaf, 0xff, 0xf8, 0xec, 0xe1, 0xff, 0xf8, 0xed, 0xe4, 0xff, 0xf4, 0xe3, 0xd7, 0xff, 0xf0, 0xda, 0xcb, 0xff, 0xef, 0xd6, 0xc6, 0xff, 0xef, 0xd6, 0xc6, 0xff, 0xf0, 0xda, 0xcb, 0xff, 0xf3, 0xe2, 0xd5, 0xff, 0xf8, 0xec, 0xe4, 0xff, 0xfa, 0xf0, 0xe8, 0xff, 0xf3, 0xd9, 0xc3, 0xff, 0xd0, 0x8e, 0x57, 0xe5, 0x91, 0x56, 0x11, 0x6b, 0x7a, 0x5f, 0x1d, 0x00, 0x7a, 0x5f, 0x1d, 0x00, 0x7a, 0x5f, 0x1d, 0x00, 0x7a, 0x5f, 0x1d, 0x00, 0x7a, 0x5f, 0x1d, 0x00, 0x7a, 0x5f, 0x1d, 0x00, 0x7a, 0x5f, 0x1d, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x7a, 0x5f, 0x1d, 0x00, 0x7a, 0x5f, 0x1d, 0x00, 0x7a, 0x5f, 0x1d, 0x00, 0x7a, 0x5f, 0x1d, 0x00, 0x7a, 0x5f, 0x1d, 0x00, 0x7a, 0x5f, 0x1d, 0x00, 0x98, 0x57, 0x0f, 0x79, 0xe8, 0xbb, 0x93, 0xff, 0xf9, 0xf1, 0xe6, 0xff, 0xf4, 0xe2, 0xd4, 0xff, 0xed, 0xd0, 0xbd, 0xff, 0xe8, 0xc6, 0xae, 0xff, 0xe6, 0xc0, 0xa8, 0xff, 0xe5, 0xbe, 0xa4, 0xff, 0xe3, 0xbb, 0xa1, 0xff, 0xe3, 0xbb, 0xa1, 0xff, 0xe5, 0xbe, 0xa4, 0xff, 0xe6, 0xc0, 0xa8, 0xff, 0xe8, 0xc6, 0xaf, 0xff, 0xec, 0xce, 0xbb, 0xff, 0xf3, 0xe0, 0xd2, 0xff, 0xfc, 0xf6, 0xee, 0xff, 0xef, 0xcd, 0xae, 0xff, 0xad, 0x5e, 0x13, 0xa0, 0x7c, 0x5e, 0x1b, 0x0e, 0x7a, 0x5f, 0x1d, 0x00, 0x7a, 0x5f, 0x1d, 0x00, 0x7a, 0x5f, 0x1d, 0x00, 0x7a, 0x5f, 0x1d, 0x00, 0x7a, 0x5f, 0x1d, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x7a, 0x5f, 0x1d, 0x00, 0x7a, 0x5f, 0x1d, 0x00, 0x7a, 0x5f, 0x1d, 0x00, 0x7a, 0x5f, 0x1d, 0x00, 0x7a, 0x5f, 0x1d, 0x04, 0xa9, 0x59, 0x0e, 0x9e, 0xf0, 0xce, 0xab, 0xff, 0xf7, 0xea, 0xdc, 0xff, 0xec, 0xcf, 0xb9, 0xff, 0xe7, 0xc1, 0xa8, 0xff, 0xe4, 0xbb, 0xa0, 0xff, 0xe2, 0xb6, 0x99, 0xff, 0xe0, 0xb2, 0x93, 0xff, 0xdf, 0xb0, 0x90, 0xff, 0xe0, 0xb0, 0x8f, 0xff, 0xe0, 0xb0, 0x8f, 0xff, 0xdf, 0xb0, 0x90, 0xff, 0xe0, 0xb2, 0x93, 0xff, 0xe2, 0xb6, 0x99, 0xff, 0xe4, 0xbb, 0xa0, 0xff, 0xe6, 0xc1, 0xa8, 0xff, 0xec, 0xcd, 0xb8, 0xff, 0xf7, 0xe9, 0xdc, 0xff, 0xf6, 0xe4, 0xcc, 0xff, 0xbe, 0x6d, 0x25, 0xc7, 0x7d, 0x5b, 0x1a, 0x19, 0x7a, 0x5f, 0x1d, 0x00, 0x7a, 0x5f, 0x1d, 0x00, 0x7a, 0x5f, 0x1d, 0x00, 0x7a, 0x5f, 0x1d, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x7a, 0x5f, 0x1d, 0x00, 0x7a, 0x5f, 0x1d, 0x00, 0x7a, 0x5f, 0x1d, 0x00, 0x7a, 0x5f, 0x1d, 0x00, 0xad, 0x5c, 0x0f, 0x9f, 0xf0, 0xd4, 0xb2, 0xff, 0xf7, 0xe9, 0xd9, 0xff, 0xea, 0xc8, 0xaf, 0xff, 0xe4, 0xbb, 0x9e, 0xff, 0xe2, 0xb5, 0x96, 0xff, 0xdf, 0xaf, 0x8d, 0xff, 0xdd, 0xaa, 0x85, 0xff, 0xdd, 0xa7, 0x80, 0xff, 0xdd, 0xa5, 0x7c, 0xff, 0xdc, 0xa3, 0x7a, 0xff, 0xdc, 0xa3, 0x7a, 0xff, 0xdd, 0xa5, 0x7c, 0xff, 0xdd, 0xa7, 0x80, 0xff, 0xdd, 0xaa, 0x85, 0xff, 0xe1, 0xb0, 0x8e, 0xff, 0xe0, 0xb4, 0x95, 0xff, 0xe3, 0xbb, 0x9e, 0xff, 0xea, 0xc9, 0xb0, 0xff, 0xf5, 0xe5, 0xd4, 0xff, 0xf8, 0xec, 0xd5, 0xff, 0xc0, 0x6e, 0x26, 0xcb, 0x7e, 0x5f, 0x1b, 0x11, 0x7a, 0x5f, 0x1d, 0x00, 0x7a, 0x5f, 0x1d, 0x00, 0x7a, 0x5f, 0x1d, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x7a, 0x5f, 0x1d, 0x00, 0x7a, 0x5f, 0x1d, 0x00, 0x7a, 0x5f, 0x1d, 0x00, 0x9c, 0x5a, 0x0f, 0x79, 0xee, 0xcb, 0xa3, 0xff, 0xf7, 0xe9, 0xd4, 0xff, 0xea, 0xc8, 0xad, 0xff, 0xe4, 0xba, 0x9a, 0xff, 0xe1, 0xb2, 0x8e, 0xff, 0xdf, 0xab, 0x84, 0xff, 0xdd, 0xa5, 0x7a, 0xff, 0xdc, 0xa0, 0x72, 0xff, 0xdb, 0x9c, 0x6c, 0xff, 0xdb, 0x9b, 0x69, 0xff, 0xdb, 0x9a, 0x68, 0xff, 0xdf, 0xa6, 0x7a, 0xff, 0xdb, 0x9b, 0x69, 0xff, 0xdb, 0x9c, 0x6c, 0xff, 0xdc, 0xa0, 0x72, 0xff, 0xdd, 0xa5, 0x7a, 0xff, 0xdf, 0xab, 0x84, 0xff, 0xe1, 0xb2, 0x8e, 0xff, 0xe5, 0xbb, 0x9b, 0xff, 0xe9, 0xc8, 0xad, 0xff, 0xf6, 0xe5, 0xd1, 0xff, 0xf7, 0xe6, 0xca, 0xff, 0xb5, 0x64, 0x15, 0xae, 0x7a, 0x5f, 0x1d, 0x01, 0x7a, 0x5f, 0x1d, 0x00, 0x7a, 0x5f, 0x1d, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x7a, 0x5f, 0x1d, 0x00, 0x7a, 0x5f, 0x1d, 0x00, 0x8b, 0x5a, 0x14, 0x4f, 0xe8, 0xb6, 0x84, 0xfe, 0xf8, 0xe9, 0xd0, 0xff, 0xea, 0xc8, 0xa8, 0xff, 0xe4, 0xba, 0x95, 0xff, 0xe0, 0xaf, 0x85, 0xff, 0xdf, 0xa7, 0x79, 0xff, 0xdd, 0xa0, 0x6e, 0xff, 0xdc, 0x9b, 0x64, 0xff, 0xdc, 0x97, 0x5e, 0xff, 0xdd, 0x94, 0x59, 0xff, 0xdf, 0x9d, 0x66, 0xff, 0xfa, 0xee, 0xe5, 0xff, 0xff, 0xff, 0xff, 0xff, 0xf6, 0xe3, 0xd3, 0xff, 0xdf, 0x9a, 0x63, 0xff, 0xdc, 0x97, 0x5e, 0xff, 0xdc, 0x9b, 0x64, 0xff, 0xdc, 0x9f, 0x6d, 0xff, 0xdf, 0xa7, 0x79, 0xff, 0xe1, 0xb0, 0x87, 0xff, 0xe4, 0xba, 0x95, 0xff, 0xea, 0xc7, 0xa8, 0xff, 0xf7, 0xe7, 0xce, 0xff, 0xf2, 0xd6, 0xb1, 0xff, 0xa5, 0x5d, 0x0e, 0x84, 0x7a, 0x5f, 0x1d, 0x00, 0x7a, 0x5f, 0x1d, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x7a, 0x5f, 0x1d, 0x00, 0x7b, 0x5d, 0x1c, 0x07, 0xc5, 0x77, 0x31, 0xd7, 0xfb, 0xef, 0xd1, 0xff, 0xed, 0xce, 0xab, 0xff, 0xe5, 0xbc, 0x94, 0xff, 0xe2, 0xb1, 0x86, 0xff, 0xdf, 0xa5, 0x74, 0xff, 0xdd, 0x9d, 0x67, 0xff, 0xdd, 0x98, 0x5e, 0xff, 0xdc, 0x93, 0x56, 0xff, 0xdd, 0x90, 0x50, 0xff, 0xdd, 0x8f, 0x4c, 0xff, 0xeb, 0xbe, 0x98, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xf7, 0xe6, 0xd7, 0xff, 0xdf, 0x97, 0x5a, 0xff, 0xdc, 0x93, 0x56, 0xff, 0xdd, 0x98, 0x5e, 0xff, 0xdd, 0x9d, 0x67, 0xff, 0xdf, 0xa6, 0x75, 0xff, 0xe2, 0xb2, 0x86, 0xff, 0xe4, 0xbb, 0x94, 0xff, 0xec, 0xcd, 0xaa, 0xff, 0xfc, 0xf2, 0xd8, 0xff, 0xde, 0xa2, 0x67, 0xf9, 0x7f, 0x5a, 0x19, 0x26, 0x7a, 0x5f, 0x1d, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x7a, 0x5f, 0x1d, 0x00, 0x8c, 0x58, 0x13, 0x56, 0xee, 0xc5, 0x95, 0xff, 0xf6, 0xe1, 0xc0, 0xff, 0xe7, 0xbf, 0x98, 0xff, 0xe4, 0xb4, 0x88, 0xff, 0xe1, 0xaa, 0x79, 0xff, 0xdf, 0xa0, 0x69, 0xff, 0xde, 0x98, 0x5c, 0xff, 0xdd, 0x93, 0x52, 0xff, 0xdd, 0x8f, 0x4b, 0xff, 0xdd, 0x8c, 0x45, 0xff, 0xdd, 0x8a, 0x42, 0xff, 0xee, 0xc1, 0x9a, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xf7, 0xe5, 0xd5, 0xff, 0xdf, 0x96, 0x56, 0xff, 0xde, 0x93, 0x53, 0xff, 0xde, 0x98, 0x5c, 0xff, 0xe0, 0xa1, 0x6a, 0xff, 0xe1, 0xaa, 0x79, 0xff, 0xe4, 0xb4, 0x88, 0xff, 0xe8, 0xc0, 0x98, 0xff, 0xf3, 0xdb, 0xba, 0xff, 0xf7, 0xe2, 0xbc, 0xff, 0xab, 0x5f, 0x0f, 0x91, 0x7a, 0x5f, 0x1d, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x7a, 0x5f, 0x1d, 0x00, 0xb8, 0x69, 0x1a, 0xb3, 0xf9, 0xe6, 0xc0, 0xff, 0xee, 0xcd, 0xa6, 0xff, 0xe5, 0xb9, 0x8c, 0xff, 0xe2, 0xae, 0x7c, 0xff, 0xe0, 0xa4, 0x6e, 0xff, 0xe0, 0x9b, 0x5e, 0xff, 0xde, 0x94, 0x52, 0xff, 0xde, 0x8f, 0x49, 0xff, 0xde, 0x8c, 0x42, 0xff, 0xdf, 0x8a, 0x3d, 0xff, 0xe0, 0x89, 0x39, 0xff, 0xec, 0xb8, 0x87, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xf8, 0xe5, 0xd5, 0xff, 0xe0, 0x94, 0x52, 0xff, 0xde, 0x94, 0x51, 0xff, 0xdf, 0x9b, 0x5e, 0xff, 0xe0, 0xa4, 0x6e, 0xff, 0xe2, 0xae, 0x7d, 0xff, 0xe5, 0xb9, 0x8c, 0xff, 0xed, 0xcb, 0xa4, 0xff, 0xfc, 0xef, 0xce, 0xff, 0xd2, 0x8a, 0x43, 0xe4, 0x7d, 0x5e, 0x1c, 0x0d, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x7c, 0x5c, 0x1a, 0x16, 0xd6, 0x8c, 0x47, 0xf0, 0xfa, 0xe8, 0xc0, 0xff, 0xea, 0xc2, 0x96, 0xff, 0xe5, 0xb5, 0x83, 0xff, 0xe2, 0xaa, 0x72, 0xff, 0xdf, 0x9f, 0x62, 0xff, 0xe0, 0x97, 0x54, 0xff, 0xdf, 0x91, 0x48, 0xff, 0xe2, 0x8e, 0x42, 0xff, 0xe1, 0x8b, 0x3b, 0xff, 0xe2, 0x89, 0x37, 0xff, 0xe1, 0x86, 0x31, 0xff, 0xe2, 0x85, 0x2f, 0xff, 0xf3, 0xcd, 0xa9, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xf9, 0xe6, 0xd5, 0xff, 0xe1, 0x96, 0x51, 0xff, 0xe0, 0x97, 0x54, 0xff, 0xe0, 0xa0, 0x63, 0xff, 0xe2, 0xaa, 0x72, 0xff, 0xe5, 0xb5, 0x83, 0xff, 0xe9, 0xc2, 0x96, 0xff, 0xf8, 0xe6, 0xc0, 0xff, 0xea, 0xb7, 0x7e, 0xff, 0x81, 0x54, 0x15, 0x43, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, 0x55, 0x16, 0x40, 0xde, 0x91, 0x4e, 0xff, 0xf8, 0xe0, 0xb4, 0xff, 0xe8, 0xbc, 0x8b, 0xff, 0xe4, 0xaf, 0x78, 0xff, 0xe2, 0xa5, 0x68, 0xff, 0xe1, 0x9b, 0x59, 0xff, 0xe0, 0x93, 0x4a, 0xff, 0xe2, 0x8f, 0x42, 0xff, 0xe2, 0x8c, 0x3a, 0xff, 0xe2, 0x89, 0x35, 0xff, 0xe3, 0x87, 0x30, 0xff, 0xe5, 0x86, 0x2c, 0xff, 0xe5, 0x84, 0x29, 0xff, 0xe4, 0x83, 0x27, 0xff, 0xf4, 0xcc, 0xa6, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xf9, 0xe6, 0xd5, 0xff, 0xe1, 0x98, 0x53, 0xff, 0xe1, 0x9b, 0x59, 0xff, 0xe2, 0xa5, 0x68, 0xff, 0xe4, 0xaf, 0x78, 0xff, 0xe7, 0xbb, 0x8a, 0xff, 0xf5, 0xdb, 0xb1, 0xff, 0xed, 0xbb, 0x82, 0xff, 0x89, 0x4f, 0x0f, 0x78, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x7e, 0x48, 0x12, 0x65, 0xdc, 0x8b, 0x49, 0xff, 0xf7, 0xda, 0xa9, 0xff, 0xe8, 0xb8, 0x82, 0xff, 0xe5, 0xae, 0x73, 0xff, 0xda, 0x9c, 0x5d, 0xff, 0xdd, 0xa9, 0x77, 0xff, 0xf6, 0xe7, 0xd9, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xf4, 0xe1, 0xd0, 0xff, 0xd2, 0x90, 0x51, 0xff, 0xdd, 0x9d, 0x5e, 0xff, 0xe5, 0xad, 0x72, 0xff, 0xe8, 0xb8, 0x82, 0xff, 0xf5, 0xd7, 0xa7, 0xff, 0xec, 0xb7, 0x7d, 0xff, 0x85, 0x40, 0x0b, 0x9f, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x7b, 0x41, 0x0f, 0x79, 0xd0, 0x64, 0x19, 0xff, 0xe9, 0xb2, 0x73, 0xff, 0xdd, 0x99, 0x57, 0xff, 0xd6, 0x7f, 0x34, 0xff, 0xaf, 0x58, 0x11, 0xff, 0xf7, 0xee, 0xe7, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xeb, 0xd5, 0xc3, 0xff, 0xb0, 0x5e, 0x1c, 0xff, 0xd3, 0x7d, 0x33, 0xff, 0xdd, 0x99, 0x58, 0xff, 0xea, 0xb7, 0x7a, 0xff, 0xdc, 0x86, 0x3f, 0xff, 0x81, 0x34, 0x09, 0xb4, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x78, 0x3e, 0x0f, 0x7b, 0xac, 0x3e, 0x01, 0xff, 0xa3, 0x43, 0x01, 0xff, 0x93, 0x3b, 0x01, 0xff, 0x95, 0x39, 0x01, 0xff, 0x82, 0x34, 0x01, 0xff, 0xf2, 0xea, 0xe4, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xe4, 0xd3, 0xc6, 0xff, 0x85, 0x3d, 0x0d, 0xff, 0x94, 0x38, 0x01, 0xff, 0x93, 0x3b, 0x01, 0xff, 0x9d, 0x40, 0x01, 0xff, 0xb1, 0x42, 0x01, 0xff, 0x7c, 0x32, 0x08, 0xb6, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x75, 0x41, 0x11, 0x6d, 0xb5, 0x3c, 0x01, 0xff, 0xa3, 0x42, 0x01, 0xff, 0x92, 0x39, 0x01, 0xff, 0x98, 0x3f, 0x01, 0xff, 0x93, 0x3e, 0x01, 0xff, 0xa8, 0x6e, 0x43, 0xff, 0xeb, 0xdc, 0xcf, 0xff, 0xfe, 0xfe, 0xfe, 0xff, 0xfd, 0xfd, 0xfd, 0xff, 0xfc, 0xfc, 0xfc, 0xff, 0xfc, 0xfc, 0xfc, 0xff, 0xfc, 0xfc, 0xfc, 0xff, 0xfc, 0xfc, 0xfc, 0xff, 0xfc, 0xfc, 0xfc, 0xff, 0xfc, 0xfc, 0xfc, 0xff, 0xfc, 0xfc, 0xfc, 0xff, 0xfc, 0xfc, 0xfc, 0xff, 0xfc, 0xfc, 0xfc, 0xff, 0xfd, 0xfd, 0xfd, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xe7, 0xd5, 0xc6, 0xff, 0x91, 0x47, 0x10, 0xff, 0x96, 0x3f, 0x01, 0xff, 0x99, 0x3f, 0x01, 0xff, 0x95, 0x39, 0x01, 0xff, 0x95, 0x3a, 0x01, 0xff, 0xbc, 0x43, 0x01, 0xff, 0x77, 0x34, 0x0a, 0xa7, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x7b, 0x4f, 0x14, 0x4b, 0xad, 0x31, 0x01, 0xff, 0xbc, 0x4d, 0x01, 0xff, 0x93, 0x39, 0x01, 0xff, 0x9c, 0x40, 0x01, 0xff, 0xa9, 0x48, 0x01, 0xff, 0xa9, 0x4c, 0x01, 0xff, 0xa5, 0x4e, 0x01, 0xff, 0xa7, 0x52, 0x01, 0xff, 0xab, 0x55, 0x01, 0xff, 0xb1, 0x59, 0x01, 0xff, 0xb5, 0x5c, 0x01, 0xff, 0xb7, 0x5e, 0x00, 0xff, 0xb7, 0x5f, 0x01, 0xff, 0xb8, 0x60, 0x02, 0xff, 0xd9, 0xb5, 0x8e, 0xff, 0xf0, 0xf0, 0xf0, 0xff, 0xf0, 0xf0, 0xf0, 0xff, 0xf0, 0xf0, 0xf0, 0xff, 0xf1, 0xf1, 0xf1, 0xff, 0xf2, 0xf2, 0xf2, 0xff, 0xe1, 0xce, 0xbc, 0xff, 0xa3, 0x54, 0x0f, 0xff, 0xaa, 0x4d, 0x01, 0xff, 0xa9, 0x48, 0x01, 0xff, 0x99, 0x3f, 0x01, 0xff, 0x95, 0x39, 0x01, 0xff, 0xa9, 0x44, 0x01, 0xff, 0xc1, 0x3e, 0x01, 0xff, 0x7c, 0x40, 0x0e, 0x85, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x7b, 0x59, 0x19, 0x21, 0x95, 0x28, 0x01, 0xf8, 0xd2, 0x57, 0x03, 0xff, 0x99, 0x3d, 0x01, 0xff, 0xa6, 0x47, 0x01, 0xff, 0xbb, 0x54, 0x01, 0xff, 0xc7, 0x5f, 0x01, 0xff, 0xd9, 0x6c, 0x01, 0xff, 0xe3, 0x75, 0x01, 0xff, 0xe7, 0x7a, 0x02, 0xff, 0xe8, 0x7c, 0x04, 0xff, 0xe9, 0x7e, 0x06, 0xff, 0xea, 0x81, 0x08, 0xff, 0xcc, 0x70, 0x07, 0xff, 0xd2, 0xb0, 0x89, 0xff, 0xe4, 0xe4, 0xe4, 0xff, 0xe4, 0xe4, 0xe4, 0xff, 0xe4, 0xe4, 0xe4, 0xff, 0xe4, 0xe4, 0xe4, 0xff, 0xe5, 0xe5, 0xe5, 0xff, 0xdb, 0xc8, 0xb5, 0xff, 0xb7, 0x64, 0x0e, 0xff, 0xc8, 0x64, 0x01, 0xff, 0xc5, 0x5f, 0x01, 0xff, 0xbb, 0x54, 0x01, 0xff, 0xa7, 0x47, 0x01, 0xff, 0x95, 0x3b, 0x01, 0xff, 0xc8, 0x52, 0x01, 0xff, 0xb9, 0x33, 0x01, 0xff, 0x78, 0x4b, 0x14, 0x53, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x7a, 0x5e, 0x1d, 0x02, 0x7d, 0x2d, 0x06, 0xc9, 0xd6, 0x5b, 0x09, 0xff, 0xbb, 0x52, 0x01, 0xff, 0xb5, 0x53, 0x01, 0xff, 0xca, 0x62, 0x01, 0xff, 0xdc, 0x70, 0x01, 0xff, 0xe9, 0x7d, 0x03, 0xff, 0xea, 0x81, 0x08, 0xff, 0xec, 0x86, 0x0b, 0xff, 0xec, 0x87, 0x0e, 0xff, 0xed, 0x8b, 0x11, 0xff, 0xd7, 0x80, 0x11, 0xff, 0xc4, 0x98, 0x5f, 0xff, 0xd7, 0xd7, 0xd7, 0xff, 0xd7, 0xd7, 0xd7, 0xff, 0xd7, 0xd7, 0xd7, 0xff, 0xd8, 0xd8, 0xd7, 0xff, 0xd8, 0xd8, 0xd8, 0xff, 0xd1, 0xc0, 0xad, 0xff, 0xb8, 0x6f, 0x14, 0xff, 0xd6, 0x77, 0x07, 0xff, 0xe9, 0x7d, 0x03, 0xff, 0xde, 0x72, 0x01, 0xff, 0xca, 0x62, 0x01, 0xff, 0xb9, 0x54, 0x01, 0xff, 0xa6, 0x48, 0x01, 0xff, 0xd9, 0x61, 0x0a, 0xff, 0x8a, 0x27, 0x01, 0xf2, 0x7b, 0x5b, 0x1a, 0x19, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x7a, 0x5f, 0x1d, 0x00, 0x7c, 0x47, 0x10, 0x72, 0xce, 0x4c, 0x02, 0xff, 0xe8, 0x78, 0x0c, 0xff, 0xc5, 0x5f, 0x01, 0xff, 0xda, 0x72, 0x01, 0xff, 0xe9, 0x7f, 0x03, 0xff, 0xec, 0x87, 0x0b, 0xff, 0xee, 0x8f, 0x13, 0xff, 0xef, 0x95, 0x19, 0xff, 0xef, 0x98, 0x1d, 0xff, 0xf1, 0x9c, 0x21, 0xff, 0xd6, 0x8e, 0x1f, 0xff, 0xc2, 0xa1, 0x6f, 0xff, 0xcc, 0xcc, 0xcc, 0xff, 0xcc, 0xcc, 0xcc, 0xff, 0xcc, 0xcc, 0xcc, 0xff, 0xcc, 0xcc, 0xcc, 0xff, 0xc8, 0xbb, 0xa8, 0xff, 0xb8, 0x79, 0x21, 0xff, 0xda, 0x88, 0x17, 0xff, 0xee, 0x8f, 0x13, 0xff, 0xec, 0x87, 0x0b, 0xff, 0xe9, 0x7f, 0x03, 0xff, 0xda, 0x72, 0x01, 0xff, 0xc4, 0x60, 0x01, 0xff, 0xdf, 0x6c, 0x01, 0xff, 0xd8, 0x62, 0x0c, 0xff, 0x79, 0x35, 0x09, 0xad, 0x7a, 0x5f, 0x1d, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x7a, 0x5f, 0x1d, 0x00, 0x79, 0x59, 0x1a, 0x18, 0x88, 0x27, 0x02, 0xef, 0xef, 0x8e, 0x22, 0xff, 0xe7, 0x7a, 0x01, 0xff, 0xe5, 0x7c, 0x01, 0xff, 0xed, 0x8a, 0x0b, 0xff, 0xef, 0x96, 0x17, 0xff, 0xf2, 0xa1, 0x22, 0xff, 0xf3, 0xa7, 0x29, 0xff, 0xf5, 0xad, 0x30, 0xff, 0xf6, 0xb0, 0x33, 0xff, 0xdc, 0x9f, 0x30, 0xff, 0xbd, 0xa1, 0x6b, 0xff, 0xc3, 0xc3, 0xc3, 0xff, 0xc3, 0xc3, 0xc3, 0xff, 0xc3, 0xc3, 0xc3, 0xff, 0xc1, 0xb7, 0xa4, 0xff, 0xba, 0x89, 0x2f, 0xff, 0xdd, 0x9c, 0x2b, 0xff, 0xf3, 0xa8, 0x2a, 0xff, 0xf2, 0xa1, 0x22, 0xff, 0xef, 0x95, 0x17, 0xff, 0xed, 0x8a, 0x0b, 0xff, 0xe8, 0x7f, 0x01, 0xff, 0xd6, 0x6f, 0x01, 0xff, 0xf3, 0x93, 0x21, 0xff, 0xb1, 0x38, 0x01, 0xff, 0x78, 0x4f, 0x15, 0x43, 0x7a, 0x5f, 0x1d, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x7a, 0x5f, 0x1d, 0x00, 0x7a, 0x5f, 0x1d, 0x00, 0x77, 0x44, 0x10, 0x6e, 0xd1, 0x55, 0x01, 0xff, 0xf8, 0xaa, 0x30, 0xff, 0xee, 0x8a, 0x0a, 0xff, 0xee, 0x95, 0x16, 0xff, 0xf5, 0xaa, 0x2c, 0xff, 0xf7, 0xb5, 0x38, 0xff, 0xfa, 0xbc, 0x3f, 0xff, 0xfb, 0xc2, 0x44, 0xff, 0xfc, 0xc5, 0x47, 0xff, 0xf7, 0xc2, 0x48, 0xff, 0xbc, 0x98, 0x44, 0xff, 0xbc, 0xb4, 0xa0, 0xff, 0xbc, 0xbc, 0xbc, 0xff, 0xbc, 0xb0, 0x95, 0xff, 0xbc, 0x96, 0x40, 0xff, 0xe3, 0xb1, 0x40, 0xff, 0xfb, 0xc2, 0x44, 0xff, 0xfa, 0xbc, 0x3f, 0xff, 0xf9, 0xb5, 0x39, 0xff, 0xf5, 0xaa, 0x2c, 0xff, 0xef, 0x97, 0x19, 0xff, 0xed, 0x87, 0x06, 0xff, 0xf7, 0xa3, 0x25, 0xff, 0xe0, 0x74, 0x13, 0xff, 0x77, 0x35, 0x0a, 0xa6, 0x7a, 0x5f, 0x1d, 0x00, 0x7a, 0x5f, 0x1d, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x7a, 0x5f, 0x1d, 0x00, 0x7a, 0x5f, 0x1d, 0x00, 0x7a, 0x5f, 0x1d, 0x00, 0x75, 0x33, 0x0a, 0xa7, 0xe5, 0x7c, 0x1a, 0xff, 0xfd, 0xc6, 0x4e, 0xff, 0xf6, 0xa4, 0x25, 0xff, 0xfa, 0xbc, 0x3f, 0xff, 0xfd, 0xca, 0x4e, 0xff, 0xfe, 0xd0, 0x54, 0xff, 0xff, 0xd6, 0x5a, 0xff, 0xff, 0xd9, 0x60, 0xff, 0xff, 0xdb, 0x5f, 0xff, 0xe5, 0xc6, 0x57, 0xff, 0xc9, 0xae, 0x4f, 0xff, 0xbb, 0xa3, 0x4e, 0xff, 0xcf, 0xb2, 0x4f, 0xff, 0xeb, 0xca, 0x58, 0xff, 0xff, 0xd9, 0x60, 0xff, 0xff, 0xd6, 0x5a, 0xff, 0xff, 0xd0, 0x54, 0xff, 0xfd, 0xca, 0x4e, 0xff, 0xf9, 0xbd, 0x3f, 0xff, 0xf4, 0xa2, 0x23, 0xff, 0xfa, 0xba, 0x3f, 0xff, 0xf2, 0x9e, 0x32, 0xff, 0x7a, 0x27, 0x05, 0xd6, 0x7a, 0x5d, 0x1b, 0x0e, 0x7a, 0x5f, 0x1d, 0x00, 0x7a, 0x5f, 0x1d, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x7a, 0x5f, 0x1d, 0x00, 0x7a, 0x5f, 0x1d, 0x00, 0x7a, 0x5f, 0x1d, 0x00, 0x7b, 0x5d, 0x1b, 0x10, 0x77, 0x29, 0x05, 0xd0, 0xf1, 0x9b, 0x36, 0xff, 0xff, 0xdf, 0x6b, 0xff, 0xfe, 0xc9, 0x4c, 0xff, 0xff, 0xd6, 0x5c, 0xff, 0xff, 0xe0, 0x65, 0xff, 0xff, 0xe5, 0x6a, 0xff, 0xff, 0xe8, 0x6d, 0xff, 0xff, 0xeb, 0x6f, 0xff, 0xff, 0xeb, 0x74, 0xff, 0xff, 0xeb, 0x74, 0xff, 0xfc, 0xe8, 0x72, 0xff, 0xff, 0xeb, 0x74, 0xff, 0xff, 0xeb, 0x6f, 0xff, 0xff, 0xe8, 0x6d, 0xff, 0xff, 0xe5, 0x6a, 0xff, 0xff, 0xe0, 0x65, 0xff, 0xff, 0xd8, 0x5e, 0xff, 0xfd, 0xc6, 0x48, 0xff, 0xff, 0xd5, 0x61, 0xff, 0xf9, 0xba, 0x4e, 0xff, 0x95, 0x2d, 0x02, 0xef, 0x7b, 0x56, 0x17, 0x31, 0x7a, 0x5f, 0x1d, 0x00, 0x7a, 0x5f, 0x1d, 0x00, 0x7a, 0x5f, 0x1d, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x7a, 0x5f, 0x1d, 0x00, 0x7a, 0x5f, 0x1d, 0x00, 0x7a, 0x5f, 0x1d, 0x00, 0x7a, 0x5f, 0x1d, 0x00, 0x79, 0x59, 0x1a, 0x1e, 0x77, 0x28, 0x05, 0xd0, 0xef, 0x94, 0x34, 0xff, 0xff, 0xf7, 0x89, 0xff, 0xff, 0xea, 0x75, 0xff, 0xff, 0xe9, 0x6e, 0xff, 0xff, 0xf0, 0x73, 0xff, 0xff, 0xf3, 0x7b, 0xff, 0xff, 0xf4, 0x80, 0xff, 0xff, 0xf5, 0x82, 0xff, 0xff, 0xf4, 0x87, 0xff, 0xff, 0xf4, 0x87, 0xff, 0xff, 0xf5, 0x82, 0xff, 0xff, 0xf4, 0x80, 0xff, 0xff, 0xf3, 0x7c, 0xff, 0xff, 0xef, 0x79, 0xff, 0xff, 0xea, 0x6b, 0xff, 0xff, 0xe7, 0x6a, 0xff, 0xff, 0xf5, 0x85, 0xff, 0xf8, 0xb4, 0x51, 0xff, 0x94, 0x2e, 0x02, 0xed, 0x77, 0x4f, 0x15, 0x42, 0x7a, 0x5f, 0x1d, 0x00, 0x7a, 0x5f, 0x1d, 0x00, 0x7a, 0x5f, 0x1d, 0x00, 0x7a, 0x5f, 0x1d, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x7a, 0x5f, 0x1d, 0x00, 0x7a, 0x5f, 0x1d, 0x00, 0x7a, 0x5f, 0x1d, 0x00, 0x7a, 0x5f, 0x1d, 0x00, 0x7a, 0x5f, 0x1d, 0x00, 0x79, 0x5b, 0x1a, 0x16, 0x77, 0x2f, 0x09, 0xb3, 0xe8, 0x82, 0x2c, 0xff, 0xff, 0xee, 0x9b, 0xff, 0xff, 0xff, 0xa9, 0xff, 0xff, 0xff, 0x90, 0xff, 0xff, 0xfb, 0x85, 0xff, 0xff, 0xf7, 0x8c, 0xff, 0xfe, 0xf6, 0x94, 0xff, 0xfd, 0xf5, 0x98, 0xff, 0xfd, 0xf5, 0x98, 0xff, 0xfe, 0xf6, 0x94, 0xff, 0xff, 0xf7, 0x8e, 0xff, 0xff, 0xfa, 0x85, 0xff, 0xff, 0xfd, 0x8a, 0xff, 0xff, 0xff, 0xa2, 0xff, 0xff, 0xfb, 0xa5, 0xff, 0xef, 0x98, 0x3f, 0xff, 0x7c, 0x28, 0x05, 0xd4, 0x79, 0x54, 0x17, 0x33, 0x7a, 0x5f, 0x1d, 0x00, 0x7a, 0x5f, 0x1d, 0x00, 0x7a, 0x5f, 0x1d, 0x00, 0x7a, 0x5f, 0x1d, 0x00, 0x7a, 0x5f, 0x1d, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x7a, 0x5f, 0x1d, 0x00, 0x7a, 0x5f, 0x1d, 0x00, 0x7a, 0x5f, 0x1d, 0x00, 0x7a, 0x5f, 0x1d, 0x00, 0x7a, 0x5f, 0x1d, 0x00, 0x7a, 0x5f, 0x1d, 0x00, 0x7a, 0x5f, 0x1d, 0x01, 0x75, 0x39, 0x0d, 0x8c, 0xb8, 0x40, 0x01, 0xf8, 0xf1, 0xa1, 0x52, 0xff, 0xff, 0xe9, 0xaa, 0xff, 0xff, 0xff, 0xc8, 0xff, 0xff, 0xff, 0xc4, 0xff, 0xff, 0xff, 0xba, 0xff, 0xff, 0xff, 0xb2, 0xff, 0xff, 0xff, 0xb1, 0xff, 0xff, 0xff, 0xb7, 0xff, 0xff, 0xff, 0xc1, 0xff, 0xff, 0xff, 0xc8, 0xff, 0xff, 0xf4, 0xb4, 0xff, 0xf7, 0xb7, 0x6a, 0xff, 0xd7, 0x56, 0x04, 0xff, 0x75, 0x34, 0x0a, 0xa3, 0x79, 0x5b, 0x1b, 0x10, 0x7a, 0x5f, 0x1d, 0x00, 0x7a, 0x5f, 0x1d, 0x00, 0x7a, 0x5f, 0x1d, 0x00, 0x7a, 0x5f, 0x1d, 0x00, 0x7a, 0x5f, 0x1d, 0x00, 0x7a, 0x5f, 0x1d, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x7a, 0x5f, 0x1d, 0x00, 0x7a, 0x5f, 0x1d, 0x00, 0x7a, 0x5f, 0x1d, 0x00, 0x7a, 0x5f, 0x1d, 0x00, 0x7a, 0x5f, 0x1d, 0x00, 0x7a, 0x5f, 0x1d, 0x00, 0x7a, 0x5f, 0x1d, 0x00, 0x7a, 0x5f, 0x1d, 0x00, 0x79, 0x52, 0x18, 0x2f, 0x76, 0x36, 0x0c, 0x97, 0x97, 0x38, 0x03, 0xe4, 0xde, 0x70, 0x20, 0xff, 0xef, 0xa3, 0x5b, 0xff, 0xf7, 0xc2, 0x85, 0xff, 0xfb, 0xd6, 0x9f, 0xff, 0xfb, 0xd9, 0xa1, 0xff, 0xf9, 0xc8, 0x8d, 0xff, 0xf3, 0xad, 0x68, 0xff, 0xe4, 0x7d, 0x2f, 0xff, 0xb3, 0x43, 0x02, 0xf1, 0x78, 0x31, 0x09, 0xae, 0x78, 0x4d, 0x15, 0x46, 0x7a, 0x5f, 0x1d, 0x00, 0x7a, 0x5f, 0x1d, 0x00, 0x7a, 0x5f, 0x1d, 0x00, 0x7a, 0x5f, 0x1d, 0x00, 0x7a, 0x5f, 0x1d, 0x00, 0x7a, 0x5f, 0x1d, 0x00, 0x7a, 0x5f, 0x1d, 0x00, 0x7a, 0x5f, 0x1d, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x7a, 0x5f, 0x1d, 0x00, 0x7a, 0x5f, 0x1d, 0x00, 0x7a, 0x5f, 0x1d, 0x00, 0x7a, 0x5f, 0x1d, 0x00, 0x7a, 0x5f, 0x1d, 0x00, 0x7a, 0x5f, 0x1d, 0x00, 0x7a, 0x5f, 0x1d, 0x00, 0x7a, 0x5f, 0x1d, 0x00, 0x7a, 0x5f, 0x1d, 0x00, 0x7a, 0x5f, 0x1d, 0x00, 0x79, 0x5b, 0x1b, 0x11, 0x76, 0x4c, 0x15, 0x47, 0x70, 0x3b, 0x0f, 0x7b, 0x78, 0x35, 0x0a, 0xa3, 0x7e, 0x31, 0x08, 0xb7, 0x7e, 0x31, 0x08, 0xb7, 0x7b, 0x34, 0x0a, 0xab, 0x74, 0x3a, 0x0e, 0x85, 0x75, 0x47, 0x13, 0x55, 0x79, 0x58, 0x1a, 0x1e, 0x7a, 0x5f, 0x1d, 0x00, 0x7a, 0x5f, 0x1d, 0x00, 0x7a, 0x5f, 0x1d, 0x00, 0x7a, 0x5f, 0x1d, 0x00, 0x7a, 0x5f, 0x1d, 0x00, 0x7a, 0x5f, 0x1d, 0x00, 0x7a, 0x5f, 0x1d, 0x00, 0x7a, 0x5f, 0x1d, 0x00, 0x7a, 0x5f, 0x1d, 0x00, 0x7a, 0x5f, 0x1d, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }; int init_bitmap_suite(void) { return 0; } int clean_bitmap_suite(void) { return 0; } int add_bitmap_suite(void) { add_test_suite(bitmap); add_test_function(bitmap); return 0; } void test_bitmap(void) { struct btest { uint8 decompressed_16x1x8[16 * 1 * 1]; uint8 decompressed_32x32x8[32 * 32 * 1]; uint8 decompressed_16x1x16[16 * 1 * 2]; uint8 decompressed_32x32x16[32 * 32 * 2]; uint8 decompressed_16x1x24[16 * 1 * 3]; uint8 decompressed_32x32x24[32 * 32 * 3]; uint8 decompressed_16x1x32[16 * 1 * 4]; uint8 decompressed_32x32x32[32 * 32 * 4]; }; struct btest* t; int width; int height; int comp_size; int decomp_size; int bpp; t = (struct btest*)malloc(sizeof(struct btest)); width = 16; height = 1; bpp = 8; comp_size = sizeof(compressed_16x1x8); decomp_size = sizeof(decompressed_16x1x8); CU_ASSERT(bitmap_decompress(compressed_16x1x8, t->decompressed_16x1x8, width, height, comp_size, bpp, bpp) == true); CU_ASSERT(memcmp(t->decompressed_16x1x8, decompressed_16x1x8, decomp_size) == 0); width = 32; height = 32; bpp = 8; comp_size = sizeof(compressed_32x32x8); decomp_size = sizeof(decompressed_32x32x8); CU_ASSERT(bitmap_decompress(compressed_32x32x8, t->decompressed_32x32x8, width, height, comp_size, bpp, bpp) == true); CU_ASSERT(memcmp(t->decompressed_32x32x8, decompressed_32x32x8, decomp_size) == 0); width = 16; height = 1; bpp = 16; comp_size = sizeof(compressed_16x1x16); decomp_size = sizeof(decompressed_16x1x16); CU_ASSERT(bitmap_decompress(compressed_16x1x16, t->decompressed_16x1x16, width, height, comp_size, bpp, bpp) == true); CU_ASSERT(memcmp(t->decompressed_16x1x16, decompressed_16x1x16, decomp_size) == 0); width = 32; height = 32; bpp = 16; comp_size = sizeof(compressed_32x32x16); decomp_size = sizeof(decompressed_32x32x16); CU_ASSERT(bitmap_decompress(compressed_32x32x16, t->decompressed_32x32x16, width, height, comp_size, bpp, bpp) == true); CU_ASSERT(memcmp(t->decompressed_32x32x16, decompressed_32x32x16, decomp_size) == 0); width = 16; height = 1; bpp = 24; comp_size = sizeof(compressed_16x1x24); decomp_size = sizeof(decompressed_16x1x24); CU_ASSERT(bitmap_decompress(compressed_16x1x24, t->decompressed_16x1x24, width, height, comp_size, bpp, bpp) == true); CU_ASSERT(memcmp(t->decompressed_16x1x24, decompressed_16x1x24, decomp_size) == 0); width = 32; height = 32; bpp = 24; comp_size = sizeof(compressed_32x32x24); decomp_size = sizeof(decompressed_32x32x24); CU_ASSERT(bitmap_decompress(compressed_32x32x24, t->decompressed_32x32x24, width, height, comp_size, bpp, bpp) == true); CU_ASSERT(memcmp(t->decompressed_32x32x24, decompressed_32x32x24, decomp_size) == 0); width = 16; height = 1; bpp = 32; comp_size = sizeof(compressed_16x1x32); decomp_size = sizeof(decompressed_16x1x32); CU_ASSERT(bitmap_decompress(compressed_16x1x32, t->decompressed_16x1x32, width, height, comp_size, bpp, bpp) == true); CU_ASSERT(memcmp(t->decompressed_16x1x32, decompressed_16x1x32, decomp_size) == 0); width = 32; height = 32; bpp = 32; comp_size = sizeof(compressed_32x32x32); decomp_size = sizeof(decompressed_32x32x32); CU_ASSERT(bitmap_decompress(compressed_32x32x32, t->decompressed_32x32x32, width, height, comp_size, bpp, bpp) == true); CU_ASSERT(memcmp(t->decompressed_32x32x32, decompressed_32x32x32, decomp_size) == 0); free(t); } FreeRDP-1.0.2/cunit/test_bitmap.h000066400000000000000000000014671207112532300165530ustar00rootroot00000000000000/** * FreeRDP: A Remote Desktop Protocol Client * Bitmap Unit Tests * * Copyright 2011 Jay Sorg * * 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. */ #include "test_freerdp.h" int init_bitmap_suite(void); int clean_bitmap_suite(void); int add_bitmap_suite(void); void test_bitmap(void); FreeRDP-1.0.2/cunit/test_channels.c000066400000000000000000000050421207112532300170560ustar00rootroot00000000000000/** * FreeRDP: A Remote Desktop Protocol Client * Channel Manager Unit Tests * * Copyright 2011 Vic Lee * * 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. */ #include #include #include #include #include #include #include #include "test_channels.h" int init_chanman_suite(void) { freerdp_channels_global_init(); return 0; } int clean_chanman_suite(void) { freerdp_channels_global_uninit(); return 0; } int add_chanman_suite(void) { add_test_suite(chanman); add_test_function(chanman); return 0; } static int test_rdp_channel_data(freerdp* instance, int chan_id, uint8* data, int data_size) { printf("chan_id %d data_size %d\n", chan_id, data_size); return 0; } void test_chanman(void) { rdpChannels* chan_man; rdpSettings settings = { 0 }; freerdp instance = { 0 }; RDP_EVENT* event; settings.hostname = "testhost"; instance.settings = &settings; instance.SendChannelData = test_rdp_channel_data; chan_man = freerdp_channels_new(); freerdp_channels_load_plugin(chan_man, &settings, "../channels/rdpdbg/rdpdbg.so", NULL); freerdp_channels_pre_connect(chan_man, &instance); freerdp_channels_post_connect(chan_man, &instance); freerdp_channels_data(&instance, 0, "testdata", 8, CHANNEL_FLAG_FIRST | CHANNEL_FLAG_LAST, 8); freerdp_channels_data(&instance, 0, "testdata1", 9, CHANNEL_FLAG_FIRST | CHANNEL_FLAG_LAST, 9); freerdp_channels_data(&instance, 0, "testdata11", 10, CHANNEL_FLAG_FIRST | CHANNEL_FLAG_LAST, 10); freerdp_channels_data(&instance, 0, "testdata111", 11, CHANNEL_FLAG_FIRST | CHANNEL_FLAG_LAST, 11); event = freerdp_event_new(RDP_EVENT_CLASS_DEBUG, 0, NULL, NULL); freerdp_channels_send_event(chan_man, event); while ((event = freerdp_channels_pop_event(chan_man)) == NULL) { freerdp_channels_check_fds(chan_man, &instance); } printf("responded event_type %d\n", event->event_type); freerdp_event_free(event); freerdp_channels_close(chan_man, &instance); freerdp_channels_free(chan_man); } FreeRDP-1.0.2/cunit/test_channels.h000066400000000000000000000014561207112532300170700ustar00rootroot00000000000000/** * FreeRDP: A Remote Desktop Protocol Client * Channel Manager Unit Tests * * Copyright 2011 Vic Lee * * 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. */ #include "test_freerdp.h" int init_chanman_suite(void); int clean_chanman_suite(void); int add_chanman_suite(void); void test_chanman(void); FreeRDP-1.0.2/cunit/test_cliprdr.c000066400000000000000000000201761207112532300167270ustar00rootroot00000000000000/** * FreeRDP: A Remote Desktop Protocol Client * Clipboard Virtual Channel Unit Tests * * Copyright 2011 Vic Lee * * 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. */ #include #include #include #include #include #include #include #include #include #include #include "test_cliprdr.h" int init_cliprdr_suite(void) { freerdp_channels_global_init(); return 0; } int clean_cliprdr_suite(void) { freerdp_channels_global_uninit(); return 0; } int add_cliprdr_suite(void) { add_test_suite(cliprdr); add_test_function(cliprdr); return 0; } static const uint8 test_clip_caps_data[] = { "\x07\x00\x00\x00\x10\x00\x00\x00\x01\x00\x00\x00\x01\x00\x0C\x00" "\x02\x00\x00\x00\x0E\x00\x00\x00" }; static const uint8 test_monitor_ready_data[] = { "\x01\x00\x00\x00\x00\x00\x00\x00" }; static const uint8 test_format_list_data[] = { "\x02\x00\x00\x00\x48\x00\x00\x00\x01\x00\x00\x00\x00\x00\x00\x00" "\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00" "\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x10\xd0\x00\x00" "\x48\x00\x54\x00\x4D\x00\x4C\x00\x20\x00\x46\x00\x6F\x00\x72\x00" "\x6D\x00\x61\x00\x74\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00" }; static const uint8 test_format_list_response_data[] = { "\x03\x00\x01\x00\x00\x00\x00\x00" }; static const uint8 test_data_request_data[] = { "\x04\x00\x00\x00\x04\x00\x00\x00\x01\x00\x00\x00" }; static const uint8 test_data_response_data[] = { "\x05\x00\x01\x00\x18\x00\x00\x00\x68\x00\x65\x00\x6C\x00\x6C\x00" "\x6F\x00\x20\x00\x77\x00\x6F\x00\x72\x00\x6c\x00\x64\x00\x00\x00" }; static int test_rdp_channel_data(freerdp* instance, int chan_id, uint8* data, int data_size) { printf("chan_id %d data_size %d\n", chan_id, data_size); freerdp_hexdump(data, data_size); return 0; } static int event_processed; static void event_process_callback(RDP_EVENT* event) { printf("Event %d processed.\n", event->event_type); event_processed = 1; } void test_cliprdr(void) { int i; rdpChannels* channels; rdpSettings settings = { 0 }; freerdp instance = { 0 }; RDP_EVENT* event; RDP_CB_FORMAT_LIST_EVENT* format_list_event; RDP_CB_DATA_REQUEST_EVENT* data_request_event; RDP_CB_DATA_RESPONSE_EVENT* data_response_event; settings.hostname = "testhost"; instance.settings = &settings; instance.SendChannelData = test_rdp_channel_data; channels = freerdp_channels_new(); freerdp_channels_load_plugin(channels, &settings, "../channels/cliprdr/cliprdr.so", NULL); freerdp_channels_pre_connect(channels, &instance); freerdp_channels_post_connect(channels, &instance); /* server sends cliprdr capabilities and monitor ready PDU */ freerdp_channels_data(&instance, 0, (char*)test_clip_caps_data, sizeof(test_clip_caps_data) - 1, CHANNEL_FLAG_FIRST | CHANNEL_FLAG_LAST, sizeof(test_clip_caps_data) - 1); freerdp_channels_data(&instance, 0, (char*)test_monitor_ready_data, sizeof(test_monitor_ready_data) - 1, CHANNEL_FLAG_FIRST | CHANNEL_FLAG_LAST, sizeof(test_monitor_ready_data) - 1); /* cliprdr sends clipboard_sync event to UI */ while ((event = freerdp_channels_pop_event(channels)) == NULL) { freerdp_channels_check_fds(channels, &instance); } printf("Got event %d\n", event->event_type); CU_ASSERT(event->event_type == RDP_EVENT_TYPE_CB_MONITOR_READY); freerdp_event_free(event); /* UI sends format_list event to cliprdr */ event = freerdp_event_new(RDP_EVENT_CLASS_CLIPRDR, RDP_EVENT_TYPE_CB_FORMAT_LIST, event_process_callback, NULL); format_list_event = (RDP_CB_FORMAT_LIST_EVENT*) event; format_list_event->num_formats = 2; format_list_event->formats = (uint32*) xmalloc(sizeof(uint32) * 2); format_list_event->formats[0] = CB_FORMAT_TEXT; format_list_event->formats[1] = CB_FORMAT_HTML; event_processed = 0; freerdp_channels_send_event(channels, event); /* cliprdr sends format list PDU to server */ while (!event_processed) { freerdp_channels_check_fds(channels, &instance); } /* server sends format list response PDU to cliprdr */ freerdp_channels_data(&instance, 0, (char*)test_format_list_response_data, sizeof(test_format_list_response_data) - 1, CHANNEL_FLAG_FIRST | CHANNEL_FLAG_LAST, sizeof(test_format_list_response_data) - 1); /* server sends format list PDU to cliprdr */ freerdp_channels_data(&instance, 0, (char*)test_format_list_data, sizeof(test_format_list_data) - 1, CHANNEL_FLAG_FIRST | CHANNEL_FLAG_LAST, sizeof(test_format_list_data) - 1); /* cliprdr sends format_list event to UI */ while ((event = freerdp_channels_pop_event(channels)) == NULL) { freerdp_channels_check_fds(channels, &instance); } printf("Got event %d\n", event->event_type); CU_ASSERT(event->event_type == RDP_EVENT_TYPE_CB_FORMAT_LIST); if (event->event_type == RDP_EVENT_TYPE_CB_FORMAT_LIST) { format_list_event = (RDP_CB_FORMAT_LIST_EVENT*)event; for (i = 0; i < format_list_event->num_formats; i++) printf("Format: 0x%X\n", format_list_event->formats[i]); } freerdp_event_free(event); /* server sends data request PDU to cliprdr */ freerdp_channels_data(&instance, 0, (char*)test_data_request_data, sizeof(test_data_request_data) - 1, CHANNEL_FLAG_FIRST | CHANNEL_FLAG_LAST, sizeof(test_data_request_data) - 1); /* cliprdr sends data request event to UI */ while ((event = freerdp_channels_pop_event(channels)) == NULL) { freerdp_channels_check_fds(channels, &instance); } printf("Got event %d\n", event->event_type); CU_ASSERT(event->event_type == RDP_EVENT_TYPE_CB_DATA_REQUEST); if (event->event_type == RDP_EVENT_TYPE_CB_DATA_REQUEST) { data_request_event = (RDP_CB_DATA_REQUEST_EVENT*)event; printf("Requested format: 0x%X\n", data_request_event->format); } freerdp_event_free(event); /* UI sends data response event to cliprdr */ event = freerdp_event_new(RDP_EVENT_CLASS_CLIPRDR, RDP_EVENT_TYPE_CB_DATA_RESPONSE, event_process_callback, NULL); data_response_event = (RDP_CB_DATA_RESPONSE_EVENT*)event; data_response_event->data = (uint8*)xmalloc(6); strcpy((char*)data_response_event->data, "hello"); data_response_event->size = 6; event_processed = 0; freerdp_channels_send_event(channels, event); /* cliprdr sends data response PDU to server */ while (!event_processed) { freerdp_channels_check_fds(channels, &instance); } /* UI sends data request event to cliprdr */ event = freerdp_event_new(RDP_EVENT_CLASS_CLIPRDR, RDP_EVENT_TYPE_CB_DATA_REQUEST, event_process_callback, NULL); data_request_event = (RDP_CB_DATA_REQUEST_EVENT*)event; data_request_event->format = CB_FORMAT_UNICODETEXT; event_processed = 0; freerdp_channels_send_event(channels, event); /* cliprdr sends data request PDU to server */ while (!event_processed) { freerdp_channels_check_fds(channels, &instance); } /* server sends data response PDU to cliprdr */ freerdp_channels_data(&instance, 0, (char*)test_data_response_data, sizeof(test_data_response_data) - 1, CHANNEL_FLAG_FIRST | CHANNEL_FLAG_LAST, sizeof(test_data_response_data) - 1); /* cliprdr sends data response event to UI */ while ((event = freerdp_channels_pop_event(channels)) == NULL) { freerdp_channels_check_fds(channels, &instance); } printf("Got event %d\n", event->event_type); CU_ASSERT(event->event_type == RDP_EVENT_TYPE_CB_DATA_RESPONSE); if (event->event_type == RDP_EVENT_TYPE_CB_DATA_RESPONSE) { data_response_event = (RDP_CB_DATA_RESPONSE_EVENT*)event; printf("Data response size: %d\n", data_response_event->size); freerdp_hexdump(data_response_event->data, data_response_event->size); } freerdp_event_free(event); freerdp_channels_close(channels, &instance); freerdp_channels_free(channels); } FreeRDP-1.0.2/cunit/test_cliprdr.h000066400000000000000000000014701207112532300167300ustar00rootroot00000000000000/** * FreeRDP: A Remote Desktop Protocol Client * Clipboard Virtual Channel Unit Tests * * Copyright 2011 Vic Lee * * 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. */ #include "test_freerdp.h" int init_cliprdr_suite(void); int clean_cliprdr_suite(void); int add_cliprdr_suite(void); void test_cliprdr(void); FreeRDP-1.0.2/cunit/test_color.c000066400000000000000000000056341207112532300164100ustar00rootroot00000000000000/** * FreeRDP: A Remote Desktop Protocol Client * Color Conversion Unit Tests * * Copyright 2010 Marc-Andre Moreau * * 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. */ #include #include #include #include #include #include "test_color.h" int init_color_suite(void) { return 0; } int clean_color_suite(void) { return 0; } int add_color_suite(void) { add_test_suite(color); add_test_function(color_GetRGB32); add_test_function(color_GetBGR32); add_test_function(color_GetRGB_565); add_test_function(color_GetRGB16); add_test_function(color_GetBGR_565); add_test_function(color_GetBGR16); return 0; } /* GDI Color Space Conversions: http://msdn.microsoft.com/en-us/library/ff566496(VS.85).aspx */ void test_color_GetRGB32(void) { int r, g, b; uint32 rgb32 = 0x00AABBCC; GetRGB32(r, g, b, rgb32); CU_ASSERT(r == 0xAA); CU_ASSERT(g == 0xBB); CU_ASSERT(b == 0xCC); } void test_color_GetBGR32(void) { int r, g, b; uint32 bgr32 = 0x00CCBBAA; GetBGR32(r, g, b, bgr32); CU_ASSERT(r == 0xAA); CU_ASSERT(g == 0xBB); CU_ASSERT(b == 0xCC); } void test_color_GetRGB_565(void) { /* R: 0x15, 10101 G: 0x33, 110011 B: 0x1D, 11101 0xAE7D, 10101110 01111101 */ int r, g, b; uint16 rgb16 = 0xAE7D; GetRGB_565(r, g, b, rgb16); CU_ASSERT(r == 0x15); CU_ASSERT(g == 0x33); CU_ASSERT(b == 0x1D); } void test_color_GetRGB16(void) { /* R: 0x15 -> 0xAD, 10101 -> 10101101 G: 0x33 -> 0xCF, 110011 -> 11001111 B: 0x1D -> 0xEF, 11101 -> 11101101 0xAE7D -> 0xADCFEF 10101110 01111101 -> 10101101 11001111 11101101 */ int r, g, b; uint16 rgb16 = 0xAE7D; GetRGB16(r, g, b, rgb16); CU_ASSERT(r == 0xAD); CU_ASSERT(g == 0xCF); CU_ASSERT(b == 0xEF); } void test_color_GetBGR_565(void) { /* B: 0x1D, 11101 G: 0x33, 110011 R: 0x15, 10101 0xEE75, 11101110 01110101 */ int r, g, b; uint16 bgr16 = 0xEE75; GetBGR_565(r, g, b, bgr16); CU_ASSERT(r == 0x15); CU_ASSERT(g == 0x33); CU_ASSERT(b == 0x1D); } void test_color_GetBGR16(void) { /* B: 0x1D -> 0xEF, 11101 -> 11101101 G: 0x33 -> 0xCF, 110011 -> 11001111 R: 0x15 -> 0xAD, 10101 -> 10101101 0xEE75 -> 0xADCFEF 11101110 01110101 -> 10101101 11001111 11101101 */ int r, g, b; uint16 bgr16 = 0xEE75; GetBGR16(r, g, b, bgr16); CU_ASSERT(r == 0xAD); CU_ASSERT(g == 0xCF); CU_ASSERT(b == 0xEF); } FreeRDP-1.0.2/cunit/test_color.h000066400000000000000000000017731207112532300164150ustar00rootroot00000000000000/** * FreeRDP: A Remote Desktop Protocol Client * Color Conversion Unit Tests * * Copyright 2010 Marc-Andre Moreau * * 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. */ #include "test_freerdp.h" int init_color_suite(void); int clean_color_suite(void); int add_color_suite(void); void test_color_GetRGB32(void); void test_color_GetBGR32(void); void test_color_GetRGB_565(void); void test_color_GetRGB16(void); void test_color_GetBGR_565(void); void test_color_GetBGR16(void); FreeRDP-1.0.2/cunit/test_drdynvc.c000066400000000000000000000047471207112532300167470ustar00rootroot00000000000000/** * FreeRDP: A Remote Desktop Protocol Client * Dynamic Virtual Channel Unit Tests * * Copyright 2011 Vic Lee * * 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. */ #include #include #include #include #include #include #include #include #include #include "test_drdynvc.h" int init_drdynvc_suite(void) { freerdp_channels_global_init(); return 0; } int clean_drdynvc_suite(void) { freerdp_channels_global_uninit(); return 0; } int add_drdynvc_suite(void) { add_test_suite(drdynvc); add_test_function(drdynvc); return 0; } static const uint8 test_capability_request_data[] = { "\x58\x00\x02\x00\x33\x33\x11\x11\x3D\x0A\xA7\x04" }; static int data_received = 0; static int test_rdp_channel_data(freerdp* instance, int chan_id, uint8* data, int data_size) { printf("chan_id %d data_size %d\n", chan_id, data_size); freerdp_hexdump(data, data_size); data_received = 1; return 0; } void test_drdynvc(void) { rdpChannels* chan_man; rdpSettings settings = { 0 }; freerdp instance = { 0 }; settings.hostname = "testhost"; instance.settings = &settings; instance.SendChannelData = test_rdp_channel_data; chan_man = freerdp_channels_new(); freerdp_channels_load_plugin(chan_man, &settings, "../channels/drdynvc/drdynvc.so", NULL); freerdp_channels_pre_connect(chan_man, &instance); freerdp_channels_post_connect(chan_man, &instance); /* server sends capability request PDU */ freerdp_channels_data(&instance, 0, (char*)test_capability_request_data, sizeof(test_capability_request_data) - 1, CHANNEL_FLAG_FIRST | CHANNEL_FLAG_LAST, sizeof(test_capability_request_data) - 1); /* drdynvc sends capability response PDU to server */ data_received = 0; while (!data_received) { freerdp_channels_check_fds(chan_man, &instance); } freerdp_channels_close(chan_man, &instance); freerdp_channels_free(chan_man); } FreeRDP-1.0.2/cunit/test_drdynvc.h000066400000000000000000000014661207112532300167470ustar00rootroot00000000000000/** * FreeRDP: A Remote Desktop Protocol Client * Dynamic Virtual Channel Unit Tests * * Copyright 2011 Vic Lee * * 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. */ #include "test_freerdp.h" int init_drdynvc_suite(void); int clean_drdynvc_suite(void); int add_drdynvc_suite(void); void test_drdynvc(void); FreeRDP-1.0.2/cunit/test_freerdp.c000066400000000000000000000112221207112532300167070ustar00rootroot00000000000000/** * FreeRDP: A Remote Desktop Protocol Client * FreeRDP Unit Tests * * Copyright 2010 Marc-Andre Moreau * * 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. */ #include #include "test_per.h" #include "test_ber.h" #include "test_gcc.h" #include "test_mcs.h" #include "test_color.h" #include "test_bitmap.h" #include "test_libgdi.h" #include "test_list.h" #include "test_stream.h" #include "test_utils.h" #include "test_orders.h" #include "test_license.h" #include "test_channels.h" #include "test_cliprdr.h" #include "test_drdynvc.h" #include "test_librfx.h" #include "test_freerdp.h" #include "test_rail.h" #include "test_pcap.h" #include "test_mppc.h" void dump_data(unsigned char * p, int len, int width, char* name) { unsigned char *line = p; int i, thisline, offset = 0; printf("\n%s[%d][%d]:\n", name, len / width, width); while (offset < len) { printf("%04x ", offset); thisline = len - offset; if (thisline > width) thisline = width; for (i = 0; i < thisline; i++) printf("%02x ", line[i]); for (; i < width; i++) printf(" "); printf("\n"); offset += thisline; line += thisline; } printf("\n"); } void assert_stream(STREAM* s, uint8* data, int length, const char* func, int line) { int i; int actual_length; uint8* actual_data; actual_data = s->data; actual_length = stream_get_length(s); if (actual_length != length) { printf("\n %s (%d): length mismatch, actual:%d, expected:%d\n", func, line, actual_length, length); printf("\nActual:\n"); freerdp_hexdump(actual_data, actual_length); printf("Expected:\n"); freerdp_hexdump(data, length); CU_FAIL("assert_stream, length mismatch"); return; } for (i = 0; i < length; i++) { if (actual_data[i] != data[i]) { printf("\n %s (%d): buffer mismatch:\n", func, line); printf("\nActual:\n"); freerdp_hexdump(actual_data, length); printf("Expected:\n"); freerdp_hexdump(data, length); CU_FAIL("assert_stream, buffer mismatch"); return; } } } int main(int argc, char* argv[]) { int index = 1; int *pindex = &index; int ret = 0; if (CU_initialize_registry() != CUE_SUCCESS) return CU_get_error(); if (argc < *pindex + 1) { add_per_suite(); add_ber_suite(); add_gcc_suite(); add_mcs_suite(); add_color_suite(); add_bitmap_suite(); add_libgdi_suite(); add_list_suite(); add_orders_suite(); add_license_suite(); add_stream_suite(); add_mppc_suite(); } else { while (*pindex < argc) { if (strcmp("rail", argv[*pindex]) == 0) { add_rail_suite(); } if (strcmp("color", argv[*pindex]) == 0) { add_color_suite(); } if (strcmp("bitmap", argv[*pindex]) == 0) { add_bitmap_suite(); } else if (strcmp("libgdi", argv[*pindex]) == 0) { add_libgdi_suite(); } else if (strcmp("list", argv[*pindex]) == 0) { add_list_suite(); } else if (strcmp("orders", argv[*pindex]) == 0) { add_orders_suite(); } else if (strcmp("license", argv[*pindex]) == 0) { add_license_suite(); } else if (strcmp("stream", argv[*pindex]) == 0) { add_stream_suite(); } else if (strcmp("utils", argv[*pindex]) == 0) { add_utils_suite(); } else if (strcmp("chanman", argv[*pindex]) == 0) { add_chanman_suite(); } else if (strcmp("cliprdr", argv[*pindex]) == 0) { add_cliprdr_suite(); } else if (strcmp("drdynvc", argv[*pindex]) == 0) { add_drdynvc_suite(); } else if (strcmp("librfx", argv[*pindex]) == 0) { add_librfx_suite(); } else if (strcmp("per", argv[*pindex]) == 0) { add_per_suite(); } else if (strcmp("pcap", argv[*pindex]) == 0) { add_pcap_suite(); } else if (strcmp("ber", argv[*pindex]) == 0) { add_ber_suite(); } else if (strcmp("gcc", argv[*pindex]) == 0) { add_gcc_suite(); } else if (strcmp("mcs", argv[*pindex]) == 0) { add_mcs_suite(); } else if (strcmp("mppc", argv[*pindex]) == 0) { add_mppc_suite(); } *pindex = *pindex + 1; } } CU_basic_set_mode(CU_BRM_VERBOSE); CU_basic_run_tests(); ret = CU_get_number_of_failure_records(); CU_cleanup_registry(); return ret; } FreeRDP-1.0.2/cunit/test_freerdp.h000066400000000000000000000027201207112532300167170ustar00rootroot00000000000000/** * FreeRDP: A Remote Desktop Protocol Client * FreeRDP Unit Tests * * Copyright 2010 Marc-Andre Moreau * * 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. */ #include #include #include #include #include #include #include #define add_test_suite(name) \ CU_pSuite pSuite; \ pSuite = CU_add_suite(#name, init_##name##_suite, clean_##name##_suite); \ if (pSuite == NULL) { \ CU_cleanup_registry(); return CU_get_error(); \ } #define add_test_function(name) \ if (CU_add_test(pSuite, #name, test_##name) == NULL) { \ CU_cleanup_registry(); return CU_get_error(); \ } void dump_data(unsigned char * p, int len, int width, char* name); void assert_stream(STREAM* s, uint8* data, int length, const char* func, int line); #define ASSERT_STREAM(_s, _data, _length) assert_stream(_s, _data, _length, __FUNCTION__, __LINE__) FreeRDP-1.0.2/cunit/test_gcc.c000066400000000000000000000172131207112532300160220ustar00rootroot00000000000000/** * FreeRDP: A Remote Desktop Protocol Client * T.124 Generic Conference Control (GCC) Unit Tests * * Copyright 2011 Marc-Andre Moreau * * 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. */ #include "gcc.h" #include #include #include #include "test_gcc.h" int init_gcc_suite(void) { return 0; } int clean_gcc_suite(void) { return 0; } int add_gcc_suite(void) { add_test_suite(gcc); add_test_function(gcc_write_conference_create_request); add_test_function(gcc_write_client_core_data); add_test_function(gcc_write_client_security_data); add_test_function(gcc_write_client_cluster_data); add_test_function(gcc_write_client_network_data); return 0; } uint8 gcc_user_data[284] = "\x01\xc0\xd8\x00\x04\x00\x08\x00\x00\x05\x00\x04\x01\xCA\x03\xAA" "\x09\x04\x00\x00\xCE\x0E\x00\x00\x45\x00\x4c\x00\x54\x00\x4f\x00" "\x4e\x00\x53\x00\x2d\x00\x44\x00\x45\x00\x56\x00\x32\x00\x00\x00" "\x00\x00\x00\x00\x00\x00\x00\x00\x04\x00\x00\x00\x00\x00\x00\x00" "\x0c\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00" "\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00" "\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00" "\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00" "\x00\x00\x00\x00\x01\xCA\x01\x00\x00\x00\x00\x00\x18\x00\x07\x00" "\x01\x00\x36\x00\x39\x00\x37\x00\x31\x00\x32\x00\x2d\x00\x37\x00" "\x38\x00\x33\x00\x2d\x00\x30\x00\x33\x00\x35\x00\x37\x00\x39\x00" "\x37\x00\x34\x00\x2d\x00\x34\x00\x32\x00\x37\x00\x31\x00\x34\x00" "\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00" "\x00\x00\x00\x00\x00\x00\x00\x00\x04\xC0\x0C\x00\x0D\x00\x00\x00" "\x00\x00\x00\x00\x02\xC0\x0C\x00\x1B\x00\x00\x00\x00\x00\x00\x00" "\x03\xC0\x2C\x00\x03\x00\x00\x00\x72\x64\x70\x64\x72\x00\x00\x00" "\x00\x00\x80\x80\x63\x6c\x69\x70\x72\x64\x72\x00\x00\x00\xA0\xC0" "\x72\x64\x70\x73\x6e\x64\x00\x00\x00\x00\x00\xc0"; uint8 gcc_conference_create_request_expected[307] = "\x00\x05\x00\x14\x7C\x00\x01\x81\x2A\x00\x08\x00\x10\x00\x01\xC0" "\x00\x44\x75\x63\x61\x81\x1c\x01\xc0\xd8\x00\x04\x00\x08\x00\x00" "\x05\x00\x04\x01\xCA\x03\xAA\x09\x04\x00\x00\xCE\x0E\x00\x00\x45" "\x00\x4c\x00\x54\x00\x4f\x00\x4e\x00\x53\x00\x2d\x00\x44\x00\x45" "\x00\x56\x00\x32\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x04" "\x00\x00\x00\x00\x00\x00\x00\x0c\x00\x00\x00\x00\x00\x00\x00\x00" "\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00" "\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00" "\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00" "\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x01\xCA\x01\x00\x00" "\x00\x00\x00\x18\x00\x07\x00\x01\x00\x36\x00\x39\x00\x37\x00\x31" "\x00\x32\x00\x2d\x00\x37\x00\x38\x00\x33\x00\x2d\x00\x30\x00\x33" "\x00\x35\x00\x37\x00\x39\x00\x37\x00\x34\x00\x2d\x00\x34\x00\x32" "\x00\x37\x00\x31\x00\x34\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00" "\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x04" "\xC0\x0C\x00\x0D\x00\x00\x00\x00\x00\x00\x00\x02\xC0\x0C\x00\x1B" "\x00\x00\x00\x00\x00\x00\x00\x03\xC0\x2C\x00\x03\x00\x00\x00\x72" "\x64\x70\x64\x72\x00\x00\x00\x00\x00\x80\x80\x63\x6c\x69\x70\x72" "\x64\x72\x00\x00\x00\xA0\xC0\x72\x64\x70\x73\x6e\x64\x00\x00\x00" "\x00\x00\xc0"; void test_gcc_write_conference_create_request(void) { STREAM* s; STREAM user_data; user_data.data = gcc_user_data; user_data.size = sizeof(gcc_user_data); user_data.p = user_data.data + user_data.size; s = stream_new(sizeof(gcc_conference_create_request_expected)); gcc_write_conference_create_request(s, &user_data); ASSERT_STREAM(s, (uint8*) gcc_conference_create_request_expected, sizeof(gcc_conference_create_request_expected)); } uint8 gcc_client_core_data_expected[216] = "\x01\xc0\xd8\x00\x04\x00\x08\x00\x00\x05\x00\x04\x01\xCA\x03\xAA" "\x09\x04\x00\x00\xCE\x0E\x00\x00\x45\x00\x4c\x00\x54\x00\x4f\x00" "\x4e\x00\x53\x00\x2d\x00\x44\x00\x45\x00\x56\x00\x32\x00\x00\x00" "\x00\x00\x00\x00\x00\x00\x00\x00\x04\x00\x00\x00\x00\x00\x00\x00" "\x0c\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00" "\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00" "\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00" "\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00" "\x00\x00\x00\x00\x01\xCA\x01\x00\x00\x00\x00\x00\x18\x00\x07\x00" "\x01\x00\x36\x00\x39\x00\x37\x00\x31\x00\x32\x00\x2d\x00\x37\x00" "\x38\x00\x33\x00\x2d\x00\x30\x00\x33\x00\x35\x00\x37\x00\x39\x00" "\x37\x00\x34\x00\x2d\x00\x34\x00\x32\x00\x37\x00\x31\x00\x34\x00" "\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00" "\x00\x00\x00\x00\x00\x00\x00\x00"; void test_gcc_write_client_core_data(void) { STREAM* s; rdpSettings* settings; s = stream_new(512); settings = settings_new(NULL); settings->width = 1280; settings->height = 1024; settings->rdp_version = 5; settings->color_depth = 24; settings->kbd_layout = 0x409; settings->kbd_type = 0x04; settings->kbd_fn_keys = 12; settings->client_build = 3790; strcpy(settings->client_hostname, "ELTONS-DEV2"); strcpy(settings->client_product_id, "69712-783-0357974-42714"); gcc_write_client_core_data(s, settings); ASSERT_STREAM(s, (uint8*) gcc_client_core_data_expected, sizeof(gcc_client_core_data_expected)); } uint8 gcc_client_security_data_expected[12] = "\x02\xC0\x0C\x00\x1B\x00\x00\x00\x00\x00\x00\x00"; void test_gcc_write_client_security_data(void) { STREAM* s; rdpSettings* settings; s = stream_new(12); settings = settings_new(NULL); settings->encryption = 1; /* turn on encryption */ settings->encryption_method = ENCRYPTION_METHOD_40BIT | ENCRYPTION_METHOD_56BIT | ENCRYPTION_METHOD_128BIT | ENCRYPTION_METHOD_FIPS; gcc_write_client_security_data(s, settings); ASSERT_STREAM(s, (uint8*) gcc_client_security_data_expected, sizeof(gcc_client_security_data_expected)); } uint8 gcc_client_cluster_data_expected[12] = "\x04\xC0\x0C\x00\x0D\x00\x00\x00\x00\x00\x00\x00"; void test_gcc_write_client_cluster_data(void) { STREAM* s; rdpSettings* settings; s = stream_new(12); settings = settings_new(NULL); gcc_write_client_cluster_data(s, settings); ASSERT_STREAM(s, (uint8*) gcc_client_cluster_data_expected, sizeof(gcc_client_cluster_data_expected)); } uint8 gcc_client_network_data_expected[44] = "\x03\xC0\x2C\x00\x03\x00\x00\x00\x72\x64\x70\x64\x72\x00\x00\x00" "\x00\x00\x80\x80\x63\x6c\x69\x70\x72\x64\x72\x00\x00\x00\xA0\xC0" "\x72\x64\x70\x73\x6e\x64\x00\x00\x00\x00\x00\xc0"; void test_gcc_write_client_network_data(void) { STREAM* s; rdpSettings* settings; s = stream_new(44); settings = settings_new(NULL); settings->num_channels = 3; memset(settings->channels, 0, sizeof(rdpChannel) * settings->num_channels); strcpy(settings->channels[0].name, "rdpdr"); settings->channels[0].options = 0x80800000; strcpy(settings->channels[1].name, "cliprdr"); settings->channels[1].options = 0xc0A00000; strcpy(settings->channels[2].name, "rdpsnd"); settings->channels[2].options = 0xc0000000; gcc_write_client_network_data(s, settings); ASSERT_STREAM(s, (uint8*) gcc_client_network_data_expected, sizeof(gcc_client_network_data_expected)); } FreeRDP-1.0.2/cunit/test_gcc.h000066400000000000000000000020661207112532300160270ustar00rootroot00000000000000/** * FreeRDP: A Remote Desktop Protocol Client * T.124 Generic Conference Control (GCC) Unit Tests * * Copyright 2011 Marc-Andre Moreau * * 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. */ #include "test_freerdp.h" int init_gcc_suite(void); int clean_gcc_suite(void); int add_gcc_suite(void); void test_gcc_write_conference_create_request(void); void test_gcc_write_client_core_data(void); void test_gcc_write_client_security_data(void); void test_gcc_write_client_cluster_data(void); void test_gcc_write_client_network_data(void); FreeRDP-1.0.2/cunit/test_libgdi.c000066400000000000000000003634751207112532300165360ustar00rootroot00000000000000/** * FreeRDP: A Remote Desktop Protocol Client * GDI Unit Tests * * Copyright 2010 Marc-Andre Moreau * * 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. */ #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include "test_libgdi.h" int init_libgdi_suite(void) { return 0; } int clean_libgdi_suite(void) { return 0; } int add_libgdi_suite(void) { add_test_suite(libgdi); add_test_function(gdi_GetDC); add_test_function(gdi_CreateCompatibleDC); add_test_function(gdi_CreateBitmap); add_test_function(gdi_CreateCompatibleBitmap); add_test_function(gdi_CreatePen); add_test_function(gdi_CreateSolidBrush); add_test_function(gdi_CreatePatternBrush); add_test_function(gdi_CreateRectRgn); add_test_function(gdi_CreateRect); add_test_function(gdi_GetPixel); add_test_function(gdi_SetPixel); add_test_function(gdi_SetROP2); add_test_function(gdi_MoveToEx); add_test_function(gdi_LineTo); add_test_function(gdi_Ellipse); add_test_function(gdi_PtInRect); add_test_function(gdi_FillRect); add_test_function(gdi_BitBlt_32bpp); add_test_function(gdi_BitBlt_16bpp); add_test_function(gdi_BitBlt_8bpp); add_test_function(gdi_ClipCoords); add_test_function(gdi_InvalidateRegion); return 0; } /* BitBlt() Test Data */ /* source bitmap (16x16) */ unsigned char bmp_SRC[256] = { "\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF" "\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF" "\xFF\xFF\xFF\xFF\xFF\xFF\x00\x00\x00\x00\xFF\xFF\xFF\xFF\xFF\xFF" "\xFF\xFF\xFF\xFF\x00\x00\x00\x00\x00\x00\x00\x00\xFF\xFF\xFF\xFF" "\xFF\xFF\xFF\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\xFF\xFF\xFF" "\xFF\xFF\xFF\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\xFF\xFF\xFF" "\xFF\xFF\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\xFF\xFF" "\xFF\xFF\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\xFF\xFF" "\xFF\xFF\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\xFF\xFF" "\xFF\xFF\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\xFF\xFF" "\xFF\xFF\xFF\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\xFF\xFF\xFF" "\xFF\xFF\xFF\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\xFF\xFF\xFF" "\xFF\xFF\xFF\xFF\x00\x00\x00\x00\x00\x00\x00\x00\xFF\xFF\xFF\xFF" "\xFF\xFF\xFF\xFF\xFF\xFF\x00\x00\x00\x00\xFF\xFF\xFF\xFF\xFF\xFF" "\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF" "\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF" }; /* destination bitmap (16x16) */ unsigned char bmp_DST[256] = { "\x00\x00\x00\x00\x00\x00\x00\x00\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF" "\x00\x00\x00\x00\x00\x00\x00\x00\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF" "\x00\x00\x00\x00\x00\x00\x00\x00\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF" "\x00\x00\x00\x00\x00\x00\x00\x00\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF" "\x00\x00\x00\x00\x00\x00\x00\x00\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF" "\x00\x00\x00\x00\x00\x00\x00\x00\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF" "\x00\x00\x00\x00\x00\x00\x00\x00\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF" "\x00\x00\x00\x00\x00\x00\x00\x00\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF" "\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\x00\x00\x00\x00\x00\x00\x00\x00" "\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\x00\x00\x00\x00\x00\x00\x00\x00" "\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\x00\x00\x00\x00\x00\x00\x00\x00" "\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\x00\x00\x00\x00\x00\x00\x00\x00" "\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\x00\x00\x00\x00\x00\x00\x00\x00" "\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\x00\x00\x00\x00\x00\x00\x00\x00" "\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\x00\x00\x00\x00\x00\x00\x00\x00" "\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\x00\x00\x00\x00\x00\x00\x00\x00" }; /* pattern bitmap (8x8) */ unsigned char bmp_PAT[64] = { "\xFF\xFF\x00\x00\xFF\xFF\x00\x00" "\xFF\xFF\x00\x00\xFF\xFF\x00\x00" "\x00\x00\xFF\xFF\x00\x00\xFF\xFF" "\x00\x00\xFF\xFF\x00\x00\xFF\xFF" "\xFF\xFF\x00\x00\xFF\xFF\x00\x00" "\xFF\xFF\x00\x00\xFF\xFF\x00\x00" "\x00\x00\xFF\xFF\x00\x00\xFF\xFF" "\x00\x00\xFF\xFF\x00\x00\xFF\xFF" }; /* SRCCOPY (0x00CC0020) */ unsigned char bmp_SRCCOPY[256] = { "\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF" "\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF" "\xFF\xFF\xFF\xFF\xFF\xFF\x00\x00\x00\x00\xFF\xFF\xFF\xFF\xFF\xFF" "\xFF\xFF\xFF\xFF\x00\x00\x00\x00\x00\x00\x00\x00\xFF\xFF\xFF\xFF" "\xFF\xFF\xFF\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\xFF\xFF\xFF" "\xFF\xFF\xFF\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\xFF\xFF\xFF" "\xFF\xFF\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\xFF\xFF" "\xFF\xFF\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\xFF\xFF" "\xFF\xFF\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\xFF\xFF" "\xFF\xFF\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\xFF\xFF" "\xFF\xFF\xFF\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\xFF\xFF\xFF" "\xFF\xFF\xFF\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\xFF\xFF\xFF" "\xFF\xFF\xFF\xFF\x00\x00\x00\x00\x00\x00\x00\x00\xFF\xFF\xFF\xFF" "\xFF\xFF\xFF\xFF\xFF\xFF\x00\x00\x00\x00\xFF\xFF\xFF\xFF\xFF\xFF" "\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF" "\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF" }; /* BLACKNESS (0x00000042) */ unsigned char bmp_BLACKNESS[256] = { "\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00" "\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00" "\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00" "\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00" "\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00" "\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00" "\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00" "\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00" "\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00" "\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00" "\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00" "\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00" "\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00" "\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00" "\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00" "\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00" }; /* WHITENESS (0x00FF0062) */ unsigned char bmp_WHITENESS[256] = { "\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF" "\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF" "\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF" "\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF" "\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF" "\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF" "\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF" "\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF" "\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF" "\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF" "\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF" "\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF" "\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF" "\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF" "\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF" "\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF" }; /* SRCAND (0x008800C6) */ unsigned char bmp_SRCAND[256] = { "\x00\x00\x00\x00\x00\x00\x00\x00\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF" "\x00\x00\x00\x00\x00\x00\x00\x00\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF" "\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\xFF\xFF\xFF\xFF\xFF\xFF" "\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\xFF\xFF\xFF\xFF" "\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\xFF\xFF\xFF" "\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\xFF\xFF\xFF" "\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\xFF\xFF" "\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\xFF\xFF" "\xFF\xFF\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00" "\xFF\xFF\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00" "\xFF\xFF\xFF\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00" "\xFF\xFF\xFF\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00" "\xFF\xFF\xFF\xFF\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00" "\xFF\xFF\xFF\xFF\xFF\xFF\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00" "\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\x00\x00\x00\x00\x00\x00\x00\x00" "\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\x00\x00\x00\x00\x00\x00\x00\x00" }; /* SRCPAINT (0x00EE0086) */ unsigned char bmp_SRCPAINT[256] = { "\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF" "\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF" "\xFF\xFF\xFF\xFF\xFF\xFF\x00\x00\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF" "\xFF\xFF\xFF\xFF\x00\x00\x00\x00\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF" "\xFF\xFF\xFF\x00\x00\x00\x00\x00\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF" "\xFF\xFF\xFF\x00\x00\x00\x00\x00\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF" "\xFF\xFF\x00\x00\x00\x00\x00\x00\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF" "\xFF\xFF\x00\x00\x00\x00\x00\x00\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF" "\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\x00\x00\x00\x00\x00\x00\xFF\xFF" "\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\x00\x00\x00\x00\x00\x00\xFF\xFF" "\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\x00\x00\x00\x00\x00\xFF\xFF\xFF" "\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\x00\x00\x00\x00\x00\xFF\xFF\xFF" "\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\x00\x00\x00\x00\xFF\xFF\xFF\xFF" "\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\x00\x00\xFF\xFF\xFF\xFF\xFF\xFF" "\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF" "\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF" }; /* SRCINVERT (0x00660046) */ unsigned char bmp_SRCINVERT[256] = { "\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\x00\x00\x00\x00\x00\x00\x00\x00" "\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\x00\x00\x00\x00\x00\x00\x00\x00" "\xFF\xFF\xFF\xFF\xFF\xFF\x00\x00\xFF\xFF\x00\x00\x00\x00\x00\x00" "\xFF\xFF\xFF\xFF\x00\x00\x00\x00\xFF\xFF\xFF\xFF\x00\x00\x00\x00" "\xFF\xFF\xFF\x00\x00\x00\x00\x00\xFF\xFF\xFF\xFF\xFF\x00\x00\x00" "\xFF\xFF\xFF\x00\x00\x00\x00\x00\xFF\xFF\xFF\xFF\xFF\x00\x00\x00" "\xFF\xFF\x00\x00\x00\x00\x00\x00\xFF\xFF\xFF\xFF\xFF\xFF\x00\x00" "\xFF\xFF\x00\x00\x00\x00\x00\x00\xFF\xFF\xFF\xFF\xFF\xFF\x00\x00" "\x00\x00\xFF\xFF\xFF\xFF\xFF\xFF\x00\x00\x00\x00\x00\x00\xFF\xFF" "\x00\x00\xFF\xFF\xFF\xFF\xFF\xFF\x00\x00\x00\x00\x00\x00\xFF\xFF" "\x00\x00\x00\xFF\xFF\xFF\xFF\xFF\x00\x00\x00\x00\x00\xFF\xFF\xFF" "\x00\x00\x00\xFF\xFF\xFF\xFF\xFF\x00\x00\x00\x00\x00\xFF\xFF\xFF" "\x00\x00\x00\x00\xFF\xFF\xFF\xFF\x00\x00\x00\x00\xFF\xFF\xFF\xFF" "\x00\x00\x00\x00\x00\x00\xFF\xFF\x00\x00\xFF\xFF\xFF\xFF\xFF\xFF" "\x00\x00\x00\x00\x00\x00\x00\x00\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF" "\x00\x00\x00\x00\x00\x00\x00\x00\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF" }; /* SRCERASE (0x00440328) */ unsigned char bmp_SRCERASE[256] = { "\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\x00\x00\x00\x00\x00\x00\x00\x00" "\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\x00\x00\x00\x00\x00\x00\x00\x00" "\xFF\xFF\xFF\xFF\xFF\xFF\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00" "\xFF\xFF\xFF\xFF\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00" "\xFF\xFF\xFF\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00" "\xFF\xFF\xFF\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00" "\xFF\xFF\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00" "\xFF\xFF\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00" "\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\xFF\xFF" "\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\xFF\xFF" "\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\xFF\xFF\xFF" "\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\xFF\xFF\xFF" "\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\xFF\xFF\xFF\xFF" "\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\xFF\xFF\xFF\xFF\xFF\xFF" "\x00\x00\x00\x00\x00\x00\x00\x00\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF" "\x00\x00\x00\x00\x00\x00\x00\x00\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF" }; /* NOTSRCCOPY (0x00330008) */ unsigned char bmp_NOTSRCCOPY[256] = { "\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00" "\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00" "\x00\x00\x00\x00\x00\x00\xFF\xFF\xFF\xFF\x00\x00\x00\x00\x00\x00" "\x00\x00\x00\x00\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\x00\x00\x00\x00" "\x00\x00\x00\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\x00\x00\x00" "\x00\x00\x00\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\x00\x00\x00" "\x00\x00\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\x00\x00" "\x00\x00\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\x00\x00" "\x00\x00\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\x00\x00" "\x00\x00\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\x00\x00" "\x00\x00\x00\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\x00\x00\x00" "\x00\x00\x00\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\x00\x00\x00" "\x00\x00\x00\x00\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\x00\x00\x00\x00" "\x00\x00\x00\x00\x00\x00\xFF\xFF\xFF\xFF\x00\x00\x00\x00\x00\x00" "\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00" "\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00" }; /* NOTSRCERASE (0x001100A6) */ unsigned char bmp_NOTSRCERASE[256] = { "\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00" "\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00" "\x00\x00\x00\x00\x00\x00\xFF\xFF\x00\x00\x00\x00\x00\x00\x00\x00" "\x00\x00\x00\x00\xFF\xFF\xFF\xFF\x00\x00\x00\x00\x00\x00\x00\x00" "\x00\x00\x00\xFF\xFF\xFF\xFF\xFF\x00\x00\x00\x00\x00\x00\x00\x00" "\x00\x00\x00\xFF\xFF\xFF\xFF\xFF\x00\x00\x00\x00\x00\x00\x00\x00" "\x00\x00\xFF\xFF\xFF\xFF\xFF\xFF\x00\x00\x00\x00\x00\x00\x00\x00" "\x00\x00\xFF\xFF\xFF\xFF\xFF\xFF\x00\x00\x00\x00\x00\x00\x00\x00" "\x00\x00\x00\x00\x00\x00\x00\x00\xFF\xFF\xFF\xFF\xFF\xFF\x00\x00" "\x00\x00\x00\x00\x00\x00\x00\x00\xFF\xFF\xFF\xFF\xFF\xFF\x00\x00" "\x00\x00\x00\x00\x00\x00\x00\x00\xFF\xFF\xFF\xFF\xFF\x00\x00\x00" "\x00\x00\x00\x00\x00\x00\x00\x00\xFF\xFF\xFF\xFF\xFF\x00\x00\x00" "\x00\x00\x00\x00\x00\x00\x00\x00\xFF\xFF\xFF\xFF\x00\x00\x00\x00" "\x00\x00\x00\x00\x00\x00\x00\x00\xFF\xFF\x00\x00\x00\x00\x00\x00" "\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00" "\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00" }; /* DSTINVERT (0x00550009) */ unsigned char bmp_DSTINVERT[256] = { "\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\x00\x00\x00\x00\x00\x00\x00\x00" "\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\x00\x00\x00\x00\x00\x00\x00\x00" "\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\x00\x00\x00\x00\x00\x00\x00\x00" "\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\x00\x00\x00\x00\x00\x00\x00\x00" "\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\x00\x00\x00\x00\x00\x00\x00\x00" "\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\x00\x00\x00\x00\x00\x00\x00\x00" "\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\x00\x00\x00\x00\x00\x00\x00\x00" "\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\x00\x00\x00\x00\x00\x00\x00\x00" "\x00\x00\x00\x00\x00\x00\x00\x00\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF" "\x00\x00\x00\x00\x00\x00\x00\x00\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF" "\x00\x00\x00\x00\x00\x00\x00\x00\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF" "\x00\x00\x00\x00\x00\x00\x00\x00\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF" "\x00\x00\x00\x00\x00\x00\x00\x00\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF" "\x00\x00\x00\x00\x00\x00\x00\x00\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF" "\x00\x00\x00\x00\x00\x00\x00\x00\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF" "\x00\x00\x00\x00\x00\x00\x00\x00\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF" }; /* SPna (0x000C0324) */ unsigned char bmp_SPna[256] = { "\x00\x00\xFF\xFF\x00\x00\xFF\xFF\x00\x00\xFF\xFF\x00\x00\xFF\xFF" "\x00\x00\xFF\xFF\x00\x00\xFF\xFF\x00\x00\xFF\xFF\x00\x00\xFF\xFF" "\xFF\xFF\x00\x00\xFF\xFF\x00\x00\x00\x00\x00\x00\xFF\xFF\x00\x00" "\xFF\xFF\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\xFF\xFF\x00\x00" "\x00\x00\xFF\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\xFF\xFF" "\x00\x00\xFF\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\xFF\xFF" "\xFF\xFF\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00" "\xFF\xFF\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00" "\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\xFF\xFF" "\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\xFF\xFF" "\xFF\xFF\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\xFF\x00\x00" "\xFF\xFF\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\xFF\x00\x00" "\x00\x00\xFF\xFF\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\xFF\xFF" "\x00\x00\xFF\xFF\x00\x00\x00\x00\x00\x00\xFF\xFF\x00\x00\xFF\xFF" "\xFF\xFF\x00\x00\xFF\xFF\x00\x00\xFF\xFF\x00\x00\xFF\xFF\x00\x00" "\xFF\xFF\x00\x00\xFF\xFF\x00\x00\xFF\xFF\x00\x00\xFF\xFF\x00\x00" }; /* MERGEPAINT (0x00BB0226) */ unsigned char bmp_MERGEPAINT[256] = { "\x00\x00\x00\x00\x00\x00\x00\x00\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF" "\x00\x00\x00\x00\x00\x00\x00\x00\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF" "\x00\x00\x00\x00\x00\x00\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF" "\x00\x00\x00\x00\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF" "\x00\x00\x00\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF" "\x00\x00\x00\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF" "\x00\x00\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF" "\x00\x00\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF" "\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\x00\x00" "\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\x00\x00" "\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\x00\x00\x00" "\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\x00\x00\x00" "\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\x00\x00\x00\x00" "\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\x00\x00\x00\x00\x00\x00" "\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\x00\x00\x00\x00\x00\x00\x00\x00" "\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\x00\x00\x00\x00\x00\x00\x00\x00" }; /* MERGECOPY (0x00C000CA) */ unsigned char bmp_MERGECOPY[256] = { "\xFF\xFF\x00\x00\xFF\xFF\x00\x00\xFF\xFF\x00\x00\xFF\xFF\x00\x00" "\xFF\xFF\x00\x00\xFF\xFF\x00\x00\xFF\xFF\x00\x00\xFF\xFF\x00\x00" "\x00\x00\xFF\xFF\x00\x00\x00\x00\x00\x00\xFF\xFF\x00\x00\xFF\xFF" "\x00\x00\xFF\xFF\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\xFF\xFF" "\xFF\xFF\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\xFF\x00\x00" "\xFF\xFF\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\xFF\x00\x00" "\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\xFF\xFF" "\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\xFF\xFF" "\xFF\xFF\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00" "\xFF\xFF\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00" "\x00\x00\xFF\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\xFF\xFF" "\x00\x00\xFF\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\xFF\xFF" "\xFF\xFF\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\xFF\xFF\x00\x00" "\xFF\xFF\x00\x00\xFF\xFF\x00\x00\x00\x00\x00\x00\xFF\xFF\x00\x00" "\x00\x00\xFF\xFF\x00\x00\xFF\xFF\x00\x00\xFF\xFF\x00\x00\xFF\xFF" "\x00\x00\xFF\xFF\x00\x00\xFF\xFF\x00\x00\xFF\xFF\x00\x00\xFF\xFF" }; /* PATPAINT (0x00FB0A09) */ unsigned char bmp_PATPAINT[256] = { "\xFF\xFF\x00\x00\xFF\xFF\x00\x00\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF" "\xFF\xFF\x00\x00\xFF\xFF\x00\x00\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF" "\x00\x00\xFF\xFF\x00\x00\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF" "\x00\x00\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF" "\xFF\xFF\x00\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF" "\xFF\xFF\x00\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF" "\x00\x00\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF" "\x00\x00\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF" "\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\x00\x00" "\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\x00\x00" "\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\x00\xFF\xFF" "\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\x00\xFF\xFF" "\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\x00\x00" "\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\x00\x00\xFF\xFF\x00\x00" "\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\x00\x00\xFF\xFF\x00\x00\xFF\xFF" "\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\x00\x00\xFF\xFF\x00\x00\xFF\xFF" }; /* PATCOPY (0x00F00021) */ unsigned char bmp_PATCOPY[256] = { "\xFF\xFF\x00\x00\xFF\xFF\x00\x00\xFF\xFF\x00\x00\xFF\xFF\x00\x00" "\xFF\xFF\x00\x00\xFF\xFF\x00\x00\xFF\xFF\x00\x00\xFF\xFF\x00\x00" "\x00\x00\xFF\xFF\x00\x00\xFF\xFF\x00\x00\xFF\xFF\x00\x00\xFF\xFF" "\x00\x00\xFF\xFF\x00\x00\xFF\xFF\x00\x00\xFF\xFF\x00\x00\xFF\xFF" "\xFF\xFF\x00\x00\xFF\xFF\x00\x00\xFF\xFF\x00\x00\xFF\xFF\x00\x00" "\xFF\xFF\x00\x00\xFF\xFF\x00\x00\xFF\xFF\x00\x00\xFF\xFF\x00\x00" "\x00\x00\xFF\xFF\x00\x00\xFF\xFF\x00\x00\xFF\xFF\x00\x00\xFF\xFF" "\x00\x00\xFF\xFF\x00\x00\xFF\xFF\x00\x00\xFF\xFF\x00\x00\xFF\xFF" "\xFF\xFF\x00\x00\xFF\xFF\x00\x00\xFF\xFF\x00\x00\xFF\xFF\x00\x00" "\xFF\xFF\x00\x00\xFF\xFF\x00\x00\xFF\xFF\x00\x00\xFF\xFF\x00\x00" "\x00\x00\xFF\xFF\x00\x00\xFF\xFF\x00\x00\xFF\xFF\x00\x00\xFF\xFF" "\x00\x00\xFF\xFF\x00\x00\xFF\xFF\x00\x00\xFF\xFF\x00\x00\xFF\xFF" "\xFF\xFF\x00\x00\xFF\xFF\x00\x00\xFF\xFF\x00\x00\xFF\xFF\x00\x00" "\xFF\xFF\x00\x00\xFF\xFF\x00\x00\xFF\xFF\x00\x00\xFF\xFF\x00\x00" "\x00\x00\xFF\xFF\x00\x00\xFF\xFF\x00\x00\xFF\xFF\x00\x00\xFF\xFF" "\x00\x00\xFF\xFF\x00\x00\xFF\xFF\x00\x00\xFF\xFF\x00\x00\xFF\xFF" }; /* PATINVERT (0x005A0049) */ unsigned char bmp_PATINVERT[256] = { "\xFF\xFF\x00\x00\xFF\xFF\x00\x00\x00\x00\xFF\xFF\x00\x00\xFF\xFF" "\xFF\xFF\x00\x00\xFF\xFF\x00\x00\x00\x00\xFF\xFF\x00\x00\xFF\xFF" "\x00\x00\xFF\xFF\x00\x00\xFF\xFF\xFF\xFF\x00\x00\xFF\xFF\x00\x00" "\x00\x00\xFF\xFF\x00\x00\xFF\xFF\xFF\xFF\x00\x00\xFF\xFF\x00\x00" "\xFF\xFF\x00\x00\xFF\xFF\x00\x00\x00\x00\xFF\xFF\x00\x00\xFF\xFF" "\xFF\xFF\x00\x00\xFF\xFF\x00\x00\x00\x00\xFF\xFF\x00\x00\xFF\xFF" "\x00\x00\xFF\xFF\x00\x00\xFF\xFF\xFF\xFF\x00\x00\xFF\xFF\x00\x00" "\x00\x00\xFF\xFF\x00\x00\xFF\xFF\xFF\xFF\x00\x00\xFF\xFF\x00\x00" "\x00\x00\xFF\xFF\x00\x00\xFF\xFF\xFF\xFF\x00\x00\xFF\xFF\x00\x00" "\x00\x00\xFF\xFF\x00\x00\xFF\xFF\xFF\xFF\x00\x00\xFF\xFF\x00\x00" "\xFF\xFF\x00\x00\xFF\xFF\x00\x00\x00\x00\xFF\xFF\x00\x00\xFF\xFF" "\xFF\xFF\x00\x00\xFF\xFF\x00\x00\x00\x00\xFF\xFF\x00\x00\xFF\xFF" "\x00\x00\xFF\xFF\x00\x00\xFF\xFF\xFF\xFF\x00\x00\xFF\xFF\x00\x00" "\x00\x00\xFF\xFF\x00\x00\xFF\xFF\xFF\xFF\x00\x00\xFF\xFF\x00\x00" "\xFF\xFF\x00\x00\xFF\xFF\x00\x00\x00\x00\xFF\xFF\x00\x00\xFF\xFF" "\xFF\xFF\x00\x00\xFF\xFF\x00\x00\x00\x00\xFF\xFF\x00\x00\xFF\xFF" }; /* LineTo() Test Data */ unsigned char line_to_case_1[256] = { "\x00\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF" "\xFF\x00\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF" "\xFF\xFF\x00\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF" "\xFF\xFF\xFF\x00\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF" "\xFF\xFF\xFF\xFF\x00\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF" "\xFF\xFF\xFF\xFF\xFF\x00\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF" "\xFF\xFF\xFF\xFF\xFF\xFF\x00\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF" "\xFF\xFF\xFF\xFF\xFF\xFF\xFF\x00\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF" "\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\x00\xFF\xFF\xFF\xFF\xFF\xFF\xFF" "\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\x00\xFF\xFF\xFF\xFF\xFF\xFF" "\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\x00\xFF\xFF\xFF\xFF\xFF" "\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\x00\xFF\xFF\xFF\xFF" "\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\x00\xFF\xFF\xFF" "\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\x00\xFF\xFF" "\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\x00\xFF" "\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF" }; unsigned char line_to_case_2[256] = { "\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF" "\xFF\x00\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF" "\xFF\xFF\x00\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF" "\xFF\xFF\xFF\x00\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF" "\xFF\xFF\xFF\xFF\x00\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF" "\xFF\xFF\xFF\xFF\xFF\x00\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF" "\xFF\xFF\xFF\xFF\xFF\xFF\x00\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF" "\xFF\xFF\xFF\xFF\xFF\xFF\xFF\x00\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF" "\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\x00\xFF\xFF\xFF\xFF\xFF\xFF\xFF" "\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\x00\xFF\xFF\xFF\xFF\xFF\xFF" "\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\x00\xFF\xFF\xFF\xFF\xFF" "\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\x00\xFF\xFF\xFF\xFF" "\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\x00\xFF\xFF\xFF" "\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\x00\xFF\xFF" "\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\x00\xFF" "\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\x00" }; unsigned char line_to_case_3[256] = { "\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\x00" "\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\x00\xFF" "\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\x00\xFF\xFF" "\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\x00\xFF\xFF\xFF" "\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\x00\xFF\xFF\xFF\xFF" "\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\x00\xFF\xFF\xFF\xFF\xFF" "\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\x00\xFF\xFF\xFF\xFF\xFF\xFF" "\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\x00\xFF\xFF\xFF\xFF\xFF\xFF\xFF" "\xFF\xFF\xFF\xFF\xFF\xFF\xFF\x00\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF" "\xFF\xFF\xFF\xFF\xFF\xFF\x00\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF" "\xFF\xFF\xFF\xFF\xFF\x00\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF" "\xFF\xFF\xFF\xFF\x00\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF" "\xFF\xFF\xFF\x00\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF" "\xFF\xFF\x00\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF" "\xFF\x00\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF" "\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF" }; unsigned char line_to_case_4[256] = { "\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF" "\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\x00\xFF" "\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\x00\xFF\xFF" "\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\x00\xFF\xFF\xFF" "\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\x00\xFF\xFF\xFF\xFF" "\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\x00\xFF\xFF\xFF\xFF\xFF" "\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\x00\xFF\xFF\xFF\xFF\xFF\xFF" "\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\x00\xFF\xFF\xFF\xFF\xFF\xFF\xFF" "\xFF\xFF\xFF\xFF\xFF\xFF\xFF\x00\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF" "\xFF\xFF\xFF\xFF\xFF\xFF\x00\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF" "\xFF\xFF\xFF\xFF\xFF\x00\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF" "\xFF\xFF\xFF\xFF\x00\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF" "\xFF\xFF\xFF\x00\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF" "\xFF\xFF\x00\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF" "\xFF\x00\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF" "\x00\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF" }; unsigned char line_to_case_5[256] = { "\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF" "\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF" "\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF" "\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF" "\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF" "\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF" "\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF" "\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF" "\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\xFF" "\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF" "\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF" "\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF" "\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF" "\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF" "\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF" "\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF" }; unsigned char line_to_case_6[256] = { "\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF" "\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF" "\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF" "\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF" "\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF" "\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF" "\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF" "\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF" "\xFF\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00" "\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF" "\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF" "\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF" "\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF" "\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF" "\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF" "\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF" }; unsigned char line_to_case_7[256] = { "\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\x00\xFF\xFF\xFF\xFF\xFF\xFF\xFF" "\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\x00\xFF\xFF\xFF\xFF\xFF\xFF\xFF" "\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\x00\xFF\xFF\xFF\xFF\xFF\xFF\xFF" "\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\x00\xFF\xFF\xFF\xFF\xFF\xFF\xFF" "\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\x00\xFF\xFF\xFF\xFF\xFF\xFF\xFF" "\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\x00\xFF\xFF\xFF\xFF\xFF\xFF\xFF" "\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\x00\xFF\xFF\xFF\xFF\xFF\xFF\xFF" "\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\x00\xFF\xFF\xFF\xFF\xFF\xFF\xFF" "\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\x00\xFF\xFF\xFF\xFF\xFF\xFF\xFF" "\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\x00\xFF\xFF\xFF\xFF\xFF\xFF\xFF" "\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\x00\xFF\xFF\xFF\xFF\xFF\xFF\xFF" "\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\x00\xFF\xFF\xFF\xFF\xFF\xFF\xFF" "\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\x00\xFF\xFF\xFF\xFF\xFF\xFF\xFF" "\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\x00\xFF\xFF\xFF\xFF\xFF\xFF\xFF" "\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\x00\xFF\xFF\xFF\xFF\xFF\xFF\xFF" "\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF" }; unsigned char line_to_case_8[256] = { "\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF" "\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\x00\xFF\xFF\xFF\xFF\xFF\xFF\xFF" "\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\x00\xFF\xFF\xFF\xFF\xFF\xFF\xFF" "\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\x00\xFF\xFF\xFF\xFF\xFF\xFF\xFF" "\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\x00\xFF\xFF\xFF\xFF\xFF\xFF\xFF" "\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\x00\xFF\xFF\xFF\xFF\xFF\xFF\xFF" "\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\x00\xFF\xFF\xFF\xFF\xFF\xFF\xFF" "\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\x00\xFF\xFF\xFF\xFF\xFF\xFF\xFF" "\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\x00\xFF\xFF\xFF\xFF\xFF\xFF\xFF" "\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\x00\xFF\xFF\xFF\xFF\xFF\xFF\xFF" "\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\x00\xFF\xFF\xFF\xFF\xFF\xFF\xFF" "\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\x00\xFF\xFF\xFF\xFF\xFF\xFF\xFF" "\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\x00\xFF\xFF\xFF\xFF\xFF\xFF\xFF" "\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\x00\xFF\xFF\xFF\xFF\xFF\xFF\xFF" "\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\x00\xFF\xFF\xFF\xFF\xFF\xFF\xFF" "\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\x00\xFF\xFF\xFF\xFF\xFF\xFF\xFF" }; unsigned char line_to_case_9[256] = { "\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF" "\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF" "\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF" "\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF" "\xFF\xFF\xFF\xFF\x00\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF" "\xFF\xFF\xFF\xFF\xFF\x00\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF" "\xFF\xFF\xFF\xFF\xFF\xFF\x00\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF" "\xFF\xFF\xFF\xFF\xFF\xFF\xFF\x00\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF" "\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\x00\xFF\xFF\xFF\xFF\xFF\xFF\xFF" "\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\x00\xFF\xFF\xFF\xFF\xFF\xFF" "\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\x00\xFF\xFF\xFF\xFF\xFF" "\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\x00\xFF\xFF\xFF\xFF" "\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF" "\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF" "\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF" "\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF" }; unsigned char line_to_case_10[256] = { "\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF" "\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF" "\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF" "\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF" "\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF" "\xFF\xFF\xFF\xFF\xFF\x00\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF" "\xFF\xFF\xFF\xFF\xFF\xFF\x00\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF" "\xFF\xFF\xFF\xFF\xFF\xFF\xFF\x00\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF" "\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\x00\xFF\xFF\xFF\xFF\xFF\xFF\xFF" "\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\x00\xFF\xFF\xFF\xFF\xFF\xFF" "\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\x00\xFF\xFF\xFF\xFF\xFF" "\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\x00\xFF\xFF\xFF\xFF" "\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\x00\xFF\xFF\xFF" "\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF" "\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF" "\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF" }; unsigned char line_to_case_11[256] = { "\x00\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF" "\xFF\x00\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF" "\xFF\xFF\x00\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF" "\xFF\xFF\xFF\x00\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF" "\xFF\xFF\xFF\xFF\x00\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF" "\xFF\xFF\xFF\xFF\xFF\x00\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF" "\xFF\xFF\xFF\xFF\xFF\xFF\x00\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF" "\xFF\xFF\xFF\xFF\xFF\xFF\xFF\x00\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF" "\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\x00\xFF\xFF\xFF\xFF\xFF\xFF\xFF" "\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\x00\xFF\xFF\xFF\xFF\xFF\xFF" "\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\x00\xFF\xFF\xFF\xFF\xFF" "\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\x00\xFF\xFF\xFF\xFF" "\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\x00\xFF\xFF\xFF" "\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\x00\xFF\xFF" "\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\x00\xFF" "\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\x00" }; unsigned char line_to_R2_BLACK[256] = { "\x00\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF" "\xFF\x00\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF" "\xFF\xFF\x00\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF" "\xFF\xFF\xFF\x00\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF" "\xFF\xFF\xFF\xFF\x00\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF" "\xFF\xFF\xFF\xFF\xFF\x00\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF" "\xFF\xFF\xFF\xFF\xFF\xFF\x00\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF" "\xFF\xFF\xFF\xFF\xFF\xFF\xFF\x00\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF" "\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\x00\xFF\xFF\xFF\xFF\xFF\xFF\xFF" "\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\x00\xFF\xFF\xFF\xFF\xFF\xFF" "\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\x00\xFF\xFF\xFF\xFF\xFF" "\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\x00\xFF\xFF\xFF\xFF" "\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\x00\xFF\xFF\xFF" "\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\x00\xFF\xFF" "\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\x00\xFF" "\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\x00" }; unsigned char line_to_R2_NOTMERGEPEN[256] = { "\x00\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF" "\xFF\x00\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF" "\xFF\xFF\x00\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF" "\xFF\xFF\xFF\x00\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF" "\xFF\xFF\xFF\xFF\x00\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF" "\xFF\xFF\xFF\xFF\xFF\x00\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF" "\xFF\xFF\xFF\xFF\xFF\xFF\x00\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF" "\xFF\xFF\xFF\xFF\xFF\xFF\xFF\x00\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF" "\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\x00\xFF\xFF\xFF\xFF\xFF\xFF\xFF" "\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\x00\xFF\xFF\xFF\xFF\xFF\xFF" "\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\x00\xFF\xFF\xFF\xFF\xFF" "\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\x00\xFF\xFF\xFF\xFF" "\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\x00\xFF\xFF\xFF" "\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\x00\xFF\xFF" "\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\x00\xFF" "\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\x00" }; unsigned char line_to_R2_MASKNOTPEN[256] = { "\x00\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF" "\xFF\x00\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF" "\xFF\xFF\x00\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF" "\xFF\xFF\xFF\x00\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF" "\xFF\xFF\xFF\xFF\x00\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF" "\xFF\xFF\xFF\xFF\xFF\x00\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF" "\xFF\xFF\xFF\xFF\xFF\xFF\x00\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF" "\xFF\xFF\xFF\xFF\xFF\xFF\xFF\x00\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF" "\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\x00\xFF\xFF\xFF\xFF\xFF\xFF\xFF" "\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\x00\xFF\xFF\xFF\xFF\xFF\xFF" "\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\x00\xFF\xFF\xFF\xFF\xFF" "\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\x00\xFF\xFF\xFF\xFF" "\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\x00\xFF\xFF\xFF" "\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\x00\xFF\xFF" "\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\x00\xFF" "\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\x00" }; unsigned char line_to_R2_NOTCOPYPEN[256] = { "\x00\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF" "\xFF\x00\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF" "\xFF\xFF\x00\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF" "\xFF\xFF\xFF\x00\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF" "\xFF\xFF\xFF\xFF\x00\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF" "\xFF\xFF\xFF\xFF\xFF\x00\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF" "\xFF\xFF\xFF\xFF\xFF\xFF\x00\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF" "\xFF\xFF\xFF\xFF\xFF\xFF\xFF\x00\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF" "\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\x00\xFF\xFF\xFF\xFF\xFF\xFF\xFF" "\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\x00\xFF\xFF\xFF\xFF\xFF\xFF" "\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\x00\xFF\xFF\xFF\xFF\xFF" "\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\x00\xFF\xFF\xFF\xFF" "\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\x00\xFF\xFF\xFF" "\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\x00\xFF\xFF" "\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\x00\xFF" "\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\x00" }; unsigned char line_to_R2_MASKPENNOT[256] = { "\x00\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF" "\xFF\x00\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF" "\xFF\xFF\x00\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF" "\xFF\xFF\xFF\x00\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF" "\xFF\xFF\xFF\xFF\x00\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF" "\xFF\xFF\xFF\xFF\xFF\x00\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF" "\xFF\xFF\xFF\xFF\xFF\xFF\x00\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF" "\xFF\xFF\xFF\xFF\xFF\xFF\xFF\x00\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF" "\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\x00\xFF\xFF\xFF\xFF\xFF\xFF\xFF" "\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\x00\xFF\xFF\xFF\xFF\xFF\xFF" "\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\x00\xFF\xFF\xFF\xFF\xFF" "\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\x00\xFF\xFF\xFF\xFF" "\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\x00\xFF\xFF\xFF" "\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\x00\xFF\xFF" "\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\x00\xFF" "\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\x00" }; unsigned char line_to_R2_NOT[256] = { "\x00\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF" "\xFF\x00\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF" "\xFF\xFF\x00\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF" "\xFF\xFF\xFF\x00\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF" "\xFF\xFF\xFF\xFF\x00\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF" "\xFF\xFF\xFF\xFF\xFF\x00\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF" "\xFF\xFF\xFF\xFF\xFF\xFF\x00\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF" "\xFF\xFF\xFF\xFF\xFF\xFF\xFF\x00\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF" "\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\x00\xFF\xFF\xFF\xFF\xFF\xFF\xFF" "\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\x00\xFF\xFF\xFF\xFF\xFF\xFF" "\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\x00\xFF\xFF\xFF\xFF\xFF" "\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\x00\xFF\xFF\xFF\xFF" "\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\x00\xFF\xFF\xFF" "\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\x00\xFF\xFF" "\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\x00\xFF" "\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\x00" }; unsigned char line_to_R2_XORPEN[256] = { "\x00\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF" "\xFF\x00\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF" "\xFF\xFF\x00\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF" "\xFF\xFF\xFF\x00\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF" "\xFF\xFF\xFF\xFF\x00\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF" "\xFF\xFF\xFF\xFF\xFF\x00\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF" "\xFF\xFF\xFF\xFF\xFF\xFF\x00\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF" "\xFF\xFF\xFF\xFF\xFF\xFF\xFF\x00\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF" "\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\x00\xFF\xFF\xFF\xFF\xFF\xFF\xFF" "\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\x00\xFF\xFF\xFF\xFF\xFF\xFF" "\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\x00\xFF\xFF\xFF\xFF\xFF" "\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\x00\xFF\xFF\xFF\xFF" "\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\x00\xFF\xFF\xFF" "\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\x00\xFF\xFF" "\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\x00\xFF" "\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\x00" }; unsigned char line_to_R2_NOTMASKPEN[256] = { "\x00\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF" "\xFF\x00\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF" "\xFF\xFF\x00\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF" "\xFF\xFF\xFF\x00\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF" "\xFF\xFF\xFF\xFF\x00\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF" "\xFF\xFF\xFF\xFF\xFF\x00\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF" "\xFF\xFF\xFF\xFF\xFF\xFF\x00\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF" "\xFF\xFF\xFF\xFF\xFF\xFF\xFF\x00\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF" "\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\x00\xFF\xFF\xFF\xFF\xFF\xFF\xFF" "\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\x00\xFF\xFF\xFF\xFF\xFF\xFF" "\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\x00\xFF\xFF\xFF\xFF\xFF" "\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\x00\xFF\xFF\xFF\xFF" "\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\x00\xFF\xFF\xFF" "\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\x00\xFF\xFF" "\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\x00\xFF" "\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\x00" }; unsigned char line_to_R2_MASKPEN[256] = { "\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF" "\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF" "\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF" "\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF" "\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF" "\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF" "\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF" "\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF" "\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF" "\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF" "\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF" "\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF" "\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF" "\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF" "\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF" "\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF" }; unsigned char line_to_R2_NOTXORPEN[256] = { "\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF" "\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF" "\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF" "\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF" "\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF" "\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF" "\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF" "\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF" "\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF" "\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF" "\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF" "\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF" "\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF" "\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF" "\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF" "\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF" }; unsigned char line_to_R2_NOP[256] = { "\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF" "\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF" "\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF" "\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF" "\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF" "\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF" "\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF" "\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF" "\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF" "\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF" "\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF" "\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF" "\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF" "\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF" "\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF" "\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF" }; unsigned char line_to_R2_MERGENOTPEN[256] = { "\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF" "\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF" "\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF" "\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF" "\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF" "\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF" "\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF" "\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF" "\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF" "\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF" "\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF" "\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF" "\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF" "\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF" "\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF" "\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF" }; unsigned char line_to_R2_COPYPEN[256] = { "\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF" "\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF" "\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF" "\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF" "\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF" "\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF" "\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF" "\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF" "\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF" "\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF" "\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF" "\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF" "\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF" "\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF" "\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF" "\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF" }; unsigned char line_to_R2_MERGEPENNOT[256] = { "\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF" "\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF" "\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF" "\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF" "\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF" "\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF" "\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF" "\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF" "\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF" "\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF" "\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF" "\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF" "\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF" "\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF" "\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF" "\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF" }; unsigned char line_to_R2_MERGEPEN[256] = { "\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF" "\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF" "\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF" "\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF" "\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF" "\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF" "\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF" "\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF" "\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF" "\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF" "\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF" "\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF" "\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF" "\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF" "\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF" "\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF" }; unsigned char line_to_R2_WHITE[256] = { "\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF" "\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF" "\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF" "\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF" "\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF" "\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF" "\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF" "\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF" "\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF" "\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF" "\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF" "\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF" "\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF" "\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF" "\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF" "\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF" }; /* PolylineTo() Test Data */ unsigned char polyline_to_case_1[256] = { "\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\x00\xFF\xFF\xFF\xFF\xFF\xFF\xFF" "\xFF\xFF\xFF\xFF\xFF\xFF\xFF\x00\x00\xFF\xFF\xFF\xFF\xFF\xFF\xFF" "\xFF\xFF\xFF\xFF\xFF\xFF\xFF\x00\xFF\x00\xFF\xFF\xFF\xFF\xFF\xFF" "\xFF\xFF\xFF\xFF\xFF\xFF\x00\xFF\xFF\x00\xFF\xFF\xFF\xFF\xFF\xFF" "\xFF\xFF\xFF\xFF\xFF\xFF\x00\xFF\xFF\xFF\x00\xFF\xFF\xFF\xFF\xFF" "\xFF\xFF\xFF\xFF\xFF\x00\xFF\xFF\xFF\xFF\x00\xFF\xFF\xFF\xFF\xFF" "\xFF\xFF\xFF\xFF\xFF\x00\xFF\xFF\xFF\xFF\xFF\x00\xFF\xFF\xFF\xFF" "\xFF\xFF\xFF\xFF\x00\xFF\xFF\xFF\xFF\xFF\xFF\x00\xFF\xFF\xFF\xFF" "\xFF\xFF\xFF\xFF\x00\xFF\xFF\xFF\xFF\xFF\xFF\xFF\x00\xFF\xFF\xFF" "\xFF\xFF\xFF\x00\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\x00\xFF\xFF\xFF" "\xFF\xFF\xFF\x00\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\x00\xFF\xFF" "\xFF\xFF\x00\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\x00\xFF\xFF" "\xFF\xFF\x00\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\x00\xFF" "\xFF\x00\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\x00\xFF" "\xFF\x00\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\x00" "\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00" }; unsigned char polyline_to_case_2[256] = { "\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF" "\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF" "\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF" "\xFF\xFF\xFF\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\xFF\xFF" "\xFF\xFF\xFF\x00\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\x00\xFF\xFF" "\xFF\xFF\xFF\x00\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\x00\xFF\xFF" "\xFF\xFF\xFF\x00\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\x00\xFF\xFF" "\xFF\xFF\xFF\x00\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\x00\xFF\xFF" "\xFF\xFF\xFF\x00\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\x00\xFF\xFF" "\xFF\xFF\xFF\x00\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\x00\xFF\xFF" "\xFF\xFF\xFF\x00\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\x00\xFF\xFF" "\xFF\xFF\xFF\x00\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\x00\xFF\xFF" "\xFF\xFF\xFF\x00\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\x00\xFF\xFF" "\xFF\xFF\xFF\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\xFF\xFF" "\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF" "\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF" }; /* Ellipse() Test Data */ unsigned char ellipse_case_1[256] = { "\xFF\xFF\xFF\xFF\xFF\x00\x00\x00\x00\x00\x00\xFF\xFF\xFF\xFF\xFF" "\xFF\xFF\xFF\xFF\x00\x00\x00\x00\x00\x00\x00\x00\xFF\xFF\xFF\xFF" "\xFF\xFF\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\xFF\xFF" "\xFF\xFF\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\xFF\xFF" "\xFF\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\xFF" "\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00" "\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00" "\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00" "\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00" "\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00" "\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00" "\xFF\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\xFF" "\xFF\xFF\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\xFF\xFF" "\xFF\xFF\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\xFF\xFF" "\xFF\xFF\xFF\xFF\x00\x00\x00\x00\x00\x00\x00\x00\xFF\xFF\xFF\xFF" "\xFF\xFF\xFF\xFF\xFF\x00\x00\x00\x00\x00\x00\xFF\xFF\xFF\xFF\xFF" }; unsigned char ellipse_case_2[256] = { "\xFF\xFF\xFF\xFF\xFF\xFF\x00\x00\x00\x00\xFF\xFF\xFF\xFF\xFF\xFF" "\xFF\xFF\xFF\xFF\xFF\x00\x00\x00\x00\x00\x00\xFF\xFF\xFF\xFF\xFF" "\xFF\xFF\xFF\xFF\x00\x00\x00\x00\x00\x00\x00\x00\xFF\xFF\xFF\xFF" "\xFF\xFF\xFF\xFF\x00\x00\x00\x00\x00\x00\x00\x00\xFF\xFF\xFF\xFF" "\xFF\xFF\xFF\xFF\x00\x00\x00\x00\x00\x00\x00\x00\xFF\xFF\xFF\xFF" "\xFF\xFF\xFF\xFF\x00\x00\x00\x00\x00\x00\x00\x00\xFF\xFF\xFF\xFF" "\xFF\xFF\xFF\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\xFF\xFF\xFF" "\xFF\xFF\xFF\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\xFF\xFF\xFF" "\xFF\xFF\xFF\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\xFF\xFF\xFF" "\xFF\xFF\xFF\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\xFF\xFF\xFF" "\xFF\xFF\xFF\xFF\x00\x00\x00\x00\x00\x00\x00\x00\xFF\xFF\xFF\xFF" "\xFF\xFF\xFF\xFF\x00\x00\x00\x00\x00\x00\x00\x00\xFF\xFF\xFF\xFF" "\xFF\xFF\xFF\xFF\x00\x00\x00\x00\x00\x00\x00\x00\xFF\xFF\xFF\xFF" "\xFF\xFF\xFF\xFF\x00\x00\x00\x00\x00\x00\x00\x00\xFF\xFF\xFF\xFF" "\xFF\xFF\xFF\xFF\xFF\x00\x00\x00\x00\x00\x00\xFF\xFF\xFF\xFF\xFF" "\xFF\xFF\xFF\xFF\xFF\xFF\x00\x00\x00\x00\xFF\xFF\xFF\xFF\xFF\xFF" }; unsigned char ellipse_case_3[256] = { "\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF" "\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF" "\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF" "\xFF\xFF\xFF\xFF\xFF\xFF\x00\x00\x00\x00\xFF\xFF\xFF\xFF\xFF\xFF" "\xFF\xFF\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\xFF\xFF" "\xFF\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\xFF" "\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00" "\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00" "\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00" "\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00" "\xFF\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\xFF" "\xFF\xFF\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\xFF\xFF" "\xFF\xFF\xFF\xFF\xFF\xFF\x00\x00\x00\x00\xFF\xFF\xFF\xFF\xFF\xFF" "\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF" "\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF" "\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF" }; /* Polygon() Test Data */ unsigned char polygon_case_1[256] = { "\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\x00\xFF\xFF\xFF\xFF\xFF\xFF\xFF" "\xFF\xFF\xFF\xFF\xFF\xFF\xFF\x00\x00\xFF\xFF\xFF\xFF\xFF\xFF\xFF" "\xFF\xFF\xFF\xFF\xFF\xFF\xFF\x00\x00\x00\xFF\xFF\xFF\xFF\xFF\xFF" "\xFF\xFF\xFF\xFF\xFF\xFF\x00\x00\x00\x00\xFF\xFF\xFF\xFF\xFF\xFF" "\xFF\xFF\xFF\xFF\xFF\xFF\x00\x00\x00\x00\x00\xFF\xFF\xFF\xFF\xFF" "\xFF\xFF\xFF\xFF\xFF\x00\x00\x00\x00\x00\x00\xFF\xFF\xFF\xFF\xFF" "\xFF\xFF\xFF\xFF\xFF\x00\x00\x00\x00\x00\x00\x00\xFF\xFF\xFF\xFF" "\xFF\xFF\xFF\xFF\x00\x00\x00\x00\x00\x00\x00\x00\xFF\xFF\xFF\xFF" "\xFF\xFF\xFF\xFF\x00\x00\x00\x00\x00\x00\x00\x00\x00\xFF\xFF\xFF" "\xFF\xFF\xFF\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\xFF\xFF\xFF" "\xFF\xFF\xFF\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\xFF\xFF" "\xFF\xFF\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\xFF\xFF" "\xFF\xFF\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\xFF" "\xFF\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\xFF" "\xFF\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00" "\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00" }; unsigned char polygon_case_2[256] = { "\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF" "\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF" "\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF" "\xFF\xFF\xFF\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\xFF\xFF" "\xFF\xFF\xFF\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\xFF\xFF" "\xFF\xFF\xFF\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\xFF\xFF" "\xFF\xFF\xFF\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\xFF\xFF" "\xFF\xFF\xFF\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\xFF\xFF" "\xFF\xFF\xFF\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\xFF\xFF" "\xFF\xFF\xFF\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\xFF\xFF" "\xFF\xFF\xFF\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\xFF\xFF" "\xFF\xFF\xFF\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\xFF\xFF" "\xFF\xFF\xFF\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\xFF\xFF" "\xFF\xFF\xFF\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\xFF\xFF" "\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF" "\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF" }; int CompareBitmaps(HGDI_BITMAP hBmp1, HGDI_BITMAP hBmp2) { int x, y; uint8 *p1, *p2; int minw = (hBmp1->width < hBmp2->width) ? hBmp1->width : hBmp2->width; int minh = (hBmp1->height < hBmp2->height) ? hBmp1->height : hBmp2->height; if (hBmp1->bitsPerPixel == hBmp2->bitsPerPixel) { p1 = hBmp1->data; p2 = hBmp2->data; int bpp = hBmp1->bitsPerPixel; if (bpp == 32) { for (y = 0; y < minh; y++) { for (x = 0; x < minw; x++) { if (*p1 != *p2) return 0; p1++; p2++; if (*p1 != *p2) return 0; p1++; p2++; if (*p1 != *p2) return 0; p1 += 2; p2 += 2; } } } else if (bpp == 16) { for (y = 0; y < minh; y++) { for (x = 0; x < minw; x++) { if (*p1 != *p2) return 0; p1++; p2++; if (*p1 != *p2) return 0; p1++; p2++; } } } else if (bpp == 8) { for (y = 0; y < minh; y++) { for (x = 0; x < minw; x++) { if (*p1 != *p2) return 0; p1++; p2++; } } } } else { return 0; } return 1; } void dump_bitmap(HGDI_BITMAP hBmp, char* name) { dump_data(hBmp->data, hBmp->width * hBmp->height * hBmp->bytesPerPixel, hBmp->width * hBmp->bytesPerPixel, name); } void assertBitmapsEqual(HGDI_BITMAP hBmpActual, HGDI_BITMAP hBmpExpected, char *name) { int bitmapsEqual = CompareBitmaps(hBmpActual, hBmpExpected); if (bitmapsEqual != 1) { printf("\n%s\n", name); dump_bitmap(hBmpActual, "Actual"); dump_bitmap(hBmpExpected, "Expected"); } CU_ASSERT(bitmapsEqual == 1); } void test_gdi_GetDC(void) { HGDI_DC hdc = gdi_GetDC(); CU_ASSERT(hdc->bytesPerPixel == 4); CU_ASSERT(hdc->bitsPerPixel == 32); CU_ASSERT(hdc->drawMode == GDI_R2_BLACK); } void test_gdi_CreateCompatibleDC(void) { HGDI_DC hdc; HGDI_DC chdc; hdc = gdi_GetDC(); hdc->bytesPerPixel = 2; hdc->bitsPerPixel = 16; hdc->drawMode = GDI_R2_XORPEN; chdc = gdi_CreateCompatibleDC(hdc); CU_ASSERT(chdc->bytesPerPixel == hdc->bytesPerPixel); CU_ASSERT(chdc->bitsPerPixel == hdc->bitsPerPixel); CU_ASSERT(chdc->drawMode == hdc->drawMode); } void test_gdi_CreateBitmap(void) { int bpp; int width; int height; uint8* data; HGDI_BITMAP hBitmap; bpp = 32; width = 32; height = 16; data = (uint8*) malloc(width * height * 4); hBitmap = gdi_CreateBitmap(width, height, bpp, data); CU_ASSERT(hBitmap->objectType == GDIOBJECT_BITMAP); CU_ASSERT(hBitmap->bitsPerPixel == bpp); CU_ASSERT(hBitmap->width == width); CU_ASSERT(hBitmap->height == height); CU_ASSERT(hBitmap->data == data); gdi_DeleteObject((HGDIOBJECT) hBitmap); } void test_gdi_CreateCompatibleBitmap(void) { HGDI_DC hdc; int width; int height; HGDI_BITMAP hBitmap; hdc = gdi_GetDC(); hdc->bytesPerPixel = 4; hdc->bitsPerPixel = 32; width = 32; height = 16; hBitmap = gdi_CreateCompatibleBitmap(hdc, width, height); CU_ASSERT(hBitmap->objectType == GDIOBJECT_BITMAP); CU_ASSERT(hBitmap->bytesPerPixel == hdc->bytesPerPixel); CU_ASSERT(hBitmap->bitsPerPixel == hdc->bitsPerPixel); CU_ASSERT(hBitmap->width == width); CU_ASSERT(hBitmap->height == height); CU_ASSERT(hBitmap->data != NULL); gdi_DeleteObject((HGDIOBJECT) hBitmap); } void test_gdi_CreatePen(void) { HGDI_PEN hPen = gdi_CreatePen(GDI_PS_SOLID, 8, 0xAABBCCDD); CU_ASSERT(hPen->style == GDI_PS_SOLID); CU_ASSERT(hPen->width == 8); CU_ASSERT(hPen->color == 0xAABBCCDD); gdi_DeleteObject((HGDIOBJECT) hPen); } void test_gdi_CreateSolidBrush(void) { HGDI_BRUSH hBrush = gdi_CreateSolidBrush(0xAABBCCDD); CU_ASSERT(hBrush->objectType == GDIOBJECT_BRUSH); CU_ASSERT(hBrush->style == GDI_BS_SOLID); CU_ASSERT(hBrush->color == 0xAABBCCDD); gdi_DeleteObject((HGDIOBJECT) hBrush); } void test_gdi_CreatePatternBrush(void) { HGDI_BRUSH hBrush; HGDI_BITMAP hBitmap; hBitmap = gdi_CreateBitmap(64, 64, 32, NULL); hBrush = gdi_CreatePatternBrush(hBitmap); CU_ASSERT(hBrush->objectType == GDIOBJECT_BRUSH); CU_ASSERT(hBrush->style == GDI_BS_PATTERN); CU_ASSERT(hBrush->pattern == hBitmap); gdi_DeleteObject((HGDIOBJECT) hBitmap); } void test_gdi_CreateRectRgn(void) { int x1 = 32; int y1 = 64; int x2 = 128; int y2 = 256; HGDI_RGN hRegion = gdi_CreateRectRgn(x1, y1, x2, y2); CU_ASSERT(hRegion->objectType == GDIOBJECT_REGION); CU_ASSERT(hRegion->x == x1); CU_ASSERT(hRegion->y == y1); CU_ASSERT(hRegion->w == x2 - x1 + 1); CU_ASSERT(hRegion->h == y2 - y1 + 1); CU_ASSERT(hRegion->null == 0); gdi_DeleteObject((HGDIOBJECT) hRegion); } void test_gdi_CreateRect(void) { int x1 = 32; int y1 = 64; int x2 = 128; int y2 = 256; HGDI_RECT hRect = gdi_CreateRect(x1, y1, x2, y2); CU_ASSERT(hRect->objectType == GDIOBJECT_RECT); CU_ASSERT(hRect->left == x1); CU_ASSERT(hRect->top == y1); CU_ASSERT(hRect->right == x2); CU_ASSERT(hRect->bottom == y2); gdi_DeleteObject((HGDIOBJECT) hRect); } void test_gdi_GetPixel(void) { HGDI_DC hdc; int width = 128; int height = 64; HGDI_BITMAP hBitmap; hdc = gdi_GetDC(); hdc->bytesPerPixel = 4; hdc->bitsPerPixel = 32; hBitmap = gdi_CreateCompatibleBitmap(hdc, width, height); gdi_SelectObject(hdc, (HGDIOBJECT) hBitmap); hBitmap->data[(64 * width * 4) + 32 * 4 + 0] = 0xDD; hBitmap->data[(64 * width * 4) + 32 * 4 + 1] = 0xCC; hBitmap->data[(64 * width * 4) + 32 * 4 + 2] = 0xBB; hBitmap->data[(64 * width * 4) + 32 * 4 + 3] = 0xAA; CU_ASSERT(gdi_GetPixel(hdc, 32, 64) == 0xAABBCCDD); gdi_DeleteObject((HGDIOBJECT) hBitmap); } void test_gdi_SetPixel(void) { HGDI_DC hdc; int width = 128; int height = 64; HGDI_BITMAP hBitmap; hdc = gdi_GetDC(); hdc->bytesPerPixel = 4; hdc->bitsPerPixel = 32; hBitmap = gdi_CreateCompatibleBitmap(hdc, width, height); gdi_SelectObject(hdc, (HGDIOBJECT) hBitmap); gdi_SetPixel(hdc, 32, 64, 0xAABBCCDD); CU_ASSERT(gdi_GetPixel(hdc, 32, 64) == 0xAABBCCDD); gdi_SetPixel(hdc, width - 1, height - 1, 0xAABBCCDD); CU_ASSERT(gdi_GetPixel(hdc, width - 1, height - 1) == 0xAABBCCDD); gdi_DeleteObject((HGDIOBJECT) hBitmap); } void test_gdi_SetROP2(void) { HGDI_DC hdc = gdi_GetDC(); gdi_SetROP2(hdc, GDI_R2_BLACK); CU_ASSERT(hdc->drawMode == GDI_R2_BLACK); } void test_gdi_MoveToEx(void) { HGDI_DC hdc; HGDI_PEN hPen; HGDI_POINT prevPoint; hdc = gdi_GetDC(); hPen = gdi_CreatePen(GDI_PS_SOLID, 8, 0xAABBCCDD); gdi_SelectObject(hdc, (HGDIOBJECT) hPen); gdi_MoveToEx(hdc, 128, 256, NULL); CU_ASSERT(hdc->pen->posX == 128); CU_ASSERT(hdc->pen->posY == 256); prevPoint = (HGDI_POINT) malloc(sizeof(GDI_POINT)); memset(prevPoint, '\0', sizeof(GDI_POINT)); gdi_MoveToEx(hdc, 64, 128, prevPoint); CU_ASSERT(prevPoint->x == 128); CU_ASSERT(prevPoint->y == 256); CU_ASSERT(hdc->pen->posX == 64); CU_ASSERT(hdc->pen->posY == 128); } void test_gdi_LineTo(void) { HGDI_DC hdc; HGDI_PEN pen; uint8* data; HGDI_BITMAP hBmp; HGDI_BITMAP hBmp_LineTo_1; HGDI_BITMAP hBmp_LineTo_2; HGDI_BITMAP hBmp_LineTo_3; HGDI_BITMAP hBmp_LineTo_4; HGDI_BITMAP hBmp_LineTo_5; HGDI_BITMAP hBmp_LineTo_6; HGDI_BITMAP hBmp_LineTo_7; HGDI_BITMAP hBmp_LineTo_8; HGDI_BITMAP hBmp_LineTo_9; HGDI_BITMAP hBmp_LineTo_10; HGDI_BITMAP hBmp_LineTo_11; HGDI_BITMAP hBmp_LineTo_R2_BLACK; HGDI_BITMAP hBmp_LineTo_R2_NOTMERGEPEN; HGDI_BITMAP hBmp_LineTo_R2_MASKNOTPEN; HGDI_BITMAP hBmp_LineTo_R2_NOTCOPYPEN; HGDI_BITMAP hBmp_LineTo_R2_MASKPENNOT; HGDI_BITMAP hBmp_LineTo_R2_NOT; HGDI_BITMAP hBmp_LineTo_R2_XORPEN; HGDI_BITMAP hBmp_LineTo_R2_NOTMASKPEN; HGDI_BITMAP hBmp_LineTo_R2_MASKPEN; HGDI_BITMAP hBmp_LineTo_R2_NOTXORPEN; HGDI_BITMAP hBmp_LineTo_R2_NOP; HGDI_BITMAP hBmp_LineTo_R2_MERGENOTPEN; HGDI_BITMAP hBmp_LineTo_R2_COPYPEN; HGDI_BITMAP hBmp_LineTo_R2_MERGEPENNOT; HGDI_BITMAP hBmp_LineTo_R2_MERGEPEN; HGDI_BITMAP hBmp_LineTo_R2_WHITE; rdpPalette* hPalette; HCLRCONV clrconv; int bitsPerPixel = 8; int bytesPerPixel = 1; hdc = gdi_GetDC(); hdc->bitsPerPixel = bitsPerPixel; hdc->bytesPerPixel = bytesPerPixel; gdi_SetNullClipRgn(hdc); pen = gdi_CreatePen(1, 1, 0); gdi_SelectObject(hdc, (HGDIOBJECT) pen); hBmp = gdi_CreateCompatibleBitmap(hdc, 16, 16); gdi_SelectObject(hdc, (HGDIOBJECT) hBmp); hPalette = (rdpPalette*) gdi_GetSystemPalette(); clrconv = (HCLRCONV) malloc(sizeof(CLRCONV)); clrconv->alpha = 1; clrconv->invert = 0; clrconv->palette = hPalette; data = (uint8*) freerdp_image_convert((uint8*) line_to_case_1, NULL, 16, 16, 8, bitsPerPixel, clrconv); hBmp_LineTo_1 = gdi_CreateBitmap(16, 16, bitsPerPixel, data); data = (uint8*) freerdp_image_convert((uint8*) line_to_case_2, NULL, 16, 16, 8, bitsPerPixel, clrconv); hBmp_LineTo_2 = gdi_CreateBitmap(16, 16, bitsPerPixel, data); data = (uint8*) freerdp_image_convert((uint8*) line_to_case_3, NULL, 16, 16, 8, bitsPerPixel, clrconv); hBmp_LineTo_3 = gdi_CreateBitmap(16, 16, bitsPerPixel, data); data = (uint8*) freerdp_image_convert((uint8*) line_to_case_4, NULL, 16, 16, 8, bitsPerPixel, clrconv); hBmp_LineTo_4 = gdi_CreateBitmap(16, 16, bitsPerPixel, data); data = (uint8*) freerdp_image_convert((uint8*) line_to_case_5, NULL, 16, 16, 8, bitsPerPixel, clrconv); hBmp_LineTo_5 = gdi_CreateBitmap(16, 16, bitsPerPixel, data); data = (uint8*) freerdp_image_convert((uint8*) line_to_case_5, NULL, 16, 16, 8, bitsPerPixel, clrconv); hBmp_LineTo_5 = gdi_CreateBitmap(16, 16, bitsPerPixel, data); data = (uint8*) freerdp_image_convert((uint8*) line_to_case_6, NULL, 16, 16, 8, bitsPerPixel, clrconv); hBmp_LineTo_6 = gdi_CreateBitmap(16, 16, bitsPerPixel, data); data = (uint8*) freerdp_image_convert((uint8*) line_to_case_7, NULL, 16, 16, 8, bitsPerPixel, clrconv); hBmp_LineTo_7 = gdi_CreateBitmap(16, 16, bitsPerPixel, data); data = (uint8*) freerdp_image_convert((uint8*) line_to_case_8, NULL, 16, 16, 8, bitsPerPixel, clrconv); hBmp_LineTo_8 = gdi_CreateBitmap(16, 16, bitsPerPixel, data); data = (uint8*) freerdp_image_convert((uint8*) line_to_case_9, NULL, 16, 16, 8, bitsPerPixel, clrconv); hBmp_LineTo_9 = gdi_CreateBitmap(16, 16, bitsPerPixel, data); data = (uint8*) freerdp_image_convert((uint8*) line_to_case_10, NULL, 16, 16, 8, bitsPerPixel, clrconv); hBmp_LineTo_10 = gdi_CreateBitmap(16, 16, bitsPerPixel, data); data = (uint8*) freerdp_image_convert((uint8*) line_to_case_11, NULL, 16, 16, 8, bitsPerPixel, clrconv); hBmp_LineTo_11 = gdi_CreateBitmap(16, 16, bitsPerPixel, data); data = (uint8*) freerdp_image_convert((uint8*) line_to_R2_BLACK, NULL, 16, 16, 8, bitsPerPixel, clrconv); hBmp_LineTo_R2_BLACK = gdi_CreateBitmap(16, 16, bitsPerPixel, data); data = (uint8*) freerdp_image_convert((uint8*) line_to_R2_NOTMERGEPEN, NULL, 16, 16, 8, bitsPerPixel, clrconv); hBmp_LineTo_R2_NOTMERGEPEN = gdi_CreateBitmap(16, 16, bitsPerPixel, data); data = (uint8*) freerdp_image_convert((uint8*) line_to_R2_MASKNOTPEN, NULL, 16, 16, 8, bitsPerPixel, clrconv); hBmp_LineTo_R2_MASKNOTPEN = gdi_CreateBitmap(16, 16, bitsPerPixel, data); data = (uint8*) freerdp_image_convert((uint8*) line_to_R2_NOTCOPYPEN, NULL, 16, 16, 8, bitsPerPixel, clrconv); hBmp_LineTo_R2_NOTCOPYPEN = gdi_CreateBitmap(16, 16, bitsPerPixel, data); data = (uint8*) freerdp_image_convert((uint8*) line_to_R2_MASKPENNOT, NULL, 16, 16, 8, bitsPerPixel, clrconv); hBmp_LineTo_R2_MASKPENNOT = gdi_CreateBitmap(16, 16, bitsPerPixel, data); data = (uint8*) freerdp_image_convert((uint8*) line_to_R2_NOT, NULL, 16, 16, 8, bitsPerPixel, clrconv); hBmp_LineTo_R2_NOT = gdi_CreateBitmap(16, 16, bitsPerPixel, data); data = (uint8*) freerdp_image_convert((uint8*) line_to_R2_XORPEN, NULL, 16, 16, 8, bitsPerPixel, clrconv); hBmp_LineTo_R2_XORPEN = gdi_CreateBitmap(16, 16, bitsPerPixel, data); data = (uint8*) freerdp_image_convert((uint8*) line_to_R2_NOTMASKPEN, NULL, 16, 16, 8, bitsPerPixel, clrconv); hBmp_LineTo_R2_NOTMASKPEN = gdi_CreateBitmap(16, 16, bitsPerPixel, data); data = (uint8*) freerdp_image_convert((uint8*) line_to_R2_MASKPEN, NULL, 16, 16, 8, bitsPerPixel, clrconv); hBmp_LineTo_R2_MASKPEN = gdi_CreateBitmap(16, 16, bitsPerPixel, data); data = (uint8*) freerdp_image_convert((uint8*) line_to_R2_NOTXORPEN, NULL, 16, 16, 8, bitsPerPixel, clrconv); hBmp_LineTo_R2_NOTXORPEN = gdi_CreateBitmap(16, 16, bitsPerPixel, data); data = (uint8*) freerdp_image_convert((uint8*) line_to_R2_NOP, NULL, 16, 16, 8, bitsPerPixel, clrconv); hBmp_LineTo_R2_NOP = gdi_CreateBitmap(16, 16, bitsPerPixel, data); data = (uint8*) freerdp_image_convert((uint8*) line_to_R2_MERGENOTPEN, NULL, 16, 16, 8, bitsPerPixel, clrconv); hBmp_LineTo_R2_MERGENOTPEN = gdi_CreateBitmap(16, 16, bitsPerPixel, data); data = (uint8*) freerdp_image_convert((uint8*) line_to_R2_COPYPEN, NULL, 16, 16, 8, bitsPerPixel, clrconv); hBmp_LineTo_R2_COPYPEN = gdi_CreateBitmap(16, 16, bitsPerPixel, data); data = (uint8*) freerdp_image_convert((uint8*) line_to_R2_MERGEPENNOT, NULL, 16, 16, 8, bitsPerPixel, clrconv); hBmp_LineTo_R2_MERGEPENNOT = gdi_CreateBitmap(16, 16, bitsPerPixel, data); data = (uint8*) freerdp_image_convert((uint8*) line_to_R2_MERGEPEN, NULL, 16, 16, 8, bitsPerPixel, clrconv); hBmp_LineTo_R2_MERGEPEN = gdi_CreateBitmap(16, 16, bitsPerPixel, data); data = (uint8*) freerdp_image_convert((uint8*) line_to_R2_WHITE, NULL, 16, 16, 8, bitsPerPixel, clrconv); hBmp_LineTo_R2_WHITE = gdi_CreateBitmap(16, 16, bitsPerPixel, data); /* Test Case 1: (0,0) -> (15, 15) */ gdi_BitBlt(hdc, 0, 0, 16, 16, hdc, 0, 0, GDI_WHITENESS); gdi_MoveToEx(hdc, 0, 0, NULL); gdi_LineTo(hdc, 15, 15); assertBitmapsEqual(hBmp, hBmp_LineTo_1, "Case 1"); /* Test Case 2: (15,15) -> (0,0) */ gdi_BitBlt(hdc, 0, 0, 16, 16, hdc, 0, 0, GDI_WHITENESS); gdi_MoveToEx(hdc, 15, 15, NULL); gdi_LineTo(hdc, 0, 0); assertBitmapsEqual(hBmp, hBmp_LineTo_2, "Case 2"); /* Test Case 3: (15,0) -> (0,15) */ gdi_BitBlt(hdc, 0, 0, 16, 16, hdc, 0, 0, GDI_WHITENESS); gdi_MoveToEx(hdc, 15, 0, NULL); gdi_LineTo(hdc, 0, 15); assertBitmapsEqual(hBmp, hBmp_LineTo_3, "Case 3"); /* Test Case 4: (0,15) -> (15,0) */ gdi_BitBlt(hdc, 0, 0, 16, 16, hdc, 0, 0, GDI_WHITENESS); gdi_MoveToEx(hdc, 0, 15, NULL); gdi_LineTo(hdc, 15, 0); assertBitmapsEqual(hBmp, hBmp_LineTo_4, "Case 4"); /* Test Case 4: (0,15) -> (15,0) */ gdi_BitBlt(hdc, 0, 0, 16, 16, hdc, 0, 0, GDI_WHITENESS); gdi_MoveToEx(hdc, 0, 15, NULL); gdi_LineTo(hdc, 15, 0); assertBitmapsEqual(hBmp, hBmp_LineTo_4, "Case 4"); /* Test Case 5: (0,8) -> (15,8) */ gdi_BitBlt(hdc, 0, 0, 16, 16, hdc, 0, 0, GDI_WHITENESS); gdi_MoveToEx(hdc, 0, 8, NULL); gdi_LineTo(hdc, 15, 8); assertBitmapsEqual(hBmp, hBmp_LineTo_5, "Case 5"); /* Test Case 6: (15,8) -> (0,8) */ gdi_BitBlt(hdc, 0, 0, 16, 16, hdc, 0, 0, GDI_WHITENESS); gdi_MoveToEx(hdc, 15, 8, NULL); gdi_LineTo(hdc, 0, 8); assertBitmapsEqual(hBmp, hBmp_LineTo_6, "Case 6"); /* Test Case 7: (8,0) -> (8,15) */ gdi_BitBlt(hdc, 0, 0, 16, 16, hdc, 0, 0, GDI_WHITENESS); gdi_MoveToEx(hdc, 8, 0, NULL); gdi_LineTo(hdc, 8, 15); assertBitmapsEqual(hBmp, hBmp_LineTo_7, "Case 7"); /* Test Case 8: (8,15) -> (8,0) */ gdi_BitBlt(hdc, 0, 0, 16, 16, hdc, 0, 0, GDI_WHITENESS); gdi_MoveToEx(hdc, 8, 15, NULL); gdi_LineTo(hdc, 8, 0); assertBitmapsEqual(hBmp, hBmp_LineTo_8, "Case 8"); /* Test Case 9: (4,4) -> (12,12) */ gdi_BitBlt(hdc, 0, 0, 16, 16, hdc, 0, 0, GDI_WHITENESS); gdi_MoveToEx(hdc, 4, 4, NULL); gdi_LineTo(hdc, 12, 12); assertBitmapsEqual(hBmp, hBmp_LineTo_9, "Case 9"); /* Test Case 10: (12,12) -> (4,4) */ gdi_BitBlt(hdc, 0, 0, 16, 16, hdc, 0, 0, GDI_WHITENESS); gdi_MoveToEx(hdc, 12, 12, NULL); gdi_LineTo(hdc, 4, 4); assertBitmapsEqual(hBmp, hBmp_LineTo_10, "Case 10"); /* Test Case 11: (0,0) -> (+10,+10) */ gdi_BitBlt(hdc, 0, 0, 16, 16, hdc, 0, 0, GDI_WHITENESS); gdi_SetClipRgn(hdc, 0, 0, 16, 16); gdi_MoveToEx(hdc, 0, 0, NULL); gdi_LineTo(hdc, 16 + 10, 16 + 10); assertBitmapsEqual(hBmp, hBmp_LineTo_11, "Case 11"); /* Test Case 12: (0,0) -> (16,16), R2_BLACK */ gdi_BitBlt(hdc, 0, 0, 16, 16, hdc, 0, 0, GDI_WHITENESS); gdi_SetClipRgn(hdc, 0, 0, 16, 16); gdi_MoveToEx(hdc, 0, 0, NULL); gdi_SetROP2(hdc, GDI_R2_BLACK); gdi_LineTo(hdc, 16, 16); assertBitmapsEqual(hBmp, hBmp_LineTo_R2_BLACK, "Case 12"); /* Test Case 13: (0,0) -> (16,16), R2_NOTMERGEPEN */ gdi_BitBlt(hdc, 0, 0, 16, 16, hdc, 0, 0, GDI_WHITENESS); gdi_SetClipRgn(hdc, 0, 0, 16, 16); gdi_MoveToEx(hdc, 0, 0, NULL); gdi_SetROP2(hdc, GDI_R2_NOTMERGEPEN); gdi_LineTo(hdc, 16, 16); assertBitmapsEqual(hBmp, hBmp_LineTo_R2_NOTMERGEPEN, "Case 13"); /* Test Case 14: (0,0) -> (16,16), R2_MASKNOTPEN */ gdi_BitBlt(hdc, 0, 0, 16, 16, hdc, 0, 0, GDI_WHITENESS); gdi_SetClipRgn(hdc, 0, 0, 16, 16); gdi_MoveToEx(hdc, 0, 0, NULL); gdi_SetROP2(hdc, GDI_R2_MASKNOTPEN); gdi_LineTo(hdc, 16, 16); assertBitmapsEqual(hBmp, hBmp_LineTo_R2_MASKNOTPEN, "Case 14"); /* Test Case 15: (0,0) -> (16,16), R2_NOTCOPYPEN */ gdi_BitBlt(hdc, 0, 0, 16, 16, hdc, 0, 0, GDI_WHITENESS); gdi_SetClipRgn(hdc, 0, 0, 16, 16); gdi_MoveToEx(hdc, 0, 0, NULL); gdi_SetROP2(hdc, GDI_R2_NOTCOPYPEN); gdi_LineTo(hdc, 16, 16); assertBitmapsEqual(hBmp, hBmp_LineTo_R2_NOTCOPYPEN, "Case 15"); /* Test Case 16: (0,0) -> (16,16), R2_MASKPENNOT */ gdi_BitBlt(hdc, 0, 0, 16, 16, hdc, 0, 0, GDI_WHITENESS); gdi_SetClipRgn(hdc, 0, 0, 16, 16); gdi_MoveToEx(hdc, 0, 0, NULL); gdi_SetROP2(hdc, GDI_R2_MASKPENNOT); gdi_LineTo(hdc, 16, 16); assertBitmapsEqual(hBmp, hBmp_LineTo_R2_MASKPENNOT, "Case 16"); /* Test Case 17: (0,0) -> (16,16), R2_NOT */ gdi_BitBlt(hdc, 0, 0, 16, 16, hdc, 0, 0, GDI_WHITENESS); gdi_SetClipRgn(hdc, 0, 0, 16, 16); gdi_MoveToEx(hdc, 0, 0, NULL); gdi_SetROP2(hdc, GDI_R2_NOT); gdi_LineTo(hdc, 16, 16); assertBitmapsEqual(hBmp, hBmp_LineTo_R2_NOT, "Case 17"); /* Test Case 18: (0,0) -> (16,16), R2_XORPEN */ gdi_BitBlt(hdc, 0, 0, 16, 16, hdc, 0, 0, GDI_WHITENESS); gdi_SetClipRgn(hdc, 0, 0, 16, 16); gdi_MoveToEx(hdc, 0, 0, NULL); gdi_SetROP2(hdc, GDI_R2_XORPEN); gdi_LineTo(hdc, 16, 16); assertBitmapsEqual(hBmp, hBmp_LineTo_R2_XORPEN, "Case 18"); /* Test Case 19: (0,0) -> (16,16), R2_NOTMASKPEN */ gdi_BitBlt(hdc, 0, 0, 16, 16, hdc, 0, 0, GDI_WHITENESS); gdi_SetClipRgn(hdc, 0, 0, 16, 16); gdi_MoveToEx(hdc, 0, 0, NULL); gdi_SetROP2(hdc, GDI_R2_NOTMASKPEN); gdi_LineTo(hdc, 16, 16); assertBitmapsEqual(hBmp, hBmp_LineTo_R2_NOTMASKPEN, "Case 19"); /* Test Case 20: (0,0) -> (16,16), R2_MASKPEN */ gdi_BitBlt(hdc, 0, 0, 16, 16, hdc, 0, 0, GDI_WHITENESS); gdi_SetClipRgn(hdc, 0, 0, 16, 16); gdi_MoveToEx(hdc, 0, 0, NULL); gdi_SetROP2(hdc, GDI_R2_MASKPEN); gdi_LineTo(hdc, 16, 16); assertBitmapsEqual(hBmp, hBmp_LineTo_R2_MASKPEN, "Case 20"); /* Test Case 21: (0,0) -> (16,16), R2_NOTXORPEN */ gdi_BitBlt(hdc, 0, 0, 16, 16, hdc, 0, 0, GDI_WHITENESS); gdi_SetClipRgn(hdc, 0, 0, 16, 16); gdi_MoveToEx(hdc, 0, 0, NULL); gdi_SetROP2(hdc, GDI_R2_NOTXORPEN); gdi_LineTo(hdc, 16, 16); assertBitmapsEqual(hBmp, hBmp_LineTo_R2_NOTXORPEN, "Case 21"); /* Test Case 22: (0,0) -> (16,16), R2_NOP */ gdi_BitBlt(hdc, 0, 0, 16, 16, hdc, 0, 0, GDI_WHITENESS); gdi_SetClipRgn(hdc, 0, 0, 16, 16); gdi_MoveToEx(hdc, 0, 0, NULL); gdi_SetROP2(hdc, GDI_R2_NOP); gdi_LineTo(hdc, 16, 16); assertBitmapsEqual(hBmp, hBmp_LineTo_R2_NOP, "Case 22"); /* Test Case 23: (0,0) -> (16,16), R2_MERGENOTPEN */ gdi_BitBlt(hdc, 0, 0, 16, 16, hdc, 0, 0, GDI_WHITENESS); gdi_SetClipRgn(hdc, 0, 0, 16, 16); gdi_MoveToEx(hdc, 0, 0, NULL); gdi_SetROP2(hdc, GDI_R2_MERGENOTPEN); gdi_LineTo(hdc, 16, 16); assertBitmapsEqual(hBmp, hBmp_LineTo_R2_MERGENOTPEN, "Case 23"); /* Test Case 24: (0,0) -> (16,16), R2_COPYPEN */ gdi_BitBlt(hdc, 0, 0, 16, 16, hdc, 0, 0, GDI_WHITENESS); gdi_SetClipRgn(hdc, 0, 0, 16, 16); gdi_MoveToEx(hdc, 0, 0, NULL); gdi_SetROP2(hdc, GDI_R2_COPYPEN); gdi_LineTo(hdc, 16, 16); assertBitmapsEqual(hBmp, hBmp_LineTo_R2_COPYPEN, "Case 24"); /* Test Case 25: (0,0) -> (16,16), R2_MERGEPENNOT */ gdi_BitBlt(hdc, 0, 0, 16, 16, hdc, 0, 0, GDI_WHITENESS); gdi_SetClipRgn(hdc, 0, 0, 16, 16); gdi_MoveToEx(hdc, 0, 0, NULL); gdi_SetROP2(hdc, GDI_R2_MERGEPENNOT); gdi_LineTo(hdc, 16, 16); assertBitmapsEqual(hBmp, hBmp_LineTo_R2_MERGEPENNOT, "Case 25"); /* Test Case 26: (0,0) -> (16,16), R2_MERGEPEN */ gdi_BitBlt(hdc, 0, 0, 16, 16, hdc, 0, 0, GDI_WHITENESS); gdi_SetClipRgn(hdc, 0, 0, 16, 16); gdi_MoveToEx(hdc, 0, 0, NULL); gdi_SetROP2(hdc, GDI_R2_MERGEPEN); gdi_LineTo(hdc, 16, 16); assertBitmapsEqual(hBmp, hBmp_LineTo_R2_MERGEPEN, "Case 26"); /* Test Case 27: (0,0) -> (16,16), R2_WHITE */ gdi_BitBlt(hdc, 0, 0, 16, 16, hdc, 0, 0, GDI_WHITENESS); gdi_SetClipRgn(hdc, 0, 0, 16, 16); gdi_MoveToEx(hdc, 0, 0, NULL); gdi_SetROP2(hdc, GDI_R2_WHITE); gdi_LineTo(hdc, 16, 16); assertBitmapsEqual(hBmp, hBmp_LineTo_R2_WHITE, "Case 27"); } void test_gdi_Ellipse(void) { HGDI_DC hdc; HGDI_PEN pen; uint8* data; HGDI_BITMAP hBmp; HGDI_BITMAP hBmp_Ellipse_1; HGDI_BITMAP hBmp_Ellipse_2; HGDI_BITMAP hBmp_Ellipse_3; rdpPalette* hPalette; HCLRCONV clrconv; int bitsPerPixel = 8; int bytesPerPixel = 1; hdc = gdi_GetDC(); hdc->bitsPerPixel = bitsPerPixel; hdc->bytesPerPixel = bytesPerPixel; gdi_SetNullClipRgn(hdc); pen = gdi_CreatePen(1, 1, 0); gdi_SelectObject(hdc, (HGDIOBJECT) pen); hBmp = gdi_CreateCompatibleBitmap(hdc, 16, 16); gdi_SelectObject(hdc, (HGDIOBJECT) hBmp); hPalette = (rdpPalette*) gdi_GetSystemPalette(); clrconv = (HCLRCONV) malloc(sizeof(CLRCONV)); clrconv->alpha = 1; clrconv->invert = 0; clrconv->palette = hPalette; data = (uint8*) freerdp_image_convert((uint8*) ellipse_case_1, NULL, 16, 16, 8, bitsPerPixel, clrconv); hBmp_Ellipse_1 = gdi_CreateBitmap(16, 16, bitsPerPixel, data); data = (uint8*) freerdp_image_convert((uint8*) ellipse_case_2, NULL, 16, 16, 8, bitsPerPixel, clrconv); hBmp_Ellipse_2 = gdi_CreateBitmap(16, 16, bitsPerPixel, data); data = (uint8*) freerdp_image_convert((uint8*) ellipse_case_3, NULL, 16, 16, 8, bitsPerPixel, clrconv); hBmp_Ellipse_3 = gdi_CreateBitmap(16, 16, bitsPerPixel, data); /* Test Case 1: (0,0) -> (16, 16) */ gdi_BitBlt(hdc, 0, 0, 16, 16, hdc, 0, 0, GDI_WHITENESS); gdi_Ellipse(hdc, 0, 0, 16, 16); //assertBitmapsEqual(hBmp, hBmp_Ellipse_1, "Case 1"); } void test_gdi_PtInRect(void) { HGDI_RECT hRect; int left = 20; int top = 40; int right = 60; int bottom = 80; hRect = gdi_CreateRect(left, top, right, bottom); CU_ASSERT(gdi_PtInRect(hRect, 0, 0) == 0); CU_ASSERT(gdi_PtInRect(hRect, 500, 500) == 0); CU_ASSERT(gdi_PtInRect(hRect, 40, 100) == 0); CU_ASSERT(gdi_PtInRect(hRect, 10, 40) == 0); CU_ASSERT(gdi_PtInRect(hRect, 30, 50) == 1); CU_ASSERT(gdi_PtInRect(hRect, left, top) == 1); CU_ASSERT(gdi_PtInRect(hRect, right, bottom) == 1); CU_ASSERT(gdi_PtInRect(hRect, right, 60) == 1); CU_ASSERT(gdi_PtInRect(hRect, 40, bottom) == 1); } void test_gdi_FillRect(void) { HGDI_DC hdc; HGDI_RECT hRect; HGDI_BRUSH hBrush; HGDI_BITMAP hBitmap; GDI_COLOR color; GDI_COLOR pixel; GDI_COLOR rawPixel; int x, y; int badPixels; int goodPixels; int width = 200; int height = 300; int left = 20; int top = 40; int right = 60; int bottom = 80; hdc = gdi_GetDC(); hdc->bytesPerPixel = 4; hdc->bitsPerPixel = 32; hRect = gdi_CreateRect(left, top, right, bottom); hBitmap = gdi_CreateCompatibleBitmap(hdc, width, height); memset(hBitmap->data, 0, width * height * hdc->bytesPerPixel); gdi_SelectObject(hdc, (HGDIOBJECT) hBitmap); color = (GDI_COLOR) ARGB32(0xFF, 0xAA, 0xBB, 0xCC); hBrush = gdi_CreateSolidBrush(color); gdi_FillRect(hdc, hRect, hBrush); badPixels = 0; goodPixels = 0; for (x = 0; x < width; x++) { for (y = 0; y < height; y++) { rawPixel = gdi_GetPixel(hdc, x, y); pixel = gdi_get_color_32bpp(hdc, rawPixel); if (gdi_PtInRect(hRect, x, y)) { if (pixel == color) { goodPixels++; } else { printf("actual:%04X expected:%04X\n", gdi_GetPixel(hdc, x, y), color); badPixels++; } } else { if (pixel == color) { badPixels++; } else { goodPixels++; } } } } CU_ASSERT(goodPixels == width * height); CU_ASSERT(badPixels == 0); gdi_DeleteObject((HGDIOBJECT) hBrush); gdi_DeleteObject((HGDIOBJECT) hBitmap); } void test_gdi_BitBlt_32bpp(void) { uint8* data; HGDI_DC hdcSrc; HGDI_DC hdcDst; HGDI_BRUSH hBrush; HGDI_BITMAP hBmpSrc; HGDI_BITMAP hBmpDst; HGDI_BITMAP hBmpPat; HGDI_BITMAP hBmp_SPna; HGDI_BITMAP hBmp_BLACKNESS; HGDI_BITMAP hBmp_WHITENESS; HGDI_BITMAP hBmp_SRCCOPY; HGDI_BITMAP hBmp_SRCAND; HGDI_BITMAP hBmp_SRCPAINT; HGDI_BITMAP hBmp_SRCINVERT; HGDI_BITMAP hBmp_SRCERASE; HGDI_BITMAP hBmp_NOTSRCCOPY; HGDI_BITMAP hBmp_NOTSRCERASE; HGDI_BITMAP hBmp_DSTINVERT; HGDI_BITMAP hBmp_MERGECOPY; HGDI_BITMAP hBmp_MERGEPAINT; HGDI_BITMAP hBmp_PATCOPY; HGDI_BITMAP hBmp_PATPAINT; HGDI_BITMAP hBmp_PATINVERT; HGDI_BITMAP hBmpDstOriginal; rdpPalette* hPalette; HCLRCONV clrconv; int bytesPerPixel = 4; int bitsPerPixel = 32; hdcSrc = gdi_GetDC(); hdcSrc->bytesPerPixel = bytesPerPixel; hdcSrc->bitsPerPixel = bitsPerPixel; hdcDst = gdi_GetDC(); hdcDst->bytesPerPixel = bytesPerPixel; hdcDst->bitsPerPixel = bitsPerPixel; hPalette = (rdpPalette*) gdi_GetSystemPalette(); clrconv = (HCLRCONV) malloc(sizeof(CLRCONV)); clrconv->alpha = 1; clrconv->invert = 0; clrconv->palette = hPalette; data = (uint8*) freerdp_image_convert((uint8*) bmp_SRC, NULL, 16, 16, 8, bitsPerPixel, clrconv); hBmpSrc = gdi_CreateBitmap(16, 16, bitsPerPixel, data); data = (uint8*) freerdp_image_convert((uint8*) bmp_DST, NULL, 16, 16, 8, bitsPerPixel, clrconv); hBmpDst = gdi_CreateBitmap(16, 16, bitsPerPixel, data); data = (uint8*) freerdp_image_convert((uint8*) bmp_DST, NULL, 16, 16, 8, bitsPerPixel, clrconv); hBmpDstOriginal = gdi_CreateBitmap(16, 16, bitsPerPixel, data); data = (uint8*) freerdp_image_convert((uint8*) bmp_PAT, NULL, 8, 8, 8, bitsPerPixel, clrconv); hBmpPat = gdi_CreateBitmap(8, 8, bitsPerPixel, data); data = (uint8*) freerdp_image_convert((uint8*) bmp_SRCCOPY, NULL, 16, 16, 8, bitsPerPixel, clrconv); hBmp_SRCCOPY = gdi_CreateBitmap(16, 16, bitsPerPixel, data); data = (uint8*) freerdp_image_convert((uint8*) bmp_SPna, NULL, 16, 16, 8, bitsPerPixel, clrconv); hBmp_SPna = gdi_CreateBitmap(16, 16, bitsPerPixel, data); data = (uint8*) freerdp_image_convert((uint8*) bmp_BLACKNESS, NULL, 16, 16, 8, bitsPerPixel, clrconv); hBmp_BLACKNESS = gdi_CreateBitmap(16, 16, bitsPerPixel, data); data = (uint8*) freerdp_image_convert((uint8*) bmp_WHITENESS, NULL, 16, 16, 8, bitsPerPixel, clrconv); hBmp_WHITENESS = gdi_CreateBitmap(16, 16, bitsPerPixel, data); data = (uint8*) freerdp_image_convert((uint8*) bmp_SRCAND, NULL, 16, 16, 8, bitsPerPixel, clrconv); hBmp_SRCAND = gdi_CreateBitmap(16, 16, bitsPerPixel, data); data = (uint8*) freerdp_image_convert((uint8*) bmp_SRCPAINT, NULL, 16, 16, 8, bitsPerPixel, clrconv); hBmp_SRCPAINT = gdi_CreateBitmap(16, 16, bitsPerPixel, data); data = (uint8*) freerdp_image_convert((uint8*) bmp_SRCINVERT, NULL, 16, 16, 8, bitsPerPixel, clrconv); hBmp_SRCINVERT = gdi_CreateBitmap(16, 16, bitsPerPixel, data); data = (uint8*) freerdp_image_convert((uint8*) bmp_SRCERASE, NULL, 16, 16, 8, bitsPerPixel, clrconv); hBmp_SRCERASE = gdi_CreateBitmap(16, 16, bitsPerPixel, data); data = (uint8*) freerdp_image_convert((uint8*) bmp_NOTSRCCOPY, NULL, 16, 16, 8, bitsPerPixel, clrconv); hBmp_NOTSRCCOPY = gdi_CreateBitmap(16, 16, bitsPerPixel, data); data = (uint8*) freerdp_image_convert((uint8*) bmp_NOTSRCERASE, NULL, 16, 16, 8, bitsPerPixel, clrconv); hBmp_NOTSRCERASE = gdi_CreateBitmap(16, 16, bitsPerPixel, data); data = (uint8*) freerdp_image_convert((uint8*) bmp_DSTINVERT, NULL, 16, 16, 8, bitsPerPixel, clrconv); hBmp_DSTINVERT = gdi_CreateBitmap(16, 16, bitsPerPixel, data); data = (uint8*) freerdp_image_convert((uint8*) bmp_MERGECOPY, NULL, 16, 16, 8, bitsPerPixel, clrconv); hBmp_MERGECOPY = gdi_CreateBitmap(16, 16, bitsPerPixel, data); data = (uint8*) freerdp_image_convert((uint8*) bmp_MERGEPAINT, NULL, 16, 16, 8, bitsPerPixel, clrconv); hBmp_MERGEPAINT = gdi_CreateBitmap(16, 16, bitsPerPixel, data); data = (uint8*) freerdp_image_convert((uint8*) bmp_PATCOPY, NULL, 16, 16, 8, bitsPerPixel, clrconv); hBmp_PATCOPY = gdi_CreateBitmap(16, 16, bitsPerPixel, data); data = (uint8*) freerdp_image_convert((uint8*) bmp_PATPAINT, NULL, 16, 16, 8, bitsPerPixel, clrconv); hBmp_PATPAINT = gdi_CreateBitmap(16, 16, bitsPerPixel, data); data = (uint8*) freerdp_image_convert((uint8*) bmp_PATINVERT, NULL, 16, 16, 8, bitsPerPixel, clrconv); hBmp_PATINVERT = gdi_CreateBitmap(16, 16, bitsPerPixel, data); gdi_SelectObject(hdcSrc, (HGDIOBJECT) hBmpSrc); gdi_SelectObject(hdcDst, (HGDIOBJECT) hBmpDst); /* SRCCOPY */ gdi_BitBlt(hdcDst, 0, 0, 16, 16, hdcSrc, 0, 0, GDI_SRCCOPY); CU_ASSERT(CompareBitmaps(hBmpDst, hBmp_SRCCOPY) == 1) /* restore original destination bitmap */ gdi_SelectObject(hdcSrc, (HGDIOBJECT) hBmpDstOriginal); gdi_BitBlt(hdcDst, 0, 0, 16, 16, hdcSrc, 0, 0, GDI_SRCCOPY); gdi_SelectObject(hdcSrc, (HGDIOBJECT) hBmpSrc); /* BLACKNESS */ gdi_BitBlt(hdcDst, 0, 0, 16, 16, hdcSrc, 0, 0, GDI_BLACKNESS); CU_ASSERT(CompareBitmaps(hBmpDst, hBmp_BLACKNESS) == 1); /* restore original destination bitmap */ gdi_SelectObject(hdcSrc, (HGDIOBJECT) hBmpDstOriginal); gdi_BitBlt(hdcDst, 0, 0, 16, 16, hdcSrc, 0, 0, GDI_SRCCOPY); gdi_SelectObject(hdcSrc, (HGDIOBJECT) hBmpSrc); /* WHITENESS */ gdi_BitBlt(hdcDst, 0, 0, 16, 16, hdcSrc, 0, 0, GDI_WHITENESS); CU_ASSERT(CompareBitmaps(hBmpDst, hBmp_WHITENESS) == 1); /* restore original destination bitmap */ gdi_SelectObject(hdcSrc, (HGDIOBJECT) hBmpDstOriginal); gdi_BitBlt(hdcDst, 0, 0, 16, 16, hdcSrc, 0, 0, GDI_SRCCOPY); gdi_SelectObject(hdcSrc, (HGDIOBJECT) hBmpSrc); /* SRCAND */ gdi_BitBlt(hdcDst, 0, 0, 16, 16, hdcSrc, 0, 0, GDI_SRCAND); CU_ASSERT(CompareBitmaps(hBmpDst, hBmp_SRCAND) == 1); /* restore original destination bitmap */ gdi_SelectObject(hdcSrc, (HGDIOBJECT) hBmpDstOriginal); gdi_BitBlt(hdcDst, 0, 0, 16, 16, hdcSrc, 0, 0, GDI_SRCCOPY); gdi_SelectObject(hdcSrc, (HGDIOBJECT) hBmpSrc); /* SRCPAINT */ gdi_BitBlt(hdcDst, 0, 0, 16, 16, hdcSrc, 0, 0, GDI_SRCPAINT); CU_ASSERT(CompareBitmaps(hBmpDst, hBmp_SRCPAINT) == 1); /* restore original destination bitmap */ gdi_SelectObject(hdcSrc, (HGDIOBJECT) hBmpDstOriginal); gdi_BitBlt(hdcDst, 0, 0, 16, 16, hdcSrc, 0, 0, GDI_SRCCOPY); gdi_SelectObject(hdcSrc, (HGDIOBJECT) hBmpSrc); /* SRCINVERT */ gdi_BitBlt(hdcDst, 0, 0, 16, 16, hdcSrc, 0, 0, GDI_SRCINVERT); CU_ASSERT(CompareBitmaps(hBmpDst, hBmp_SRCINVERT) == 1); /* restore original destination bitmap */ gdi_SelectObject(hdcSrc, (HGDIOBJECT) hBmpDstOriginal); gdi_BitBlt(hdcDst, 0, 0, 16, 16, hdcSrc, 0, 0, GDI_SRCCOPY); gdi_SelectObject(hdcSrc, (HGDIOBJECT) hBmpSrc); /* SRCERASE */ gdi_BitBlt(hdcDst, 0, 0, 16, 16, hdcSrc, 0, 0, GDI_SRCERASE); CU_ASSERT(CompareBitmaps(hBmpDst, hBmp_SRCERASE) == 1); /* restore original destination bitmap */ gdi_SelectObject(hdcSrc, (HGDIOBJECT) hBmpDstOriginal); gdi_BitBlt(hdcDst, 0, 0, 16, 16, hdcSrc, 0, 0, GDI_SRCCOPY); gdi_SelectObject(hdcSrc, (HGDIOBJECT) hBmpSrc); /* NOTSRCCOPY */ gdi_BitBlt(hdcDst, 0, 0, 16, 16, hdcSrc, 0, 0, GDI_NOTSRCCOPY); CU_ASSERT(CompareBitmaps(hBmpDst, hBmp_NOTSRCCOPY) == 1); /* restore original destination bitmap */ gdi_SelectObject(hdcSrc, (HGDIOBJECT) hBmpDstOriginal); gdi_BitBlt(hdcDst, 0, 0, 16, 16, hdcSrc, 0, 0, GDI_SRCCOPY); gdi_SelectObject(hdcSrc, (HGDIOBJECT) hBmpSrc); /* NOTSRCERASE */ gdi_BitBlt(hdcDst, 0, 0, 16, 16, hdcSrc, 0, 0, GDI_NOTSRCERASE); CU_ASSERT(CompareBitmaps(hBmpDst, hBmp_NOTSRCERASE) == 1); /* restore original destination bitmap */ gdi_SelectObject(hdcSrc, (HGDIOBJECT) hBmpDstOriginal); gdi_BitBlt(hdcDst, 0, 0, 16, 16, hdcSrc, 0, 0, GDI_SRCCOPY); gdi_SelectObject(hdcSrc, (HGDIOBJECT) hBmpSrc); /* DSTINVERT */ gdi_BitBlt(hdcDst, 0, 0, 16, 16, hdcSrc, 0, 0, GDI_DSTINVERT); CU_ASSERT(CompareBitmaps(hBmpDst, hBmp_DSTINVERT) == 1); /* select a brush for operations using a pattern */ hBrush = gdi_CreatePatternBrush(hBmpPat); gdi_SelectObject(hdcDst, (HGDIOBJECT) hBrush); /* restore original destination bitmap */ gdi_SelectObject(hdcSrc, (HGDIOBJECT) hBmpDstOriginal); gdi_BitBlt(hdcDst, 0, 0, 16, 16, hdcSrc, 0, 0, GDI_SRCCOPY); gdi_SelectObject(hdcSrc, (HGDIOBJECT) hBmpSrc); /* MERGECOPY */ gdi_BitBlt(hdcDst, 0, 0, 16, 16, hdcSrc, 0, 0, GDI_MERGECOPY); CU_ASSERT(CompareBitmaps(hBmpDst, hBmp_MERGECOPY) == 1); /* restore original destination bitmap */ gdi_SelectObject(hdcSrc, (HGDIOBJECT) hBmpDstOriginal); gdi_BitBlt(hdcDst, 0, 0, 16, 16, hdcSrc, 0, 0, GDI_SRCCOPY); gdi_SelectObject(hdcSrc, (HGDIOBJECT) hBmpSrc); /* MERGEPAINT */ gdi_BitBlt(hdcDst, 0, 0, 16, 16, hdcSrc, 0, 0, GDI_MERGEPAINT); CU_ASSERT(CompareBitmaps(hBmpDst, hBmp_MERGEPAINT) == 1); /* restore original destination bitmap */ gdi_SelectObject(hdcSrc, (HGDIOBJECT) hBmpDstOriginal); gdi_BitBlt(hdcDst, 0, 0, 16, 16, hdcSrc, 0, 0, GDI_SRCCOPY); gdi_SelectObject(hdcSrc, (HGDIOBJECT) hBmpSrc); /* PATCOPY */ gdi_BitBlt(hdcDst, 0, 0, 16, 16, hdcSrc, 0, 0, GDI_PATCOPY); CU_ASSERT(CompareBitmaps(hBmpDst, hBmp_PATCOPY) == 1); /* restore original destination bitmap */ gdi_SelectObject(hdcSrc, (HGDIOBJECT) hBmpDstOriginal); gdi_BitBlt(hdcDst, 0, 0, 16, 16, hdcSrc, 0, 0, GDI_SRCCOPY); gdi_SelectObject(hdcSrc, (HGDIOBJECT) hBmpSrc); /* PATINVERT */ gdi_BitBlt(hdcDst, 0, 0, 16, 16, hdcSrc, 0, 0, GDI_PATINVERT); CU_ASSERT(CompareBitmaps(hBmpDst, hBmp_PATINVERT) == 1); /* restore original destination bitmap */ gdi_SelectObject(hdcSrc, (HGDIOBJECT) hBmpDstOriginal); gdi_BitBlt(hdcDst, 0, 0, 16, 16, hdcSrc, 0, 0, GDI_SRCCOPY); gdi_SelectObject(hdcSrc, (HGDIOBJECT) hBmpSrc); /* PATPAINT */ gdi_BitBlt(hdcDst, 0, 0, 16, 16, hdcSrc, 0, 0, GDI_PATPAINT); CU_ASSERT(CompareBitmaps(hBmpDst, hBmp_PATPAINT) == 1); /* restore original destination bitmap */ gdi_SelectObject(hdcSrc, (HGDIOBJECT) hBmpDstOriginal); gdi_BitBlt(hdcDst, 0, 0, 16, 16, hdcSrc, 0, 0, GDI_SRCCOPY); gdi_SelectObject(hdcSrc, (HGDIOBJECT) hBmpSrc); /* SPna */ gdi_BitBlt(hdcDst, 0, 0, 16, 16, hdcSrc, 0, 0, GDI_SPna); CU_ASSERT(CompareBitmaps(hBmpDst, hBmp_SPna) == 1) } void test_gdi_BitBlt_16bpp(void) { uint8* data; HGDI_DC hdcSrc; HGDI_DC hdcDst; HGDI_BRUSH hBrush; HGDI_BITMAP hBmpSrc; HGDI_BITMAP hBmpDst; HGDI_BITMAP hBmpPat; HGDI_BITMAP hBmp_SPna; HGDI_BITMAP hBmp_BLACKNESS; HGDI_BITMAP hBmp_WHITENESS; HGDI_BITMAP hBmp_SRCCOPY; HGDI_BITMAP hBmp_SRCAND; HGDI_BITMAP hBmp_SRCPAINT; HGDI_BITMAP hBmp_SRCINVERT; HGDI_BITMAP hBmp_SRCERASE; HGDI_BITMAP hBmp_NOTSRCCOPY; HGDI_BITMAP hBmp_NOTSRCERASE; HGDI_BITMAP hBmp_DSTINVERT; HGDI_BITMAP hBmp_MERGECOPY; HGDI_BITMAP hBmp_MERGEPAINT; HGDI_BITMAP hBmp_PATCOPY; HGDI_BITMAP hBmp_PATPAINT; HGDI_BITMAP hBmp_PATINVERT; HGDI_BITMAP hBmpDstOriginal; rdpPalette* hPalette; HCLRCONV clrconv; int bytesPerPixel = 2; int bitsPerPixel = 16; hdcSrc = gdi_GetDC(); hdcSrc->bytesPerPixel = bytesPerPixel; hdcSrc->bitsPerPixel = bitsPerPixel; hdcDst = gdi_GetDC(); hdcDst->bytesPerPixel = bytesPerPixel; hdcDst->bitsPerPixel = bitsPerPixel; hPalette = (rdpPalette*) gdi_GetSystemPalette(); clrconv = (HCLRCONV) malloc(sizeof(CLRCONV)); clrconv->alpha = 1; clrconv->invert = 0; clrconv->palette = hPalette; data = (uint8*) freerdp_image_convert((uint8*) bmp_SRC, NULL, 16, 16, 8, bitsPerPixel, clrconv); hBmpSrc = gdi_CreateBitmap(16, 16, bitsPerPixel, data); data = (uint8*) freerdp_image_convert((uint8*) bmp_DST, NULL, 16, 16, 8, bitsPerPixel, clrconv); hBmpDst = gdi_CreateBitmap(16, 16, bitsPerPixel, data); data = (uint8*) freerdp_image_convert((uint8*) bmp_DST, NULL, 16, 16, 8, bitsPerPixel, clrconv); hBmpDstOriginal = gdi_CreateBitmap(16, 16, bitsPerPixel, data); data = (uint8*) freerdp_image_convert((uint8*) bmp_PAT, NULL, 8, 8, 8, bitsPerPixel, clrconv); hBmpPat = gdi_CreateBitmap(8, 8, bitsPerPixel, data); data = (uint8*) freerdp_image_convert((uint8*) bmp_SRCCOPY, NULL, 16, 16, 8, bitsPerPixel, clrconv); hBmp_SRCCOPY = gdi_CreateBitmap(16, 16, bitsPerPixel, data); data = (uint8*) freerdp_image_convert((uint8*) bmp_SPna, NULL, 16, 16, 8, bitsPerPixel, clrconv); hBmp_SPna = gdi_CreateBitmap(16, 16, bitsPerPixel, data); data = (uint8*) freerdp_image_convert((uint8*) bmp_BLACKNESS, NULL, 16, 16, 8, bitsPerPixel, clrconv); hBmp_BLACKNESS = gdi_CreateBitmap(16, 16, bitsPerPixel, data); data = (uint8*) freerdp_image_convert((uint8*) bmp_WHITENESS, NULL, 16, 16, 8, bitsPerPixel, clrconv); hBmp_WHITENESS = gdi_CreateBitmap(16, 16, bitsPerPixel, data); data = (uint8*) freerdp_image_convert((uint8*) bmp_SRCAND, NULL, 16, 16, 8, bitsPerPixel, clrconv); hBmp_SRCAND = gdi_CreateBitmap(16, 16, bitsPerPixel, data); data = (uint8*) freerdp_image_convert((uint8*) bmp_SRCPAINT, NULL, 16, 16, 8, bitsPerPixel, clrconv); hBmp_SRCPAINT = gdi_CreateBitmap(16, 16, bitsPerPixel, data); data = (uint8*) freerdp_image_convert((uint8*) bmp_SRCINVERT, NULL, 16, 16, 8, bitsPerPixel, clrconv); hBmp_SRCINVERT = gdi_CreateBitmap(16, 16, bitsPerPixel, data); data = (uint8*) freerdp_image_convert((uint8*) bmp_SRCERASE, NULL, 16, 16, 8, bitsPerPixel, clrconv); hBmp_SRCERASE = gdi_CreateBitmap(16, 16, bitsPerPixel, data); data = (uint8*) freerdp_image_convert((uint8*) bmp_NOTSRCCOPY, NULL, 16, 16, 8, bitsPerPixel, clrconv); hBmp_NOTSRCCOPY = gdi_CreateBitmap(16, 16, bitsPerPixel, data); data = (uint8*) freerdp_image_convert((uint8*) bmp_NOTSRCERASE, NULL, 16, 16, 8, bitsPerPixel, clrconv); hBmp_NOTSRCERASE = gdi_CreateBitmap(16, 16, bitsPerPixel, data); data = (uint8*) freerdp_image_convert((uint8*) bmp_DSTINVERT, NULL, 16, 16, 8, bitsPerPixel, clrconv); hBmp_DSTINVERT = gdi_CreateBitmap(16, 16, bitsPerPixel, data); data = (uint8*) freerdp_image_convert((uint8*) bmp_MERGECOPY, NULL, 16, 16, 8, bitsPerPixel, clrconv); hBmp_MERGECOPY = gdi_CreateBitmap(16, 16, bitsPerPixel, data); data = (uint8*) freerdp_image_convert((uint8*) bmp_MERGEPAINT, NULL, 16, 16, 8, bitsPerPixel, clrconv); hBmp_MERGEPAINT = gdi_CreateBitmap(16, 16, bitsPerPixel, data); data = (uint8*) freerdp_image_convert((uint8*) bmp_PATCOPY, NULL, 16, 16, 8, bitsPerPixel, clrconv); hBmp_PATCOPY = gdi_CreateBitmap(16, 16, bitsPerPixel, data); data = (uint8*) freerdp_image_convert((uint8*) bmp_PATPAINT, NULL, 16, 16, 8, bitsPerPixel, clrconv); hBmp_PATPAINT = gdi_CreateBitmap(16, 16, bitsPerPixel, data); data = (uint8*) freerdp_image_convert((uint8*) bmp_PATINVERT, NULL, 16, 16, 8, bitsPerPixel, clrconv); hBmp_PATINVERT = gdi_CreateBitmap(16, 16, bitsPerPixel, data); gdi_SelectObject(hdcSrc, (HGDIOBJECT) hBmpSrc); gdi_SelectObject(hdcDst, (HGDIOBJECT) hBmpDst); /* SRCCOPY */ gdi_BitBlt(hdcDst, 0, 0, 16, 16, hdcSrc, 0, 0, GDI_SRCCOPY); CU_ASSERT(CompareBitmaps(hBmpDst, hBmp_SRCCOPY) == 1) /* restore original destination bitmap */ gdi_SelectObject(hdcSrc, (HGDIOBJECT) hBmpDstOriginal); gdi_BitBlt(hdcDst, 0, 0, 16, 16, hdcSrc, 0, 0, GDI_SRCCOPY); gdi_SelectObject(hdcSrc, (HGDIOBJECT) hBmpSrc); /* BLACKNESS */ gdi_BitBlt(hdcDst, 0, 0, 16, 16, hdcSrc, 0, 0, GDI_BLACKNESS); CU_ASSERT(CompareBitmaps(hBmpDst, hBmp_BLACKNESS) == 1); /* restore original destination bitmap */ gdi_SelectObject(hdcSrc, (HGDIOBJECT) hBmpDstOriginal); gdi_BitBlt(hdcDst, 0, 0, 16, 16, hdcSrc, 0, 0, GDI_SRCCOPY); gdi_SelectObject(hdcSrc, (HGDIOBJECT) hBmpSrc); /* WHITENESS */ gdi_BitBlt(hdcDst, 0, 0, 16, 16, hdcSrc, 0, 0, GDI_WHITENESS); CU_ASSERT(CompareBitmaps(hBmpDst, hBmp_WHITENESS) == 1); /* restore original destination bitmap */ gdi_SelectObject(hdcSrc, (HGDIOBJECT) hBmpDstOriginal); gdi_BitBlt(hdcDst, 0, 0, 16, 16, hdcSrc, 0, 0, GDI_SRCCOPY); gdi_SelectObject(hdcSrc, (HGDIOBJECT) hBmpSrc); /* SRCAND */ gdi_BitBlt(hdcDst, 0, 0, 16, 16, hdcSrc, 0, 0, GDI_SRCAND); CU_ASSERT(CompareBitmaps(hBmpDst, hBmp_SRCAND) == 1); /* restore original destination bitmap */ gdi_SelectObject(hdcSrc, (HGDIOBJECT) hBmpDstOriginal); gdi_BitBlt(hdcDst, 0, 0, 16, 16, hdcSrc, 0, 0, GDI_SRCCOPY); gdi_SelectObject(hdcSrc, (HGDIOBJECT) hBmpSrc); /* SRCPAINT */ gdi_BitBlt(hdcDst, 0, 0, 16, 16, hdcSrc, 0, 0, GDI_SRCPAINT); CU_ASSERT(CompareBitmaps(hBmpDst, hBmp_SRCPAINT) == 1); /* restore original destination bitmap */ gdi_SelectObject(hdcSrc, (HGDIOBJECT) hBmpDstOriginal); gdi_BitBlt(hdcDst, 0, 0, 16, 16, hdcSrc, 0, 0, GDI_SRCCOPY); gdi_SelectObject(hdcSrc, (HGDIOBJECT) hBmpSrc); /* SRCINVERT */ gdi_BitBlt(hdcDst, 0, 0, 16, 16, hdcSrc, 0, 0, GDI_SRCINVERT); CU_ASSERT(CompareBitmaps(hBmpDst, hBmp_SRCINVERT) == 1); /* restore original destination bitmap */ gdi_SelectObject(hdcSrc, (HGDIOBJECT) hBmpDstOriginal); gdi_BitBlt(hdcDst, 0, 0, 16, 16, hdcSrc, 0, 0, GDI_SRCCOPY); gdi_SelectObject(hdcSrc, (HGDIOBJECT) hBmpSrc); /* SRCERASE */ gdi_BitBlt(hdcDst, 0, 0, 16, 16, hdcSrc, 0, 0, GDI_SRCERASE); CU_ASSERT(CompareBitmaps(hBmpDst, hBmp_SRCERASE) == 1); /* restore original destination bitmap */ gdi_SelectObject(hdcSrc, (HGDIOBJECT) hBmpDstOriginal); gdi_BitBlt(hdcDst, 0, 0, 16, 16, hdcSrc, 0, 0, GDI_SRCCOPY); gdi_SelectObject(hdcSrc, (HGDIOBJECT) hBmpSrc); /* NOTSRCCOPY */ gdi_BitBlt(hdcDst, 0, 0, 16, 16, hdcSrc, 0, 0, GDI_NOTSRCCOPY); CU_ASSERT(CompareBitmaps(hBmpDst, hBmp_NOTSRCCOPY) == 1); /* restore original destination bitmap */ gdi_SelectObject(hdcSrc, (HGDIOBJECT) hBmpDstOriginal); gdi_BitBlt(hdcDst, 0, 0, 16, 16, hdcSrc, 0, 0, GDI_SRCCOPY); gdi_SelectObject(hdcSrc, (HGDIOBJECT) hBmpSrc); /* NOTSRCERASE */ gdi_BitBlt(hdcDst, 0, 0, 16, 16, hdcSrc, 0, 0, GDI_NOTSRCERASE); CU_ASSERT(CompareBitmaps(hBmpDst, hBmp_NOTSRCERASE) == 1); /* restore original destination bitmap */ gdi_SelectObject(hdcSrc, (HGDIOBJECT) hBmpDstOriginal); gdi_BitBlt(hdcDst, 0, 0, 16, 16, hdcSrc, 0, 0, GDI_SRCCOPY); gdi_SelectObject(hdcSrc, (HGDIOBJECT) hBmpSrc); /* DSTINVERT */ gdi_BitBlt(hdcDst, 0, 0, 16, 16, hdcSrc, 0, 0, GDI_DSTINVERT); CU_ASSERT(CompareBitmaps(hBmpDst, hBmp_DSTINVERT) == 1); /* select a brush for operations using a pattern */ hBrush = gdi_CreatePatternBrush(hBmpPat); gdi_SelectObject(hdcDst, (HGDIOBJECT) hBrush); /* restore original destination bitmap */ gdi_SelectObject(hdcSrc, (HGDIOBJECT) hBmpDstOriginal); gdi_BitBlt(hdcDst, 0, 0, 16, 16, hdcSrc, 0, 0, GDI_SRCCOPY); gdi_SelectObject(hdcSrc, (HGDIOBJECT) hBmpSrc); /* MERGECOPY */ gdi_BitBlt(hdcDst, 0, 0, 16, 16, hdcSrc, 0, 0, GDI_MERGECOPY); CU_ASSERT(CompareBitmaps(hBmpDst, hBmp_MERGECOPY) == 1); /* restore original destination bitmap */ gdi_SelectObject(hdcSrc, (HGDIOBJECT) hBmpDstOriginal); gdi_BitBlt(hdcDst, 0, 0, 16, 16, hdcSrc, 0, 0, GDI_SRCCOPY); gdi_SelectObject(hdcSrc, (HGDIOBJECT) hBmpSrc); /* MERGEPAINT */ gdi_BitBlt(hdcDst, 0, 0, 16, 16, hdcSrc, 0, 0, GDI_MERGEPAINT); CU_ASSERT(CompareBitmaps(hBmpDst, hBmp_MERGEPAINT) == 1); /* restore original destination bitmap */ gdi_SelectObject(hdcSrc, (HGDIOBJECT) hBmpDstOriginal); gdi_BitBlt(hdcDst, 0, 0, 16, 16, hdcSrc, 0, 0, GDI_SRCCOPY); gdi_SelectObject(hdcSrc, (HGDIOBJECT) hBmpSrc); /* PATCOPY */ gdi_BitBlt(hdcDst, 0, 0, 16, 16, hdcSrc, 0, 0, GDI_PATCOPY); CU_ASSERT(CompareBitmaps(hBmpDst, hBmp_PATCOPY) == 1); /* restore original destination bitmap */ gdi_SelectObject(hdcSrc, (HGDIOBJECT) hBmpDstOriginal); gdi_BitBlt(hdcDst, 0, 0, 16, 16, hdcSrc, 0, 0, GDI_SRCCOPY); gdi_SelectObject(hdcSrc, (HGDIOBJECT) hBmpSrc); /* PATINVERT */ gdi_BitBlt(hdcDst, 0, 0, 16, 16, hdcSrc, 0, 0, GDI_PATINVERT); CU_ASSERT(CompareBitmaps(hBmpDst, hBmp_PATINVERT) == 1); /* restore original destination bitmap */ gdi_SelectObject(hdcSrc, (HGDIOBJECT) hBmpDstOriginal); gdi_BitBlt(hdcDst, 0, 0, 16, 16, hdcSrc, 0, 0, GDI_SRCCOPY); gdi_SelectObject(hdcSrc, (HGDIOBJECT) hBmpSrc); /* PATPAINT */ gdi_BitBlt(hdcDst, 0, 0, 16, 16, hdcSrc, 0, 0, GDI_PATPAINT); CU_ASSERT(CompareBitmaps(hBmpDst, hBmp_PATPAINT) == 1); /* restore original destination bitmap */ gdi_SelectObject(hdcSrc, (HGDIOBJECT) hBmpDstOriginal); gdi_BitBlt(hdcDst, 0, 0, 16, 16, hdcSrc, 0, 0, GDI_SRCCOPY); gdi_SelectObject(hdcSrc, (HGDIOBJECT) hBmpSrc); /* SPna */ gdi_BitBlt(hdcDst, 0, 0, 16, 16, hdcSrc, 0, 0, GDI_SPna); CU_ASSERT(CompareBitmaps(hBmpDst, hBmp_SPna) == 1) } void test_gdi_BitBlt_8bpp(void) { uint8* data; HGDI_DC hdcSrc; HGDI_DC hdcDst; HGDI_BRUSH hBrush; HGDI_BITMAP hBmpSrc; HGDI_BITMAP hBmpDst; HGDI_BITMAP hBmpPat; HGDI_BITMAP hBmp_SPna; HGDI_BITMAP hBmp_BLACKNESS; HGDI_BITMAP hBmp_WHITENESS; HGDI_BITMAP hBmp_SRCCOPY; HGDI_BITMAP hBmp_SRCAND; HGDI_BITMAP hBmp_SRCPAINT; HGDI_BITMAP hBmp_SRCINVERT; HGDI_BITMAP hBmp_SRCERASE; HGDI_BITMAP hBmp_NOTSRCCOPY; HGDI_BITMAP hBmp_NOTSRCERASE; HGDI_BITMAP hBmp_DSTINVERT; HGDI_BITMAP hBmp_MERGECOPY; HGDI_BITMAP hBmp_MERGEPAINT; HGDI_BITMAP hBmp_PATCOPY; HGDI_BITMAP hBmp_PATPAINT; HGDI_BITMAP hBmp_PATINVERT; HGDI_BITMAP hBmpDstOriginal; rdpPalette* hPalette; HCLRCONV clrconv; int bytesPerPixel = 1; int bitsPerPixel = 8; hdcSrc = gdi_GetDC(); hdcSrc->bytesPerPixel = bytesPerPixel; hdcSrc->bitsPerPixel = bitsPerPixel; hdcDst = gdi_GetDC(); hdcDst->bytesPerPixel = bytesPerPixel; hdcDst->bitsPerPixel = bitsPerPixel; hPalette = (rdpPalette*) gdi_GetSystemPalette(); clrconv = (HCLRCONV) malloc(sizeof(CLRCONV)); clrconv->alpha = 1; clrconv->invert = 0; clrconv->palette = hPalette; data = (uint8*) freerdp_image_convert((uint8*) bmp_SRC, NULL, 16, 16, 8, bitsPerPixel, clrconv); hBmpSrc = gdi_CreateBitmap(16, 16, bitsPerPixel, data); data = (uint8*) freerdp_image_convert((uint8*) bmp_DST, NULL, 16, 16, 8, bitsPerPixel, clrconv); hBmpDst = gdi_CreateBitmap(16, 16, bitsPerPixel, data); data = (uint8*) freerdp_image_convert((uint8*) bmp_DST, NULL, 16, 16, 8, bitsPerPixel, clrconv); hBmpDstOriginal = gdi_CreateBitmap(16, 16, bitsPerPixel, data); data = (uint8*) freerdp_image_convert((uint8*) bmp_PAT, NULL, 8, 8, 8, bitsPerPixel, clrconv); hBmpPat = gdi_CreateBitmap(8, 8, bitsPerPixel, data); data = (uint8*) freerdp_image_convert((uint8*) bmp_SRCCOPY, NULL, 16, 16, 8, bitsPerPixel, clrconv); hBmp_SRCCOPY = gdi_CreateBitmap(16, 16, bitsPerPixel, data); data = (uint8*) freerdp_image_convert((uint8*) bmp_SPna, NULL, 16, 16, 8, bitsPerPixel, clrconv); hBmp_SPna = gdi_CreateBitmap(16, 16, bitsPerPixel, data); data = (uint8*) freerdp_image_convert((uint8*) bmp_BLACKNESS, NULL, 16, 16, 8, bitsPerPixel, clrconv); hBmp_BLACKNESS = gdi_CreateBitmap(16, 16, bitsPerPixel, data); data = (uint8*) freerdp_image_convert((uint8*) bmp_WHITENESS, NULL, 16, 16, 8, bitsPerPixel, clrconv); hBmp_WHITENESS = gdi_CreateBitmap(16, 16, bitsPerPixel, data); data = (uint8*) freerdp_image_convert((uint8*) bmp_SRCAND, NULL, 16, 16, 8, bitsPerPixel, clrconv); hBmp_SRCAND = gdi_CreateBitmap(16, 16, bitsPerPixel, data); data = (uint8*) freerdp_image_convert((uint8*) bmp_SRCPAINT, NULL, 16, 16, 8, bitsPerPixel, clrconv); hBmp_SRCPAINT = gdi_CreateBitmap(16, 16, bitsPerPixel, data); data = (uint8*) freerdp_image_convert((uint8*) bmp_SRCINVERT, NULL, 16, 16, 8, bitsPerPixel, clrconv); hBmp_SRCINVERT = gdi_CreateBitmap(16, 16, bitsPerPixel, data); data = (uint8*) freerdp_image_convert((uint8*) bmp_SRCERASE, NULL, 16, 16, 8, bitsPerPixel, clrconv); hBmp_SRCERASE = gdi_CreateBitmap(16, 16, bitsPerPixel, data); data = (uint8*) freerdp_image_convert((uint8*) bmp_NOTSRCCOPY, NULL, 16, 16, 8, bitsPerPixel, clrconv); hBmp_NOTSRCCOPY = gdi_CreateBitmap(16, 16, bitsPerPixel, data); data = (uint8*) freerdp_image_convert((uint8*) bmp_NOTSRCERASE, NULL, 16, 16, 8, bitsPerPixel, clrconv); hBmp_NOTSRCERASE = gdi_CreateBitmap(16, 16, bitsPerPixel, data); data = (uint8*) freerdp_image_convert((uint8*) bmp_DSTINVERT, NULL, 16, 16, 8, bitsPerPixel, clrconv); hBmp_DSTINVERT = gdi_CreateBitmap(16, 16, bitsPerPixel, data); data = (uint8*) freerdp_image_convert((uint8*) bmp_MERGECOPY, NULL, 16, 16, 8, bitsPerPixel, clrconv); hBmp_MERGECOPY = gdi_CreateBitmap(16, 16, bitsPerPixel, data); data = (uint8*) freerdp_image_convert((uint8*) bmp_MERGEPAINT, NULL, 16, 16, 8, bitsPerPixel, clrconv); hBmp_MERGEPAINT = gdi_CreateBitmap(16, 16, bitsPerPixel, data); data = (uint8*) freerdp_image_convert((uint8*) bmp_PATCOPY, NULL, 16, 16, 8, bitsPerPixel, clrconv); hBmp_PATCOPY = gdi_CreateBitmap(16, 16, bitsPerPixel, data); data = (uint8*) freerdp_image_convert((uint8*) bmp_PATPAINT, NULL, 16, 16, 8, bitsPerPixel, clrconv); hBmp_PATPAINT = gdi_CreateBitmap(16, 16, bitsPerPixel, data); data = (uint8*) freerdp_image_convert((uint8*) bmp_PATINVERT, NULL, 16, 16, 8, bitsPerPixel, clrconv); hBmp_PATINVERT = gdi_CreateBitmap(16, 16, bitsPerPixel, data); gdi_SelectObject(hdcSrc, (HGDIOBJECT) hBmpSrc); gdi_SelectObject(hdcDst, (HGDIOBJECT) hBmpDst); /* SRCCOPY */ gdi_BitBlt(hdcDst, 0, 0, 16, 16, hdcSrc, 0, 0, GDI_SRCCOPY); CU_ASSERT(CompareBitmaps(hBmpDst, hBmp_SRCCOPY) == 1) /* restore original destination bitmap */ gdi_SelectObject(hdcSrc, (HGDIOBJECT) hBmpDstOriginal); gdi_BitBlt(hdcDst, 0, 0, 16, 16, hdcSrc, 0, 0, GDI_SRCCOPY); gdi_SelectObject(hdcSrc, (HGDIOBJECT) hBmpSrc); /* BLACKNESS */ gdi_BitBlt(hdcDst, 0, 0, 16, 16, hdcSrc, 0, 0, GDI_BLACKNESS); CU_ASSERT(CompareBitmaps(hBmpDst, hBmp_BLACKNESS) == 1); /* restore original destination bitmap */ gdi_SelectObject(hdcSrc, (HGDIOBJECT) hBmpDstOriginal); gdi_BitBlt(hdcDst, 0, 0, 16, 16, hdcSrc, 0, 0, GDI_SRCCOPY); gdi_SelectObject(hdcSrc, (HGDIOBJECT) hBmpSrc); /* WHITENESS */ gdi_BitBlt(hdcDst, 0, 0, 16, 16, hdcSrc, 0, 0, GDI_WHITENESS); CU_ASSERT(CompareBitmaps(hBmpDst, hBmp_WHITENESS) == 1); /* restore original destination bitmap */ gdi_SelectObject(hdcSrc, (HGDIOBJECT) hBmpDstOriginal); gdi_BitBlt(hdcDst, 0, 0, 16, 16, hdcSrc, 0, 0, GDI_SRCCOPY); gdi_SelectObject(hdcSrc, (HGDIOBJECT) hBmpSrc); /* SRCAND */ gdi_BitBlt(hdcDst, 0, 0, 16, 16, hdcSrc, 0, 0, GDI_SRCAND); CU_ASSERT(CompareBitmaps(hBmpDst, hBmp_SRCAND) == 1); /* restore original destination bitmap */ gdi_SelectObject(hdcSrc, (HGDIOBJECT) hBmpDstOriginal); gdi_BitBlt(hdcDst, 0, 0, 16, 16, hdcSrc, 0, 0, GDI_SRCCOPY); gdi_SelectObject(hdcSrc, (HGDIOBJECT) hBmpSrc); /* SRCPAINT */ gdi_BitBlt(hdcDst, 0, 0, 16, 16, hdcSrc, 0, 0, GDI_SRCPAINT); CU_ASSERT(CompareBitmaps(hBmpDst, hBmp_SRCPAINT) == 1); /* restore original destination bitmap */ gdi_SelectObject(hdcSrc, (HGDIOBJECT) hBmpDstOriginal); gdi_BitBlt(hdcDst, 0, 0, 16, 16, hdcSrc, 0, 0, GDI_SRCCOPY); gdi_SelectObject(hdcSrc, (HGDIOBJECT) hBmpSrc); /* SRCINVERT */ gdi_BitBlt(hdcDst, 0, 0, 16, 16, hdcSrc, 0, 0, GDI_SRCINVERT); CU_ASSERT(CompareBitmaps(hBmpDst, hBmp_SRCINVERT) == 1); /* restore original destination bitmap */ gdi_SelectObject(hdcSrc, (HGDIOBJECT) hBmpDstOriginal); gdi_BitBlt(hdcDst, 0, 0, 16, 16, hdcSrc, 0, 0, GDI_SRCCOPY); gdi_SelectObject(hdcSrc, (HGDIOBJECT) hBmpSrc); /* SRCERASE */ gdi_BitBlt(hdcDst, 0, 0, 16, 16, hdcSrc, 0, 0, GDI_SRCERASE); CU_ASSERT(CompareBitmaps(hBmpDst, hBmp_SRCERASE) == 1); /* restore original destination bitmap */ gdi_SelectObject(hdcSrc, (HGDIOBJECT) hBmpDstOriginal); gdi_BitBlt(hdcDst, 0, 0, 16, 16, hdcSrc, 0, 0, GDI_SRCCOPY); gdi_SelectObject(hdcSrc, (HGDIOBJECT) hBmpSrc); /* NOTSRCCOPY */ gdi_BitBlt(hdcDst, 0, 0, 16, 16, hdcSrc, 0, 0, GDI_NOTSRCCOPY); CU_ASSERT(CompareBitmaps(hBmpDst, hBmp_NOTSRCCOPY) == 1); /* restore original destination bitmap */ gdi_SelectObject(hdcSrc, (HGDIOBJECT) hBmpDstOriginal); gdi_BitBlt(hdcDst, 0, 0, 16, 16, hdcSrc, 0, 0, GDI_SRCCOPY); gdi_SelectObject(hdcSrc, (HGDIOBJECT) hBmpSrc); /* NOTSRCERASE */ gdi_BitBlt(hdcDst, 0, 0, 16, 16, hdcSrc, 0, 0, GDI_NOTSRCERASE); CU_ASSERT(CompareBitmaps(hBmpDst, hBmp_NOTSRCERASE) == 1); /* restore original destination bitmap */ gdi_SelectObject(hdcSrc, (HGDIOBJECT) hBmpDstOriginal); gdi_BitBlt(hdcDst, 0, 0, 16, 16, hdcSrc, 0, 0, GDI_SRCCOPY); gdi_SelectObject(hdcSrc, (HGDIOBJECT) hBmpSrc); /* DSTINVERT */ gdi_BitBlt(hdcDst, 0, 0, 16, 16, hdcSrc, 0, 0, GDI_DSTINVERT); CU_ASSERT(CompareBitmaps(hBmpDst, hBmp_DSTINVERT) == 1); /* select a brush for operations using a pattern */ hBrush = gdi_CreatePatternBrush(hBmpPat); gdi_SelectObject(hdcDst, (HGDIOBJECT) hBrush); /* restore original destination bitmap */ gdi_SelectObject(hdcSrc, (HGDIOBJECT) hBmpDstOriginal); gdi_BitBlt(hdcDst, 0, 0, 16, 16, hdcSrc, 0, 0, GDI_SRCCOPY); gdi_SelectObject(hdcSrc, (HGDIOBJECT) hBmpSrc); /* MERGECOPY */ gdi_BitBlt(hdcDst, 0, 0, 16, 16, hdcSrc, 0, 0, GDI_MERGECOPY); CU_ASSERT(CompareBitmaps(hBmpDst, hBmp_MERGECOPY) == 1); /* restore original destination bitmap */ gdi_SelectObject(hdcSrc, (HGDIOBJECT) hBmpDstOriginal); gdi_BitBlt(hdcDst, 0, 0, 16, 16, hdcSrc, 0, 0, GDI_SRCCOPY); gdi_SelectObject(hdcSrc, (HGDIOBJECT) hBmpSrc); /* MERGEPAINT */ gdi_BitBlt(hdcDst, 0, 0, 16, 16, hdcSrc, 0, 0, GDI_MERGEPAINT); CU_ASSERT(CompareBitmaps(hBmpDst, hBmp_MERGEPAINT) == 1); /* restore original destination bitmap */ gdi_SelectObject(hdcSrc, (HGDIOBJECT) hBmpDstOriginal); gdi_BitBlt(hdcDst, 0, 0, 16, 16, hdcSrc, 0, 0, GDI_SRCCOPY); gdi_SelectObject(hdcSrc, (HGDIOBJECT) hBmpSrc); /* PATCOPY */ gdi_BitBlt(hdcDst, 0, 0, 16, 16, hdcSrc, 0, 0, GDI_PATCOPY); CU_ASSERT(CompareBitmaps(hBmpDst, hBmp_PATCOPY) == 1); /* restore original destination bitmap */ gdi_SelectObject(hdcSrc, (HGDIOBJECT) hBmpDstOriginal); gdi_BitBlt(hdcDst, 0, 0, 16, 16, hdcSrc, 0, 0, GDI_SRCCOPY); gdi_SelectObject(hdcSrc, (HGDIOBJECT) hBmpSrc); /* PATINVERT */ gdi_BitBlt(hdcDst, 0, 0, 16, 16, hdcSrc, 0, 0, GDI_PATINVERT); CU_ASSERT(CompareBitmaps(hBmpDst, hBmp_PATINVERT) == 1); /* restore original destination bitmap */ gdi_SelectObject(hdcSrc, (HGDIOBJECT) hBmpDstOriginal); gdi_BitBlt(hdcDst, 0, 0, 16, 16, hdcSrc, 0, 0, GDI_SRCCOPY); gdi_SelectObject(hdcSrc, (HGDIOBJECT) hBmpSrc); /* PATPAINT */ gdi_BitBlt(hdcDst, 0, 0, 16, 16, hdcSrc, 0, 0, GDI_PATPAINT); CU_ASSERT(CompareBitmaps(hBmpDst, hBmp_PATPAINT) == 1); /* restore original destination bitmap */ gdi_SelectObject(hdcSrc, (HGDIOBJECT) hBmpDstOriginal); gdi_BitBlt(hdcDst, 0, 0, 16, 16, hdcSrc, 0, 0, GDI_SRCCOPY); gdi_SelectObject(hdcSrc, (HGDIOBJECT) hBmpSrc); /* SPna */ gdi_BitBlt(hdcDst, 0, 0, 16, 16, hdcSrc, 0, 0, GDI_SPna); CU_ASSERT(CompareBitmaps(hBmpDst, hBmp_SPna) == 1) } void test_gdi_ClipCoords(void) { HGDI_DC hdc; HGDI_RGN rgn1; HGDI_RGN rgn2; HGDI_BITMAP bmp; int draw; hdc = gdi_GetDC(); hdc->bytesPerPixel = 4; hdc->bitsPerPixel = 32; bmp = gdi_CreateBitmap(1024, 768, 4, NULL); gdi_SelectObject(hdc, (HGDIOBJECT) bmp); gdi_SetNullClipRgn(hdc); rgn1 = gdi_CreateRectRgn(0, 0, 0, 0); rgn2 = gdi_CreateRectRgn(0, 0, 0, 0); rgn1->null = 1; rgn2->null = 1; /* null clipping region */ gdi_SetNullClipRgn(hdc); gdi_SetRgn(rgn1, 20, 20, 100, 100); gdi_SetRgn(rgn2, 20, 20, 100, 100); gdi_ClipCoords(hdc, &(rgn1->x), &(rgn1->y), &(rgn1->w), &(rgn1->h), NULL, NULL); CU_ASSERT(gdi_EqualRgn(rgn1, rgn2) == 1); /* region all inside clipping region */ gdi_SetClipRgn(hdc, 0, 0, 1024, 768); gdi_SetRgn(rgn1, 20, 20, 100, 100); gdi_SetRgn(rgn2, 20, 20, 100, 100); gdi_ClipCoords(hdc, &(rgn1->x), &(rgn1->y), &(rgn1->w), &(rgn1->h), NULL, NULL); CU_ASSERT(gdi_EqualRgn(rgn1, rgn2) == 1); /* region all outside clipping region, on the left */ gdi_SetClipRgn(hdc, 300, 300, 100, 100); gdi_SetRgn(rgn1, 20, 20, 100, 100); gdi_SetRgn(rgn2, 0, 0, 0, 0); draw = gdi_ClipCoords(hdc, &(rgn1->x), &(rgn1->y), &(rgn1->w), &(rgn1->h), NULL, NULL); CU_ASSERT(draw == 0); /* region all outside clipping region, on the right */ gdi_SetClipRgn(hdc, 300, 300, 100, 100); gdi_SetRgn(rgn1, 420, 420, 100, 100); gdi_SetRgn(rgn2, 0, 0, 0, 0); draw = gdi_ClipCoords(hdc, &(rgn1->x), &(rgn1->y), &(rgn1->w), &(rgn1->h), NULL, NULL); CU_ASSERT(draw == 0); /* region all outside clipping region, on top */ gdi_SetClipRgn(hdc, 300, 300, 100, 100); gdi_SetRgn(rgn1, 300, 20, 100, 100); gdi_SetRgn(rgn2, 0, 0, 0, 0); draw = gdi_ClipCoords(hdc, &(rgn1->x), &(rgn1->y), &(rgn1->w), &(rgn1->h), NULL, NULL); CU_ASSERT(draw == 0); /* region all outside clipping region, at the bottom */ gdi_SetClipRgn(hdc, 300, 300, 100, 100); gdi_SetRgn(rgn1, 300, 420, 100, 100); gdi_SetRgn(rgn2, 0, 0, 0, 0); draw = gdi_ClipCoords(hdc, &(rgn1->x), &(rgn1->y), &(rgn1->w), &(rgn1->h), NULL, NULL); CU_ASSERT(draw == 0); /* left outside, right = clip, top = clip, bottom = clip */ gdi_SetClipRgn(hdc, 300, 300, 100, 100); gdi_SetRgn(rgn1, 100, 300, 300, 100); gdi_SetRgn(rgn2, 300, 300, 100, 100); gdi_ClipCoords(hdc, &(rgn1->x), &(rgn1->y), &(rgn1->w), &(rgn1->h), NULL, NULL); CU_ASSERT(gdi_EqualRgn(rgn1, rgn2) == 1); /* left outside, right inside, top = clip, bottom = clip */ gdi_SetClipRgn(hdc, 300, 300, 100, 100); gdi_SetRgn(rgn1, 100, 300, 250, 100); gdi_SetRgn(rgn2, 300, 300, 50, 100); gdi_ClipCoords(hdc, &(rgn1->x), &(rgn1->y), &(rgn1->w), &(rgn1->h), NULL, NULL); CU_ASSERT(gdi_EqualRgn(rgn1, rgn2) == 1); /* left = clip, right outside, top = clip, bottom = clip */ gdi_SetClipRgn(hdc, 300, 300, 100, 100); gdi_SetRgn(rgn1, 300, 300, 300, 100); gdi_SetRgn(rgn2, 300, 300, 100, 100); gdi_ClipCoords(hdc, &(rgn1->x), &(rgn1->y), &(rgn1->w), &(rgn1->h), NULL, NULL); CU_ASSERT(gdi_EqualRgn(rgn1, rgn2) == 1); /* left inside, right outside, top = clip, bottom = clip */ gdi_SetClipRgn(hdc, 300, 300, 100, 100); gdi_SetRgn(rgn1, 350, 300, 200, 100); gdi_SetRgn(rgn2, 350, 300, 50, 100); gdi_ClipCoords(hdc, &(rgn1->x), &(rgn1->y), &(rgn1->w), &(rgn1->h), NULL, NULL); CU_ASSERT(gdi_EqualRgn(rgn1, rgn2) == 1); /* top outside, bottom = clip, left = clip, right = clip */ gdi_SetClipRgn(hdc, 300, 300, 100, 100); gdi_SetRgn(rgn1, 300, 100, 300, 300); gdi_SetRgn(rgn2, 300, 300, 100, 100); gdi_ClipCoords(hdc, &(rgn1->x), &(rgn1->y), &(rgn1->w), &(rgn1->h), NULL, NULL); CU_ASSERT(gdi_EqualRgn(rgn1, rgn2) == 1); /* top = clip, bottom outside, left = clip, right = clip */ gdi_SetClipRgn(hdc, 300, 300, 100, 100); gdi_SetRgn(rgn1, 300, 300, 100, 200); gdi_SetRgn(rgn2, 300, 300, 100, 100); gdi_ClipCoords(hdc, &(rgn1->x), &(rgn1->y), &(rgn1->w), &(rgn1->h), NULL, NULL); CU_ASSERT(gdi_EqualRgn(rgn1, rgn2) == 1); /* top = clip, bottom = clip, top = clip, bottom = clip */ gdi_SetClipRgn(hdc, 300, 300, 100, 100); gdi_SetRgn(rgn1, 300, 300, 100, 100); gdi_SetRgn(rgn2, 300, 300, 100, 100); gdi_ClipCoords(hdc, &(rgn1->x), &(rgn1->y), &(rgn1->w), &(rgn1->h), NULL, NULL); CU_ASSERT(gdi_EqualRgn(rgn1, rgn2) == 1); } void test_gdi_InvalidateRegion(void) { HGDI_DC hdc; HGDI_RGN rgn1; HGDI_RGN rgn2; HGDI_RGN invalid; HGDI_BITMAP bmp; hdc = gdi_GetDC(); hdc->bytesPerPixel = 4; hdc->bitsPerPixel = 32; bmp = gdi_CreateBitmap(1024, 768, 4, NULL); gdi_SelectObject(hdc, (HGDIOBJECT) bmp); gdi_SetNullClipRgn(hdc); hdc->hwnd = (HGDI_WND) malloc(sizeof(GDI_WND)); hdc->hwnd->invalid = gdi_CreateRectRgn(0, 0, 0, 0); hdc->hwnd->invalid->null = 1; invalid = hdc->hwnd->invalid; hdc->hwnd->count = 16; hdc->hwnd->cinvalid = (HGDI_RGN) malloc(sizeof(GDI_RGN) * hdc->hwnd->count); rgn1 = gdi_CreateRectRgn(0, 0, 0, 0); rgn2 = gdi_CreateRectRgn(0, 0, 0, 0); rgn1->null = 1; rgn2->null = 1; /* no previous invalid region */ invalid->null = 1; gdi_SetRgn(rgn1, 300, 300, 100, 100); gdi_SetRgn(rgn2, 300, 300, 100, 100); gdi_InvalidateRegion(hdc, rgn1->x, rgn1->y, rgn1->w, rgn1->h); CU_ASSERT(gdi_EqualRgn(invalid, rgn2) == 1); /* region same as invalid region */ gdi_SetRgn(invalid, 300, 300, 100, 100); gdi_SetRgn(rgn1, 300, 300, 100, 100); gdi_SetRgn(rgn2, 300, 300, 100, 100); gdi_InvalidateRegion(hdc, rgn1->x, rgn1->y, rgn1->w, rgn1->h); CU_ASSERT(gdi_EqualRgn(invalid, rgn2) == 1); /* left outside */ gdi_SetRgn(invalid, 300, 300, 100, 100); gdi_SetRgn(rgn1, 100, 300, 300, 100); gdi_SetRgn(rgn2, 100, 300, 300, 100); gdi_InvalidateRegion(hdc, rgn1->x, rgn1->y, rgn1->w, rgn1->h); CU_ASSERT(gdi_EqualRgn(invalid, rgn2) == 1); /* right outside */ gdi_SetRgn(invalid, 300, 300, 100, 100); gdi_SetRgn(rgn1, 300, 300, 300, 100); gdi_SetRgn(rgn2, 300, 300, 300, 100); gdi_InvalidateRegion(hdc, rgn1->x, rgn1->y, rgn1->w, rgn1->h); CU_ASSERT(gdi_EqualRgn(invalid, rgn2) == 1); /* top outside */ gdi_SetRgn(invalid, 300, 300, 100, 100); gdi_SetRgn(rgn1, 300, 100, 100, 300); gdi_SetRgn(rgn2, 300, 100, 100, 300); gdi_InvalidateRegion(hdc, rgn1->x, rgn1->y, rgn1->w, rgn1->h); CU_ASSERT(gdi_EqualRgn(invalid, rgn2) == 1); /* bottom outside */ gdi_SetRgn(invalid, 300, 300, 100, 100); gdi_SetRgn(rgn1, 300, 300, 100, 300); gdi_SetRgn(rgn2, 300, 300, 100, 300); gdi_InvalidateRegion(hdc, rgn1->x, rgn1->y, rgn1->w, rgn1->h); CU_ASSERT(gdi_EqualRgn(invalid, rgn2) == 1); /* left outside, right outside */ gdi_SetRgn(invalid, 300, 300, 100, 100); gdi_SetRgn(rgn1, 100, 300, 600, 300); gdi_SetRgn(rgn2, 100, 300, 600, 300); gdi_InvalidateRegion(hdc, rgn1->x, rgn1->y, rgn1->w, rgn1->h); CU_ASSERT(gdi_EqualRgn(invalid, rgn2) == 1); /* top outside, bottom outside */ gdi_SetRgn(invalid, 300, 300, 100, 100); gdi_SetRgn(rgn1, 300, 100, 100, 500); gdi_SetRgn(rgn2, 300, 100, 100, 500); gdi_InvalidateRegion(hdc, rgn1->x, rgn1->y, rgn1->w, rgn1->h); CU_ASSERT(gdi_EqualRgn(invalid, rgn2) == 1); /* all outside, left */ gdi_SetRgn(invalid, 300, 300, 100, 100); gdi_SetRgn(rgn1, 100, 300, 100, 100); gdi_SetRgn(rgn2, 100, 300, 300, 100); gdi_InvalidateRegion(hdc, rgn1->x, rgn1->y, rgn1->w, rgn1->h); CU_ASSERT(gdi_EqualRgn(invalid, rgn2) == 1); /* all outside, right */ gdi_SetRgn(invalid, 300, 300, 100, 100); gdi_SetRgn(rgn1, 700, 300, 100, 100); gdi_SetRgn(rgn2, 300, 300, 500, 100); gdi_InvalidateRegion(hdc, rgn1->x, rgn1->y, rgn1->w, rgn1->h); CU_ASSERT(gdi_EqualRgn(invalid, rgn2) == 1); /* all outside, top */ gdi_SetRgn(invalid, 300, 300, 100, 100); gdi_SetRgn(rgn1, 300, 100, 100, 100); gdi_SetRgn(rgn2, 300, 100, 100, 300); gdi_InvalidateRegion(hdc, rgn1->x, rgn1->y, rgn1->w, rgn1->h); CU_ASSERT(gdi_EqualRgn(invalid, rgn2) == 1); /* all outside, bottom */ gdi_SetRgn(invalid, 300, 300, 100, 100); gdi_SetRgn(rgn1, 300, 500, 100, 100); gdi_SetRgn(rgn2, 300, 300, 100, 300); gdi_InvalidateRegion(hdc, rgn1->x, rgn1->y, rgn1->w, rgn1->h); CU_ASSERT(gdi_EqualRgn(invalid, rgn2) == 1); /* all outside */ gdi_SetRgn(invalid, 300, 300, 100, 100); gdi_SetRgn(rgn1, 100, 100, 600, 600); gdi_SetRgn(rgn2, 100, 100, 600, 600); gdi_InvalidateRegion(hdc, rgn1->x, rgn1->y, rgn1->w, rgn1->h); CU_ASSERT(gdi_EqualRgn(invalid, rgn2) == 1); /* everything */ gdi_SetRgn(invalid, 300, 300, 100, 100); gdi_SetRgn(rgn1, 0, 0, 1024, 768); gdi_SetRgn(rgn2, 0, 0, 1024, 768); gdi_InvalidateRegion(hdc, rgn1->x, rgn1->y, rgn1->w, rgn1->h); CU_ASSERT(gdi_EqualRgn(invalid, rgn2) == 1); } FreeRDP-1.0.2/cunit/test_libgdi.h000066400000000000000000000030051207112532300165170ustar00rootroot00000000000000/** * FreeRDP: A Remote Desktop Protocol Client * GDI Unit Tests * * Copyright 2010 Marc-Andre Moreau * * 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. */ #include "test_freerdp.h" int init_libgdi_suite(void); int clean_libgdi_suite(void); int add_libgdi_suite(void); void test_gdi_GetDC(void); void test_gdi_CreateCompatibleDC(void); void test_gdi_CreateBitmap(void); void test_gdi_CreateCompatibleBitmap(void); void test_gdi_CreatePen(void); void test_gdi_CreateSolidBrush(void); void test_gdi_CreatePatternBrush(void); void test_gdi_CreateRectRgn(void); void test_gdi_CreateRect(void); void test_gdi_GetPixel(void); void test_gdi_SetPixel(void); void test_gdi_SetROP2(void); void test_gdi_MoveToEx(void); void test_gdi_LineTo(void); void test_gdi_Ellipse(void); void test_gdi_PtInRect(void); void test_gdi_FillRect(void); void test_gdi_BitBlt_32bpp(void); void test_gdi_BitBlt_16bpp(void); void test_gdi_BitBlt_8bpp(void); void test_gdi_ClipCoords(void); void test_gdi_InvalidateRegion(void); FreeRDP-1.0.2/cunit/test_librfx.c000066400000000000000000000353571207112532300165650ustar00rootroot00000000000000/** * FreeRDP: A Remote Desktop Protocol Client * RemoteFX Codec Library Unit Tests * * Copyright 2011 Vic Lee * * 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. */ /** * The sample data comes from [MS-RDPRFX] 4.2.3, which is decoded into three * vertical bands in red (21x64), green (23x64) and blue(20x64) color. */ #include #include #include #include #include #include #include #include #include "rfx_types.h" #include "rfx_bitstream.h" #include "rfx_rlgr.h" #include "rfx_differential.h" #include "rfx_quantization.h" #include "rfx_dwt.h" #include "rfx_decode.h" #include "rfx_encode.h" #include "test_librfx.h" static const uint8 y_data[] = { 0x19, 0x82, 0x1d, 0x10, 0x62, 0x9d, 0x28, 0x85, 0x2c, 0xa2, 0x14, 0xb2, 0x88, 0x52, 0xca, 0x21, 0x4b, 0x28, 0x85, 0x2c, 0xa2, 0x14, 0xb2, 0x88, 0x52, 0xca, 0x21, 0x4b, 0x28, 0x85, 0x2c, 0xa2, 0x14, 0xb2, 0x88, 0x52, 0xca, 0x21, 0x4b, 0x28, 0x85, 0x2c, 0xa2, 0x14, 0xb2, 0x88, 0x52, 0xca, 0x21, 0x4b, 0x28, 0x85, 0x2c, 0xa2, 0x14, 0xb2, 0x88, 0x52, 0xca, 0x21, 0x4b, 0x28, 0x85, 0x2c, 0xa2, 0x14, 0xb2, 0x88, 0x52, 0xca, 0x21, 0x4b, 0x28, 0x85, 0x2c, 0xa2, 0x14, 0xb2, 0x88, 0x52, 0xca, 0x21, 0x4b, 0x28, 0x85, 0x2c, 0xa2, 0x14, 0xb0, 0x00, 0x20, 0xf4, 0x40, 0x0c, 0xc1, 0x1e, 0x20, 0x26, 0x22, 0x20, 0x33, 0x23, 0xc4, 0x23, 0x88, 0x86, 0x50, 0xf1, 0x22, 0x68, 0x4c, 0x91, 0x85, 0x10, 0x34, 0x4c, 0x84, 0x78, 0xa2, 0x0d, 0x13, 0x21, 0x1e, 0x29, 0x06, 0x89, 0x90, 0x8f, 0x14, 0x83, 0x44, 0xf4, 0x23, 0xc5, 0x20, 0xd1, 0x3d, 0x08, 0xf1, 0x48, 0x34, 0x4f, 0x42, 0x3c, 0x52, 0x0d, 0x13, 0xd0, 0x8f, 0x14, 0x83, 0x44, 0xf4, 0x23, 0xc5, 0x20, 0xd1, 0x3d, 0x08, 0xf1, 0x48, 0x34, 0x4f, 0x42, 0x3c, 0x52, 0x0d, 0x13, 0xd0, 0x8f, 0x14, 0x83, 0x44, 0xf4, 0x23, 0xc5, 0x20, 0x00, 0x08, 0x47, 0x70, 0x15, 0x02, 0xe0, 0x7f, 0xe4, 0x9d, 0xc2, 0x51, 0x71, 0xf4, 0x99, 0xc9, 0x57, 0xff, 0x32, 0x87, 0x9d, 0x17, 0xd6, 0x50, 0x6e, 0x06, 0x2f, 0xac, 0xa0, 0x9c, 0x0c, 0x5f, 0x59, 0x41, 0x38, 0x18, 0xbe, 0xb2, 0x82, 0x70, 0x31, 0x7d, 0x65, 0x00, 0x00, 0x10, 0xff, 0x9c, 0x33, 0x41, 0xf1, 0xc4, 0xb0, 0x3c, 0xff, 0xa2, 0x15, 0xbd, 0x7b, 0xea, 0x86, 0x9b, 0x5f, 0xfc, 0x78, 0x8c, 0xf5, 0xed, 0xa8, 0x68, 0xda, 0xfd, 0x3c, 0x45, 0x7a, 0xf4, 0xd4, 0x34, 0x6d, 0x7e, 0x9e, 0x22, 0xbd, 0x7a, 0x6a, 0x1a, 0x36, 0xbf, 0x4f, 0x11, 0x5e, 0xbd, 0x35, 0x0d, 0x1b, 0x5f, 0xa7, 0x88, 0xaf, 0x5e, 0x9a, 0x86, 0x8d, 0xaf, 0xd3, 0xc4, 0x57, 0xaf, 0x4d, 0x43, 0x46, 0xd7, 0xe9, 0xe2, 0x20, 0x30, 0x00 }; static const uint8 cb_data[] = { 0x1b, 0x04, 0x7f, 0x04, 0x31, 0x5f, 0xc2, 0x94, 0xaf, 0x05, 0x29, 0x5e, 0x0a, 0x52, 0xbc, 0x14, 0xa5, 0x78, 0x29, 0x25, 0x78, 0x29, 0x25, 0x78, 0x29, 0x25, 0x68, 0x52, 0x4a, 0xf0, 0x52, 0x4a, 0xf0, 0x52, 0x4a, 0xd0, 0xa4, 0x95, 0xe0, 0xa4, 0x95, 0xe0, 0xa4, 0x95, 0xa1, 0x49, 0x2b, 0xc1, 0x49, 0x2b, 0xc1, 0x49, 0x2b, 0x42, 0x92, 0x57, 0x82, 0x92, 0x57, 0x82, 0x92, 0x56, 0x85, 0x24, 0xaf, 0x05, 0x24, 0xaf, 0x05, 0x24, 0xad, 0x0a, 0x49, 0x5e, 0x0a, 0x49, 0x5e, 0x0a, 0x49, 0x5a, 0x14, 0x92, 0xbc, 0x14, 0x92, 0xbc, 0x14, 0x92, 0xb4, 0x29, 0x25, 0x78, 0x29, 0x25, 0x78, 0x00, 0x02, 0x0f, 0x02, 0x00, 0xac, 0x13, 0xfc, 0xc0, 0x0a, 0x20, 0x10, 0x2b, 0x27, 0xf9, 0x80, 0xb0, 0x08, 0xaa, 0x3d, 0x60, 0x8c, 0x0b, 0x24, 0xff, 0x30, 0x80, 0xc0, 0xaa, 0x13, 0xfc, 0xc2, 0x03, 0x05, 0x90, 0x9f, 0xe6, 0x10, 0x18, 0x2c, 0x84, 0xff, 0x30, 0x81, 0x82, 0xc8, 0x4f, 0xf3, 0x08, 0x18, 0x2c, 0x84, 0xff, 0x31, 0x03, 0x05, 0x90, 0x9f, 0xff, 0xd8, 0x40, 0x60, 0x59, 0x09, 0xfe, 0x61, 0x01, 0x81, 0x64, 0x27, 0xf9, 0x84, 0x06, 0x0b, 0x21, 0x3f, 0xcc, 0x20, 0x30, 0x59, 0x09, 0xfe, 0x61, 0x03, 0x05, 0x90, 0x9f, 0xe6, 0x10, 0x30, 0x59, 0x09, 0xfe, 0x62, 0x00, 0x00, 0x42, 0x15, 0x00, 0x10, 0x15, 0x01, 0xfe, 0x20, 0x84, 0xd5, 0x01, 0x0a, 0x8f, 0xf1, 0x40, 0x33, 0x78, 0x17, 0xf9, 0xc2, 0x03, 0x83, 0x01, 0x78, 0xe1, 0x01, 0xc1, 0x00, 0xbc, 0x70, 0x80, 0xe0, 0x80, 0x5e, 0x38, 0x40, 0x70, 0x40, 0x2f, 0x1c, 0x20, 0x38, 0x20, 0x17, 0x8e, 0x10, 0x00, 0x00, 0x87, 0xd5, 0x08, 0x70, 0xef, 0x81, 0xa2, 0xd8, 0xff, 0xff, 0xff, 0xfb, 0xd1, 0x2d, 0x4e, 0xa6, 0xce, 0x20, 0xa4, 0xef, 0x05, 0x78, 0x35, 0x3a, 0x9b, 0x38, 0x82, 0x93, 0xbc, 0x15, 0xe0, 0xd4, 0xea, 0x66, 0x71, 0x05, 0x27, 0x78, 0x2b, 0xc1, 0x29, 0xd4, 0xcc, 0xe2, 0x0a, 0x4e, 0xf0, 0x57, 0x82, 0x53, 0xa9, 0x99, 0xc4, 0x14, 0x9d, 0xe0, 0xaf, 0x04, 0xa7, 0x53, 0x33, 0x88, 0x29, 0x3b, 0xc1, 0x5e, 0x09, 0x4e, 0xa6, 0x67, 0x10, 0x52, 0x77, 0x82, 0xbc, 0x00, 0x18, 0x00 }; static const uint8 cr_data[] = { 0x1b, 0xfc, 0x11, 0xc1, 0x0f, 0x4a, 0xc1, 0x4f, 0x4a, 0xc1, 0x4f, 0x4a, 0xa1, 0x4d, 0x95, 0x42, 0x9e, 0x95, 0x42, 0x9e, 0x95, 0x42, 0x9b, 0x2a, 0x85, 0x3d, 0x2a, 0x85, 0x3d, 0x2a, 0x85, 0x36, 0x55, 0x0a, 0x7a, 0x55, 0x0a, 0x7a, 0x55, 0x0a, 0x6c, 0xaa, 0x14, 0xf4, 0xaa, 0x14, 0xf4, 0xaa, 0x14, 0xd9, 0x54, 0x29, 0xe9, 0x54, 0x29, 0xe9, 0x54, 0x29, 0xb2, 0xa8, 0x53, 0xd2, 0xa8, 0x53, 0xd2, 0xa8, 0x53, 0x65, 0x50, 0xa7, 0xa5, 0x50, 0xa7, 0xa5, 0x50, 0xa6, 0xca, 0xa1, 0x4f, 0x4a, 0xa1, 0x4f, 0x4a, 0xa1, 0x4d, 0x95, 0x42, 0x9e, 0x95, 0x42, 0x9e, 0x95, 0x42, 0x9b, 0x2a, 0x80, 0x00, 0x41, 0xe3, 0x80, 0x3f, 0xe2, 0x09, 0x9c, 0x00, 0x22, 0x07, 0x03, 0xe1, 0x26, 0x70, 0x06, 0x07, 0x1f, 0x04, 0x67, 0x00, 0x61, 0xdf, 0x02, 0x67, 0x00, 0x0c, 0x3b, 0xfe, 0x01, 0x33, 0x80, 0x06, 0x1d, 0xff, 0x00, 0x99, 0xc0, 0x03, 0x0e, 0xff, 0x80, 0x4c, 0xe0, 0x01, 0x87, 0x7f, 0xc0, 0x26, 0x70, 0x00, 0xc3, 0xbf, 0xe0, 0x13, 0x38, 0x00, 0x61, 0xdf, 0xf0, 0x09, 0x9c, 0x00, 0x30, 0xef, 0xf8, 0x04, 0xce, 0x00, 0x18, 0x77, 0xfc, 0x02, 0x67, 0x00, 0x0c, 0x3b, 0xfe, 0x01, 0x33, 0x80, 0x06, 0x1d, 0xff, 0x00, 0x99, 0xc0, 0x03, 0x0e, 0xff, 0x80, 0x4c, 0xe0, 0x01, 0x87, 0x7f, 0xc0, 0x26, 0x70, 0x00, 0x00, 0x08, 0x3c, 0x20, 0x1f, 0xf1, 0x00, 0xf0, 0x05, 0x02, 0x93, 0x84, 0x3d, 0x20, 0xf0, 0x52, 0x81, 0xc7, 0xff, 0xff, 0xea, 0x54, 0x01, 0x80, 0x05, 0xf5, 0x4a, 0x80, 0x30, 0x00, 0xb6, 0xa5, 0x40, 0x18, 0x00, 0x5f, 0x54, 0xa8, 0x03, 0x00, 0x0b, 0xea, 0x95, 0x00, 0x60, 0x01, 0x6d, 0x4a, 0x80, 0x30, 0x00, 0x00, 0x22, 0x3f, 0xba, 0x08, 0x10, 0x2b, 0x1f, 0xf2, 0x20, 0x3e, 0x49, 0x9c, 0x1f, 0x6e, 0x0f, 0x5a, 0x0f, 0xfb, 0x18, 0x46, 0xae, 0x27, 0x9b, 0x83, 0xcb, 0x41, 0xf3, 0x18, 0x46, 0xae, 0x27, 0x9b, 0x83, 0xc5, 0xa0, 0xf9, 0x8c, 0x22, 0xd7, 0x13, 0x8d, 0xc1, 0xe2, 0xd0, 0x7c, 0xc6, 0x11, 0x6b, 0x89, 0xc6, 0xe0, 0xf1, 0x68, 0x3e, 0x63, 0x08, 0xb5, 0xc4, 0xe3, 0x70, 0x78, 0xb4, 0x1f, 0x31, 0x84, 0x5a, 0xe2, 0x71, 0xb8, 0x3c, 0x5a, 0x0f, 0x98, 0xc2, 0x2d, 0x71, 0x30, 0x83, 0xc0, 0x00 }; /* HL1, LH1, HH1, HL2, LH2, HH2, HL3, LH3, HH3, LL3 */ static const unsigned int test_quantization_values[] = { 6, 6, 6, 6, 7, 7, 8, 8, 8, 9 }; static const uint8 rgb_scanline_data[] = { 0xFF, 0x00, 0x00, 0xFF, 0x00, 0x00, 0xFF, 0x00, 0x00, 0xFF, 0x00, 0x00, 0xFF, 0x00, 0x00, 0xFF, 0x00, 0x00, 0xFF, 0x00, 0x00, 0xFF, 0x00, 0x00, 0xFF, 0x00, 0x00, 0xFF, 0x00, 0x00, 0xFF, 0x00, 0x00, 0xFF, 0x00, 0x00, 0xFF, 0x00, 0x00, 0xFF, 0x00, 0x00, 0xFF, 0x00, 0x00, 0xFF, 0x00, 0x00, 0xFF, 0x00, 0x00, 0xFF, 0x00, 0x00, 0xFF, 0x00, 0x00, 0xFF, 0x00, 0x00, 0xFF, 0x00, 0x00, 0x00, 0xFF, 0x00, 0x00, 0xFF, 0x00, 0x00, 0xFF, 0x00, 0x00, 0xFF, 0x00, 0x00, 0xFF, 0x00, 0x00, 0xFF, 0x00, 0x00, 0xFF, 0x00, 0x00, 0xFF, 0x00, 0x00, 0xFF, 0x00, 0x00, 0xFF, 0x00, 0x00, 0xFF, 0x00, 0x00, 0xFF, 0x00, 0x00, 0xFF, 0x00, 0x00, 0xFF, 0x00, 0x00, 0xFF, 0x00, 0x00, 0xFF, 0x00, 0x00, 0xFF, 0x00, 0x00, 0xFF, 0x00, 0x00, 0xFF, 0x00, 0x00, 0xFF, 0x00, 0x00, 0xFF, 0x00, 0x00, 0xFF, 0x00, 0x00, 0xFF, 0x00, 0x00, 0x00, 0xFF, 0x00, 0x00, 0xFF, 0x00, 0x00, 0xFF, 0x00, 0x00, 0xFF, 0x00, 0x00, 0xFF, 0x00, 0x00, 0xFF, 0x00, 0x00, 0xFF, 0x00, 0x00, 0xFF, 0x00, 0x00, 0xFF, 0x00, 0x00, 0xFF, 0x00, 0x00, 0xFF, 0x00, 0x00, 0xFF, 0x00, 0x00, 0xFF, 0x00, 0x00, 0xFF, 0x00, 0x00, 0xFF, 0x00, 0x00, 0xFF, 0x00, 0x00, 0xFF, 0x00, 0x00, 0xFF, 0x00, 0x00, 0xFF, 0x00, 0x00, 0xFF, 0xFF, 0x00, 0x00, 0xFF, 0x00, 0x00, 0xFF, 0x00, 0x00, 0xFF, 0x00, 0x00, 0xFF, 0x00, 0x00, 0xFF, 0x00, 0x00, 0xFF, 0x00, 0x00, 0xFF, 0x00, 0x00, 0xFF, 0x00, 0x00, 0xFF, 0x00, 0x00, 0xFF, 0x00, 0x00, 0xFF, 0x00, 0x00, 0xFF, 0x00, 0x00, 0xFF, 0x00, 0x00, 0xFF, 0x00, 0x00, 0xFF, 0x00, 0x00, 0xFF, 0x00, 0x00, 0xFF, 0x00, 0x00, 0xFF, 0x00, 0x00, 0xFF, 0x00, 0x00, 0xFF, 0x00, 0x00, 0x00, 0xFF, 0x00, 0x00, 0xFF, 0x00, 0x00, 0xFF, 0x00, 0x00, 0xFF, 0x00, 0x00, 0xFF, 0x00, 0x00, 0xFF, 0x00, 0x00, 0xFF, 0x00, 0x00, 0xFF, 0x00, 0x00, 0xFF, 0x00, 0x00, 0xFF, 0x00, 0x00, 0xFF, 0x00, 0x00, 0xFF, 0x00, 0x00, 0xFF, 0x00, 0x00, 0xFF, 0x00, 0x00, 0xFF, 0x00, 0x00, 0xFF, 0x00, 0x00, 0xFF, 0x00, 0x00, 0xFF, 0x00, 0x00, 0xFF, 0x00, 0x00, 0xFF, 0x00, 0x00, 0xFF, 0x00, 0x00, 0xFF, 0x00, 0x00, 0xFF, 0x00, 0x00, 0x00, 0xFF, 0x00, 0x00, 0xFF, 0x00, 0x00, 0xFF, 0x00, 0x00, 0xFF, 0x00, 0x00, 0xFF, 0x00, 0x00, 0xFF, 0x00, 0x00, 0xFF, 0x00, 0x00, 0xFF, 0x00, 0x00, 0xFF, 0x00, 0x00, 0xFF, 0x00, 0x00, 0xFF, 0x00, 0x00, 0xFF, 0x00, 0x00, 0xFF, 0x00, 0x00, 0xFF, 0x00, 0x00, 0xFF, 0x00, 0x00, 0xFF, 0x00, 0x00, 0xFF, 0x00, 0x00, 0xFF, 0x00, 0x00, 0xFF, 0x00, 0x00, 0xFF }; static uint8* rgb_data; int init_librfx_suite(void) { return 0; } int clean_librfx_suite(void) { return 0; } int add_librfx_suite(void) { add_test_suite(librfx); add_test_function(bitstream); add_test_function(bitstream_enc); add_test_function(rlgr); add_test_function(differential); add_test_function(quantization); add_test_function(dwt); add_test_function(decode); add_test_function(encode); add_test_function(message); return 0; } void test_bitstream(void) { uint16 b; RFX_BITSTREAM* bs; bs = xnew(RFX_BITSTREAM); rfx_bitstream_attach(bs, (uint8*) y_data, sizeof(y_data)); while (!rfx_bitstream_eos(bs)) { rfx_bitstream_get_bits(bs, 3, b); (void) b; //printf("%u ", b); } xfree(bs); //printf("\n"); } void test_bitstream_enc(void) { uint8 buffer[10]; RFX_BITSTREAM* bs; int i; bs = xnew(RFX_BITSTREAM); memset(buffer, 0, sizeof(buffer)); rfx_bitstream_attach(bs, buffer, sizeof(buffer)); for (i = 0; i < 16; i++) { rfx_bitstream_put_bits(bs, i, 5); } /*for (i = 0; i < sizeof(buffer); i++) { printf("%X ", buffer[i]); }*/ xfree(bs); //printf("\n"); } static sint16 buffer[4096]; void dump_buffer(sint16* buf, int n) { int i; for (i = 0; i < n; i++) { if (i % 16 == 0) printf("\n%04d ", i); printf("% 4d ", buf[i]); } printf("\n"); } void test_rlgr(void) { int n; n = rfx_rlgr_decode(RLGR3, y_data, sizeof(y_data), buffer, sizeof(buffer) / sizeof(unsigned int)); //printf("RLGR decode %d bytes to %d values.", sizeof(y_data), n); //dump_buffer(buffer, n); } void test_differential(void) { rfx_differential_decode(buffer + 4032, 64); //dump_buffer(buffer + 4032, 64); } void test_quantization(void) { rfx_quantization_decode(buffer, test_quantization_values); //dump_buffer(buffer, 4096); } void test_dwt(void) { RFX_CONTEXT* context; context = rfx_context_new(); rfx_dwt_2d_decode(buffer, context->priv->dwt_buffer); //dump_buffer(buffer, 4096); rfx_context_free(context); } /* Dump a .ppm image. */ static void dump_ppm_image(uint8* image_buf) { static int frame_id = 0; char buf[100]; FILE* fp; snprintf(buf, sizeof(buf), "/tmp/FreeRDP_Frame_%d.ppm", frame_id); fp = fopen(buf, "wb"); fwrite("P6\n", 1, 3, fp); fwrite("# Created by FreeRDP\n", 1, 21, fp); fwrite("64 64\n", 1, 6, fp); fwrite("255\n", 1, 4, fp); fwrite(image_buf, 1, 4096 * 3, fp); fflush(fp); fclose(fp); frame_id++; } void test_decode(void) { RFX_CONTEXT* context; uint8 decode_buffer[4096 * 3]; STREAM* s; s = stream_new(sizeof(y_data) + sizeof(cb_data) + sizeof(cr_data)); stream_write(s, y_data, sizeof(y_data)); stream_write(s, cb_data, sizeof(cb_data)); stream_write(s, cr_data, sizeof(cr_data)); stream_set_pos(s, 0); context = rfx_context_new(); context->mode = RLGR3; rfx_context_set_pixel_format(context, RFX_PIXEL_FORMAT_RGB); rfx_decode_rgb(context, s, sizeof(y_data), test_quantization_values, sizeof(cb_data), test_quantization_values, sizeof(cr_data), test_quantization_values, decode_buffer); rfx_context_free(context); stream_free(s); dump_ppm_image(decode_buffer); } void test_encode(void) { RFX_CONTEXT* context; STREAM* enc_stream; int y_size, cb_size, cr_size; int i; uint8 decode_buffer[4096 * 3]; rgb_data = (uint8 *) malloc(64 * 64 * 3); for (i = 0; i < 64; i++) memcpy(rgb_data + i * 64 * 3, rgb_scanline_data, 64 * 3); //freerdp_hexdump(rgb_data, 64 * 64 * 3); enc_stream = stream_new(65536); stream_clear(enc_stream); context = rfx_context_new(); context->mode = RLGR3; rfx_context_set_pixel_format(context, RFX_PIXEL_FORMAT_RGB); rfx_encode_rgb(context, rgb_data, 64, 64, 64 * 3, test_quantization_values, test_quantization_values, test_quantization_values, enc_stream, &y_size, &cb_size, &cr_size); //dump_buffer(context->priv->cb_g_buffer, 4096); /*printf("*** Y ***\n"); freerdp_hexdump(stream_get_head(enc_stream), y_size); printf("*** Cb ***\n"); freerdp_hexdump(stream_get_head(enc_stream) + y_size, cb_size); printf("*** Cr ***\n"); freerdp_hexdump(stream_get_head(enc_stream) + y_size + cb_size, cr_size);*/ stream_set_pos(enc_stream, 0); rfx_decode_rgb(context, enc_stream, y_size, test_quantization_values, cb_size, test_quantization_values, cr_size, test_quantization_values, decode_buffer); dump_ppm_image(decode_buffer); rfx_context_free(context); stream_free(enc_stream); free(rgb_data); } void test_message(void) { RFX_CONTEXT* context; STREAM* s; int i, j; RFX_RECT rect = {0, 0, 100, 80}; RFX_MESSAGE * message; rgb_data = (uint8 *) malloc(100 * 80 * 3); for (i = 0; i < 80; i++) memcpy(rgb_data + i * 100 * 3, rgb_scanline_data, 100 * 3); s = stream_new(65536); stream_clear(s); context = rfx_context_new(); context->mode = RLGR3; context->width = 800; context->height = 600; rfx_context_set_pixel_format(context, RFX_PIXEL_FORMAT_RGB); for (i = 0; i < 1000; i++) { s = stream_new(65536); stream_clear(s); rfx_compose_message(context, s, &rect, 1, rgb_data, 100, 80, 100 * 3); stream_seal(s); /*hexdump(buffer, size);*/ stream_set_pos(s, 0); message = rfx_process_message(context, s->p, s->size); if (i == 0) { for (j = 0; j < message->num_tiles; j++) { dump_ppm_image(message->tiles[j]->data); } } rfx_message_free(context, message); stream_free(s); } rfx_context_free(context); free(rgb_data); } FreeRDP-1.0.2/cunit/test_librfx.h000066400000000000000000000020031207112532300165500ustar00rootroot00000000000000/** * FreeRDP: A Remote Desktop Protocol Client * RemoteFX Codec Library Unit Tests * * Copyright 2011 Vic Lee * * 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. */ #include "test_freerdp.h" int init_librfx_suite(void); int clean_librfx_suite(void); int add_librfx_suite(void); void test_bitstream(void); void test_bitstream_enc(void); void test_rlgr(void); void test_differential(void); void test_quantization(void); void test_dwt(void); void test_decode(void); void test_encode(void); void test_message(void); FreeRDP-1.0.2/cunit/test_license.c000066400000000000000000000561371207112532300167200ustar00rootroot00000000000000/** * FreeRDP: A Remote Desktop Protocol Client * Licensing Unit Tests * * Copyright 2011 Marc-Andre Moreau * * 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. */ #include "license.h" #include #include #include #include "test_license.h" rdpRdp* rdp; rdpLicense* license; int init_license_suite(void) { rdp = rdp_new(NULL); license = rdp->license; return 0; } int clean_license_suite(void) { rdp_free(rdp); return 0; } int add_license_suite(void) { add_test_suite(license); add_test_function(license); //add_test_function(license_generate_keys); //add_test_function(license_encrypt_premaster_secret); add_test_function(license_decrypt_platform_challenge); return 0; } /* Server License Request (2200 bytes) */ uint8 server_license_request[2200] = "\x01\x03\x98\x08\x84\xef\xae\x20\xb1\xd5\x9e\x36\x49\x1a\xe8\x2e" "\x0a\x99\x89\xac\x49\xa6\x47\x4f\x33\x9b\x5a\xb9\x95\x03\xa6\xc6" "\xc2\x3c\x3f\x61\x00\x00\x06\x00\x2c\x00\x00\x00\x4d\x00\x69\x00" "\x63\x00\x72\x00\x6f\x00\x73\x00\x6f\x00\x66\x00\x74\x00\x20\x00" "\x43\x00\x6f\x00\x72\x00\x70\x00\x6f\x00\x72\x00\x61\x00\x74\x00" "\x69\x00\x6f\x00\x6e\x00\x00\x00\x08\x00\x00\x00\x41\x00\x30\x00" "\x32\x00\x00\x00\x0d\x00\x04\x00\x01\x00\x00\x00\x03\x00\x12\x08" "\x02\x00\x00\x80\x02\x00\x00\x00\xf5\x02\x00\x00\x30\x82\x02\xf1" "\x30\x82\x01\xdd\xa0\x03\x02\x01\x02\x02\x08\x01\x9e\x24\xa2\xf2" "\xae\x90\x80\x30\x09\x06\x05\x2b\x0e\x03\x02\x1d\x05\x00\x30\x32" "\x31\x30\x30\x13\x06\x03\x55\x04\x03\x1e\x0c\x00\x52\x00\x4f\x00" "\x44\x00\x45\x00\x4e\x00\x54\x30\x19\x06\x03\x55\x04\x07\x1e\x12" "\x00\x57\x00\x4f\x00\x52\x00\x4b\x00\x47\x00\x52\x00\x4f\x00\x55" "\x00\x50\x30\x1e\x17\x0d\x37\x30\x30\x35\x32\x37\x30\x31\x31\x31" "\x30\x33\x5a\x17\x0d\x34\x39\x30\x35\x32\x37\x30\x31\x31\x31\x30" "\x33\x5a\x30\x32\x31\x30\x30\x13\x06\x03\x55\x04\x03\x1e\x0c\x00" "\x52\x00\x4f\x00\x44\x00\x45\x00\x4e\x00\x54\x30\x19\x06\x03\x55" "\x04\x07\x1e\x12\x00\x57\x00\x4f\x00\x52\x00\x4b\x00\x47\x00\x52" "\x00\x4f\x00\x55\x00\x50\x30\x82\x01\x22\x30\x0d\x06\x09\x2a\x86" "\x48\x86\xf7\x0d\x01\x01\x01\x05\x00\x03\x82\x01\x0f\x00\x30\x82" "\x01\x0a\x02\x82\x01\x01\x00\x88\xad\x7c\x8f\x8b\x82\x76\x5a\xbd" "\x8f\x6f\x62\x18\xe1\xd9\xaa\x41\xfd\xed\x68\x01\xc6\x34\x35\xb0" "\x29\x04\xca\x4a\x4a\x1c\x7e\x80\x14\xf7\x8e\x77\xb8\x25\xff\x16" "\x47\x6f\xbd\xe2\x34\x3d\x2e\x02\xb9\x53\xe4\x33\x75\xad\x73\x28" "\x80\xa0\x4d\xfc\x6c\xc0\x22\x53\x1b\x2c\xf8\xf5\x01\x60\x19\x7e" "\x79\x19\x39\x8d\xb5\xce\x39\x58\xdd\x55\x24\x3b\x55\x7b\x43\xc1" "\x7f\x14\x2f\xb0\x64\x3a\x54\x95\x2b\x88\x49\x0c\x61\x2d\xac\xf8" "\x45\xf5\xda\x88\x18\x5f\xae\x42\xf8\x75\xc7\x26\x6d\xb5\xbb\x39" "\x6f\xcc\x55\x1b\x32\x11\x38\x8d\xe4\xe9\x44\x84\x11\x36\xa2\x61" "\x76\xaa\x4c\xb4\xe3\x55\x0f\xe4\x77\x8e\xde\xe3\xa9\xea\xb7\x41" "\x94\x00\x58\xaa\xc9\x34\xa2\x98\xc6\x01\x1a\x76\x14\x01\xa8\xdc" "\x30\x7c\x77\x5a\x20\x71\x5a\xa2\x3f\xaf\x13\x7e\xe8\xfd\x84\xa2" "\x5b\xcf\x25\xe9\xc7\x8f\xa8\xf2\x8b\x84\xc7\x04\x5e\x53\x73\x4e" "\x0e\x89\xa3\x3c\xe7\x68\x5c\x24\xb7\x80\x53\x3c\x54\xc8\xc1\x53" "\xaa\x71\x71\x3d\x36\x15\xd6\x6a\x9d\x7d\xde\xae\xf9\xe6\xaf\x57" "\xae\xb9\x01\x96\x5d\xe0\x4d\xcd\xed\xc8\xd7\xf3\x01\x03\x38\x10" "\xbe\x7c\x42\x67\x01\xa7\x23\x02\x03\x01\x00\x01\xa3\x13\x30\x11" "\x30\x0f\x06\x03\x55\x1d\x13\x04\x08\x30\x06\x01\x01\xff\x02\x01" "\x00\x30\x09\x06\x05\x2b\x0e\x03\x02\x1d\x05\x00\x03\x82\x01\x01" "\x00\x81\xdd\xd2\xd3\x33\xd4\xa3\xb6\x8e\x6e\x7d\x9f\xfd\x73\x9f" "\x31\x0b\xdd\x42\x82\x3f\x7e\x21\xdf\x28\xcc\x59\xca\x6a\xc0\xa9" "\x3d\x30\x7d\xe1\x91\xdb\x77\x6b\x8b\x10\xe6\xfd\xbc\x3c\xa3\x58" "\x48\xc2\x36\xdd\xa0\x0b\xf5\x8e\x13\xda\x7b\x04\x08\x44\xb4\xf2" "\xa8\x0d\x1e\x0b\x1d\x1a\x3f\xf9\x9b\x4b\x5a\x54\xc5\xb3\xb4\x03" "\x93\x75\xb3\x72\x5c\x3d\xcf\x63\x0f\x15\xe1\x64\x58\xde\x52\x8d" "\x97\x79\x0e\xa4\x34\xd5\x66\x05\x58\xb8\x6e\x79\xb2\x09\x86\xd5" "\xf0\xed\xc4\x6b\x4c\xab\x02\xb8\x16\x5f\x3b\xed\x88\x5f\xd1\xde" "\x44\xe3\x73\x47\x21\xf7\x03\xce\xe1\x6d\x10\x0f\x95\xcf\x7c\xa2" "\x7a\xa6\xbf\x20\xdb\xe1\x93\x04\xc8\x5e\x6a\xbe\xc8\x01\x5d\x27" "\xb2\x03\x0f\x66\x75\xe7\xcb\xea\x8d\x4e\x98\x9d\x22\xed\x28\x40" "\xd2\x7d\xa4\x4b\xef\xcc\xbf\x01\x2a\x6d\x3a\x3e\xbe\x47\x38\xf8" "\xea\xa4\xc6\x30\x1d\x5e\x25\xcf\xfb\xe8\x3d\x42\xdd\x29\xe8\x99" "\x89\x9e\xbf\x39\xee\x77\x09\xd9\x3e\x8b\x52\x36\xb6\xbb\x8b\xbd" "\x0d\xb2\x52\xaa\x2c\xcf\x38\x4e\x4d\xcf\x1d\x6d\x5d\x25\x17\xac" "\x2c\xf6\xf0\x65\x5a\xc9\xfe\x31\x53\xb4\xf0\x0c\x94\x4e\x0d\x54" "\x8e\xfd\x04\x00\x00\x30\x82\x04\xf9\x30\x82\x03\xe5\xa0\x03\x02" "\x01\x02\x02\x05\x01\x00\x00\x00\x02\x30\x09\x06\x05\x2b\x0e\x03" "\x02\x1d\x05\x00\x30\x32\x31\x30\x30\x13\x06\x03\x55\x04\x03\x1e" "\x0c\x00\x52\x00\x4f\x00\x44\x00\x45\x00\x4e\x00\x54\x30\x19\x06" "\x03\x55\x04\x07\x1e\x12\x00\x57\x00\x4f\x00\x52\x00\x4b\x00\x47" "\x00\x52\x00\x4f\x00\x55\x00\x50\x30\x1e\x17\x0d\x30\x37\x30\x35" "\x32\x36\x31\x32\x34\x35\x35\x33\x5a\x17\x0d\x33\x38\x30\x31\x31" "\x39\x30\x33\x31\x34\x30\x37\x5a\x30\x81\x92\x31\x81\x8f\x30\x23" "\x06\x03\x55\x04\x03\x1e\x1c\x00\x6e\x00\x63\x00\x61\x00\x6c\x00" "\x72\x00\x70\x00\x63\x00\x3a\x00\x52\x00\x4f\x00\x44\x00\x45\x00" "\x4e\x00\x54\x30\x23\x06\x03\x55\x04\x07\x1e\x1c\x00\x6e\x00\x63" "\x00\x61\x00\x6c\x00\x72\x00\x70\x00\x63\x00\x3a\x00\x52\x00\x4f" "\x00\x44\x00\x45\x00\x4e\x00\x54\x30\x43\x06\x03\x55\x04\x05\x1e" "\x3c\x00\x31\x00\x42\x00\x63\x00\x4b\x00\x65\x00\x62\x00\x68\x00" "\x70\x00\x58\x00\x5a\x00\x74\x00\x4c\x00\x71\x00\x4f\x00\x37\x00" "\x53\x00\x51\x00\x6e\x00\x42\x00\x70\x00\x52\x00\x66\x00\x75\x00" "\x64\x00\x64\x00\x64\x00\x59\x00\x3d\x00\x0d\x00\x0a\x30\x82\x01" "\x1e\x30\x09\x06\x05\x2b\x0e\x03\x02\x0f\x05\x00\x03\x82\x01\x0f" "\x00\x30\x82\x01\x0a\x02\x82\x01\x01\x00\xc8\x90\x6b\xf0\xc6\x58" "\x81\xa6\x89\x1c\x0e\xf2\xf6\xd9\x82\x12\x71\xa5\x6e\x51\xdb\xe0" "\x32\x66\xaa\x91\x77\x0e\x88\xab\x44\xb7\xd3\x97\xda\x78\x8f\x0e" "\x44\x26\x46\x7f\x16\xd4\xc6\x63\xeb\xca\x55\xe5\x4e\x8b\x2d\xa6" "\x6d\x83\x95\xa7\xa8\x6a\xfa\xd0\xbe\x26\x80\xae\xab\x0a\x64\x90" "\x32\x8c\xdf\x5c\xf8\xf9\xd0\x7e\xd1\x6b\x3a\x29\x7e\x7d\xbd\x02" "\xa3\x86\x6c\xfd\xa5\x35\x71\xda\x21\xb4\xee\xa4\x97\xf3\xa8\xb2" "\x12\xdb\xa4\x27\x57\x36\xc9\x08\x22\x5c\x54\xf7\x99\x7b\xa3\x2f" "\xb8\x5c\xd5\x16\xb8\x19\x27\x6b\x71\x97\x14\x5b\xe8\x1f\x23\xe8" "\x5c\xb8\x1b\x73\x4b\x6e\x7a\x03\x13\xff\x97\xe9\x62\xb9\x4a\xa0" "\x51\x23\xc3\x6c\x32\x3e\x02\xf2\x63\x97\x23\x1c\xc5\x78\xd8\xfc" "\xb7\x07\x4b\xb0\x56\x0f\x74\xdf\xc5\x56\x28\xe4\x96\xfd\x20\x8e" "\x65\x5a\xe6\x45\xed\xc1\x05\x3e\xab\x58\x55\x40\xaf\xe2\x47\xa0" "\x4c\x49\xa3\x8d\x39\xe3\x66\x5f\x93\x33\x6d\xf8\x5f\xc5\x54\xe5" "\xfb\x57\x3a\xde\x45\x12\xb5\xc7\x05\x4b\x88\x1f\xb4\x35\x0f\x7c" "\xc0\x75\x17\xc6\x67\xdd\x48\x80\xcb\x0a\xbe\x9d\xf6\x93\x60\x65" "\x34\xeb\x97\xaf\x65\x6d\xdf\xbf\x6f\x5b\x02\x03\x01\x00\x01\xa3" "\x82\x01\xbf\x30\x82\x01\xbb\x30\x14\x06\x09\x2b\x06\x01\x04\x01" "\x82\x37\x12\x04\x01\x01\xff\x04\x04\x01\x00\x05\x00\x30\x3c\x06" "\x09\x2b\x06\x01\x04\x01\x82\x37\x12\x02\x01\x01\xff\x04\x2c\x4d" "\x00\x69\x00\x63\x00\x72\x00\x6f\x00\x73\x00\x6f\x00\x66\x00\x74" "\x00\x20\x00\x43\x00\x6f\x00\x72\x00\x70\x00\x6f\x00\x72\x00\x61" "\x00\x74\x00\x69\x00\x6f\x00\x6e\x00\x00\x00\x30\x81\xcd\x06\x09" "\x2b\x06\x01\x04\x01\x82\x37\x12\x05\x01\x01\xff\x04\x81\xbc\x00" "\x30\x00\x00\x01\x00\x00\x00\x02\x00\x00\x00\x09\x04\x00\x00\x1c" "\x00\x4a\x00\x66\x00\x4a\x00\xb0\x00\x01\x00\x33\x00\x64\x00\x32" "\x00\x36\x00\x37\x00\x39\x00\x35\x00\x34\x00\x2d\x00\x65\x00\x65" "\x00\x62\x00\x37\x00\x2d\x00\x31\x00\x31\x00\x64\x00\x31\x00\x2d" "\x00\x62\x00\x39\x00\x34\x00\x65\x00\x2d\x00\x30\x00\x30\x00\x63" "\x00\x30\x00\x34\x00\x66\x00\x61\x00\x33\x00\x30\x00\x38\x00\x30" "\x00\x64\x00\x00\x00\x33\x00\x64\x00\x32\x00\x36\x00\x37\x00\x39" "\x00\x35\x00\x34\x00\x2d\x00\x65\x00\x65\x00\x62\x00\x37\x00\x2d" "\x00\x31\x00\x31\x00\x64\x00\x31\x00\x2d\x00\x62\x00\x39\x00\x34" "\x00\x65\x00\x2d\x00\x30\x00\x30\x00\x63\x00\x30\x00\x34\x00\x66" "\x00\x61\x00\x33\x00\x30\x00\x38\x00\x30\x00\x64\x00\x00\x00\x00" "\x00\x00\x10\x00\x80\x64\x00\x00\x00\x00\x00\x30\x6e\x06\x09\x2b" "\x06\x01\x04\x01\x82\x37\x12\x06\x01\x01\xff\x04\x5e\x00\x30\x00" "\x00\x00\x00\x0e\x00\x3e\x00\x52\x00\x4f\x00\x44\x00\x45\x00\x4e" "\x00\x54\x00\x00\x00\x37\x00\x38\x00\x34\x00\x34\x00\x30\x00\x2d" "\x00\x30\x00\x30\x00\x36\x00\x2d\x00\x35\x00\x38\x00\x36\x00\x37" "\x00\x30\x00\x34\x00\x35\x00\x2d\x00\x37\x00\x30\x00\x33\x00\x34" "\x00\x37\x00\x00\x00\x57\x00\x4f\x00\x52\x00\x4b\x00\x47\x00\x52" "\x00\x4f\x00\x55\x00\x50\x00\x00\x00\x00\x00\x30\x25\x06\x03\x55" "\x1d\x23\x01\x01\xff\x04\x1b\x30\x19\xa1\x10\xa4\x0e\x52\x00\x4f" "\x00\x44\x00\x45\x00\x4e\x00\x54\x00\x00\x00\x82\x05\x01\x00\x00" "\x00\x02\x30\x09\x06\x05\x2b\x0e\x03\x02\x1d\x05\x00\x03\x82\x01" "\x01\x00\x2e\xeb\xc7\x0d\xb8\x1d\x47\x11\x9d\x09\x88\x9b\x51\xdc" "\x45\xdd\x56\x51\xe2\xd1\x23\x11\x39\x9b\x2d\xda\xc7\xfe\x7a\xd7" "\x84\xe3\x3d\x54\x77\x97\x4d\x19\x92\x30\x64\xa0\x47\xc6\x2f\x6d" "\x93\xd2\x64\x7c\x76\xc8\x26\x45\xad\x5a\x44\x54\xea\xf6\x4b\x28" "\x77\x1f\x77\xea\xec\x74\x02\x38\x68\x9e\x79\x14\x72\x83\x34\x74" "\x62\xd2\xc1\x0c\xa4\x0b\xf2\xa9\xb0\x38\xbb\x7c\xd0\xae\xbe\xbf" "\x74\x47\x16\xa0\xa2\xd3\xfc\x1d\xb9\xba\x26\x10\x06\xef\xba\x1d" "\x43\x01\x4e\x4e\x6f\x56\xca\xe0\xee\xd0\xf9\x4e\xa6\x62\x63\xff" "\xda\x0b\xc9\x15\x61\x6c\xed\x6b\x0b\xc4\x58\x53\x86\x0f\x8c\x0c" "\x1a\x2e\xdf\xc1\xf2\x43\x48\xd4\xaf\x0a\x78\x36\xb2\x51\x32\x28" "\x6c\xc2\x75\x79\x3f\x6e\x99\x66\x88\x3e\x34\xd3\x7f\x6d\x9d\x07" "\xe4\x6b\xeb\x84\xe2\x0a\xbb\xca\x7d\x3a\x40\x71\xb0\xbe\x47\x9f" "\x12\x58\x31\x61\x2b\x9b\x4a\x9a\x49\x8f\xe5\xb4\x0c\xf5\x04\x4d" "\x3c\xce\xbc\xd2\x79\x15\xd9\x28\xf4\x23\x56\x77\x9f\x38\x64\x3e" "\x03\x88\x92\x04\x26\x76\xb9\xb5\xdf\x19\xd0\x78\x4b\x7a\x60\x40" "\x23\x91\xf1\x15\x22\x2b\xb4\xe7\x02\x54\xa9\x16\x21\x5b\x60\x96" "\xa9\x5c\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00" "\x00\x00\x01\x00\x00\x00\x0e\x00\x0e\x00\x6d\x69\x63\x72\x6f\x73" "\x6f\x66\x74\x2e\x63\x6f\x6d\x00"; /* Client New License Request (341 bytes) */ uint8 client_new_license_request[341] = "\x13\x83\x55\x01\x01\x00\x00\x00\x00\x00\x01\x04\xdc\x73\xa0\xc8" "\x69\x25\x6b\x18\xaf\x0b\x94\x7a\xa9\xa5\x20\xaf\x8b\xbc\x0d\xcc" "\xa3\x95\xb7\xb9\xeb\x81\x5d\xbe\x0a\x10\x9c\xd8\x02\x00\x08\x01" "\xda\x9c\x5d\xa6\x68\x9d\xa3\x90\x67\x24\xf3\x3a\xea\xa1\xe2\x68" "\xad\x12\xf5\xf6\x0b\x7a\xac\x92\xb1\x69\x6f\x42\x55\x8a\xa0\xe2" "\x9b\x2c\xd0\xc7\xee\x33\x6c\x47\x79\xc3\x1e\xbf\x03\x8b\x95\x70" "\x07\xa2\xbe\xee\x54\x02\x68\xf8\x90\xd7\xfe\x2c\x08\xe1\x6b\x2d" "\xff\x94\x76\x72\x5f\x7a\x76\x75\x32\x55\xcc\x58\x61\x63\xa5\x64" "\xf1\x6e\xc3\x07\x81\x82\x6f\x88\x73\x62\xfc\x28\x65\x91\xc2\xc8" "\x9f\x05\xb0\xd3\x93\x12\xbf\x6a\x50\x18\x99\x2d\x4d\xc4\x7f\x74" "\xd3\x30\x9f\x16\x78\xa5\xdf\xaa\x83\x65\x4f\x77\x30\x42\xe0\xd7" "\x69\xc8\x4d\xa5\x73\x11\x59\x35\xb9\xa7\xe2\xb0\xf6\xe3\xb9\x39" "\xc3\xd4\xe4\x6b\xca\x40\x9a\xac\x66\xe6\x1a\xa4\x1b\x39\x7e\x09" "\xe3\x72\x99\xdd\x90\x62\x55\x97\xa9\x04\xc7\x51\xaa\xa2\x01\xcb" "\x5a\x63\x4d\x1a\xe5\x99\xc3\xb1\x2a\x73\xe8\x9a\x00\x46\x92\x59" "\x39\xa3\x80\xa1\xac\x90\x52\xea\x63\x81\x49\x7d\xf3\x2d\x5c\xc3" "\x19\x9f\xed\xfe\x81\x1d\x8c\x04\x1c\xd9\x23\xd2\x6d\x80\x84\xf3" "\x00\xf2\xb1\x69\x2f\xcd\xb3\x9f\x69\xee\x60\x3e\x4b\xb5\xbe\x5a" "\x09\x83\x0b\xbc\x3d\x3e\x05\x47\x65\x96\x31\x8c\x6b\xc5\xe6\xa0" "\x00\x00\x00\x00\x00\x00\x00\x00\x0f\x00\x0e\x00\x41\x64\x6d\x69" "\x6e\x69\x73\x74\x72\x61\x74\x6f\x72\x00\x10\x00\x07\x00\x52\x4f" "\x44\x45\x4e\x54\x00"; /* Server Platform Challenge (38 bytes) */ uint8 server_platform_challenge[38] = "\x02\x03\x26\x00\xff\xff\xff\xff\x50\xf7\x0a\x00\x46\x37\x85\x54" "\x8e\xc5\x91\x34\x97\x5d\x78\x94\xad\x3b\x81\xda\x88\x18\x56\x0f" "\x3a\xd1\xf1\x03\xef\x35"; /* Client Platform Challenge Response (66 bytes) */ uint8 client_platform_challenge_response[66] = "\x15\x83\x42\x00\x01\x00\x12\x00\xfa\xb4\xe8\x24\xcf\x56\xb2\x4e" "\x80\x02\xbd\xb6\x61\xfc\xdf\xe9\x6c\x44\x01\x00\x14\x00\xf8\xb5" "\xe8\x25\x3d\x0f\x3f\x70\x1d\xda\x60\x19\x16\xfe\x73\x1a\x45\x7e" "\x02\x71\x38\x23\x62\x5d\x10\x8b\x93\xc3\xf1\xe4\x67\x1f\x4a\xb6" "\x00\x0a"; uint8 license_server_modulus[256] = "\x88\xad\x7c\x8f\x8b\x82\x76\x5a\xbd\x8f\x6f\x62\x18\xe1\xd9\xaa" "\x41\xfd\xed\x68\x01\xc6\x34\x35\xb0\x29\x04\xca\x4a\x4a\x1c\x7e" "\x80\x14\xf7\x8e\x77\xb8\x25\xff\x16\x47\x6f\xbd\xe2\x34\x3d\x2e" "\x02\xb9\x53\xe4\x33\x75\xad\x73\x28\x80\xa0\x4d\xfc\x6c\xc0\x22" "\x53\x1b\x2c\xf8\xf5\x01\x60\x19\x7e\x79\x19\x39\x8d\xb5\xce\x39" "\x58\xdd\x55\x24\x3b\x55\x7b\x43\xc1\x7f\x14\x2f\xb0\x64\x3a\x54" "\x95\x2b\x88\x49\x0c\x61\x2d\xac\xf8\x45\xf5\xda\x88\x18\x5f\xae" "\x42\xf8\x75\xc7\x26\x6d\xb5\xbb\x39\x6f\xcc\x55\x1b\x32\x11\x38" "\x8d\xe4\xe9\x44\x84\x11\x36\xa2\x61\x76\xaa\x4c\xb4\xe3\x55\x0f" "\xe4\x77\x8e\xde\xe3\xa9\xea\xb7\x41\x94\x00\x58\xaa\xc9\x34\xa2" "\x98\xc6\x01\x1a\x76\x14\x01\xa8\xdc\x30\x7c\x77\x5a\x20\x71\x5a" "\xa2\x3f\xaf\x13\x7e\xe8\xfd\x84\xa2\x5b\xcf\x25\xe9\xc7\x8f\xa8" "\xf2\x8b\x84\xc7\x04\x5e\x53\x73\x4e\x0e\x89\xa3\x3c\xe7\x68\x5c" "\x24\xb7\x80\x53\x3c\x54\xc8\xc1\x53\xaa\x71\x71\x3d\x36\x15\xd6" "\x6a\x9d\x7d\xde\xae\xf9\xe6\xaf\x57\xae\xb9\x01\x96\x5d\xe0\x4d" "\xcd\xed\xc8\xd7\xf3\x01\x03\x38\x10\xbe\x7c\x42\x67\x01\xa7\x23"; uint8 license_server_exponent[4] = "\x00\x01\x00\x01"; uint8 terminal_server_modulus[256] = "\xc8\x90\x6b\xf0\xc6\x58\x81\xa6\x89\x1c\x0e\xf2\xf6\xd9\x82\x12" "\x71\xa5\x6e\x51\xdb\xe0\x32\x66\xaa\x91\x77\x0e\x88\xab\x44\xb7" "\xd3\x97\xda\x78\x8f\x0e\x44\x26\x46\x7f\x16\xd4\xc6\x63\xeb\xca" "\x55\xe5\x4e\x8b\x2d\xa6\x6d\x83\x95\xa7\xa8\x6a\xfa\xd0\xbe\x26" "\x80\xae\xab\x0a\x64\x90\x32\x8c\xdf\x5c\xf8\xf9\xd0\x7e\xd1\x6b" "\x3a\x29\x7e\x7d\xbd\x02\xa3\x86\x6c\xfd\xa5\x35\x71\xda\x21\xb4" "\xee\xa4\x97\xf3\xa8\xb2\x12\xdb\xa4\x27\x57\x36\xc9\x08\x22\x5c" "\x54\xf7\x99\x7b\xa3\x2f\xb8\x5c\xd5\x16\xb8\x19\x27\x6b\x71\x97" "\x14\x5b\xe8\x1f\x23\xe8\x5c\xb8\x1b\x73\x4b\x6e\x7a\x03\x13\xff" "\x97\xe9\x62\xb9\x4a\xa0\x51\x23\xc3\x6c\x32\x3e\x02\xf2\x63\x97" "\x23\x1c\xc5\x78\xd8\xfc\xb7\x07\x4b\xb0\x56\x0f\x74\xdf\xc5\x56" "\x28\xe4\x96\xfd\x20\x8e\x65\x5a\xe6\x45\xed\xc1\x05\x3e\xab\x58" "\x55\x40\xaf\xe2\x47\xa0\x4c\x49\xa3\x8d\x39\xe3\x66\x5f\x93\x33" "\x6d\xf8\x5f\xc5\x54\xe5\xfb\x57\x3a\xde\x45\x12\xb5\xc7\x05\x4b" "\x88\x1f\xb4\x35\x0f\x7c\xc0\x75\x17\xc6\x67\xdd\x48\x80\xcb\x0a" "\xbe\x9d\xf6\x93\x60\x65\x34\xeb\x97\xaf\x65\x6d\xdf\xbf\x6f\x5b"; uint8 terminal_server_exponent[4] = "\x00\x01\x00\x01"; uint8 client_random[32] = "\xdc\x73\xa0\xc8\x69\x25\x6b\x18\xaf\x0b\x94\x7a\xa9\xa5\x20\xaf" "\x8b\xbc\x0d\xcc\xa3\x95\xb7\xb9\xeb\x81\x5d\xbe\x0a\x10\x9c\xd8"; uint8 server_random[32] = "\x84\xef\xae\x20\xb1\xd5\x9e\x36\x49\x1a\xe8\x2e\x0a\x99\x89\xac" "\x49\xa6\x47\x4f\x33\x9b\x5a\xb9\x95\x03\xa6\xc6\xc2\x3c\x3f\x61"; uint8 premaster_secret[48] = "\xcf\x7a\xdb\xcb\xfb\x0e\x15\x23\x87\x1c\x84\x81\xba\x9d\x4e\x15" "\xbb\xd2\x56\xbd\xd8\xf7\xf3\x16\xcc\x35\x3b\xe1\x93\x42\x78\xdd" "\x92\x9a\xe4\x7a\xe2\x99\xd4\x73\xb1\xaa\x6f\x55\x94\x3b\xc9\xbc"; uint8 encrypted_premaster_secret[264] = "\xda\x9c\x5d\xa6\x68\x9d\xa3\x90\x67\x24\xf3\x3a\xea\xa1\xe2\x68" "\xad\x12\xf5\xf6\x0b\x7a\xac\x92\xb1\x69\x6f\x42\x55\x8a\xa0\xe2" "\x9b\x2c\xd0\xc7\xee\x33\x6c\x47\x79\xc3\x1e\xbf\x03\x8b\x95\x70" "\x07\xa2\xbe\xee\x54\x02\x68\xf8\x90\xd7\xfe\x2c\x08\xe1\x6b\x2d" "\xff\x94\x76\x72\x5f\x7a\x76\x75\x32\x55\xcc\x58\x61\x63\xa5\x64" "\xf1\x6e\xc3\x07\x81\x82\x6f\x88\x73\x62\xfc\x28\x65\x91\xc2\xc8" "\x9f\x05\xb0\xd3\x93\x12\xbf\x6a\x50\x18\x99\x2d\x4d\xc4\x7f\x74" "\xd3\x30\x9f\x16\x78\xa5\xdf\xaa\x83\x65\x4f\x77\x30\x42\xe0\xd7" "\x69\xc8\x4d\xa5\x73\x11\x59\x35\xb9\xa7\xe2\xb0\xf6\xe3\xb9\x39" "\xc3\xd4\xe4\x6b\xca\x40\x9a\xac\x66\xe6\x1a\xa4\x1b\x39\x7e\x09" "\xe3\x72\x99\xdd\x90\x62\x55\x97\xa9\x04\xc7\x51\xaa\xa2\x01\xcb" "\x5a\x63\x4d\x1a\xe5\x99\xc3\xb1\x2a\x73\xe8\x9a\x00\x46\x92\x59" "\x39\xa3\x80\xa1\xac\x90\x52\xea\x63\x81\x49\x7d\xf3\x2d\x5c\xc3" "\x19\x9f\xed\xfe\x81\x1d\x8c\x04\x1c\xd9\x23\xd2\x6d\x80\x84\xf3" "\x00\xf2\xb1\x69\x2f\xcd\xb3\x9f\x69\xee\x60\x3e\x4b\xb5\xbe\x5a" "\x09\x83\x0b\xbc\x3d\x3e\x05\x47\x65\x96\x31\x8c\x6b\xc5\xe6\xa0" "\x00\x00\x00\x00\x00\x00\x00\x00"; uint8 platform_challenge[10] = "\x54\x00\x45\x00\x53\x00\x54\x00\x00\x00"; void test_license(void) { STREAM _s, *s; s = &_s; memcpy(license->client_random, client_random, sizeof(client_random)); memcpy(license->premaster_secret, premaster_secret, sizeof(premaster_secret)); s->data = server_license_request; s->p = s->data + LICENSE_PREAMBLE_LENGTH; license_read_license_request_packet(license, s); #if 0 printf("\n"); printf("client random:\n"); freerdp_hexdump(license->client_random, 32); printf("\n"); printf("server random:\n"); freerdp_hexdump(license->server_random, 32); printf("\n"); printf("premaster secret:\n"); freerdp_hexdump(license->premaster_secret, 48); printf("\n"); printf("master secret:\n"); freerdp_hexdump(license->master_secret, 48); printf("\n"); printf("session key blob:\n"); freerdp_hexdump(license->session_key_blob, 48); printf("\n"); printf("licensing encryption key:\n"); freerdp_hexdump(license->licensing_encryption_key, 16); printf("\n"); printf("mac salt key:\n"); freerdp_hexdump(license->mac_salt_key, 16); printf("\n"); printf("modulus:\n"); freerdp_hexdump(license->certificate->cert_info.modulus.data, license->certificate->cert_info.modulus.length); printf("\n"); printf("exponent:\n"); freerdp_hexdump(license->certificate->cert_info.exponent, 4); printf("\n"); printf("encrypted premaster secret:\n"); freerdp_hexdump(license->encrypted_premaster_secret->data, license->encrypted_premaster_secret->length); printf("\n"); #endif s->data = server_platform_challenge; s->p = s->data + LICENSE_PREAMBLE_LENGTH; license_read_platform_challenge_packet(license, s); } uint8 test_client_random[32] = "\xdc\x73\xa0\xc8\x69\x25\x6b\x18\xaf\x0b\x94\x7a\xa9\xa5\x20\xaf" "\x8b\xbc\x0d\xcc\xa3\x95\xb7\xb9\xeb\x81\x5d\xbe\x0a\x10\x9c\xd8"; uint8 test_server_random[32] = "\x16\x7e\xf8\x71\x48\x16\x1a\x4f\xa5\x2c\xcd\x73\x63\x60\xa6\xc3" "\xb9\x19\x1b\x4b\x6b\xb2\x0a\xb8\xec\xf1\x8d\x95\x4e\xa8\x21\xc5"; uint8 test_premaster_secret[48] = "\xcf\x7a\xdb\xcb\xfb\x0e\x15\x23\x87\x1c\x84\x81\xba\x9d\x4e\x15" "\xbb\xd2\x56\xbd\xd8\xf7\xf3\x16\xcc\x35\x3b\xe1\x93\x42\x78\xdd" "\x92\x9a\xe4\x7a\xe2\x99\xd4\x73\xb1\xaa\x6f\x55\x94\x3b\xc9\xbc"; uint8 test_modulus[64] = "\x23\xc9\xec\x0e\x9f\x1e\x0e\x1a\x78\xaf\xa5\x14\xd4\xf5\x45\xe4" "\x04\x6e\xf4\x01\xe9\xdf\x45\xd1\xc2\xae\xf4\x7f\xd3\xb9\xcb\xf3" "\x1a\x23\xa1\x0d\x4b\xd4\xd1\x4a\xd2\xd1\xc9\x7c\xab\x24\x8b\xb1" "\x5a\x93\xca\x34\x44\x17\xb5\xe4\xfe\xf7\x9a\xaa\x72\x0d\x41\x95"; uint8 test_exponent[4] = "\x01\x00\x01\x00"; uint8 test_master_secret[48] = "\xbe\x51\xee\x63\x23\x90\xd0\xf4\x3a\xce\x3a\x37\x65\xc3\xdd\xcf" "\xed\xf0\xc8\x19\xed\x77\x33\x4e\xfd\x2b\x7d\x5a\xe2\xca\xf3\x0a" "\xf1\x16\xe5\x0c\x78\x59\x7e\xd4\x4b\x57\xce\x17\x60\x3a\x5a\xb3"; uint8 test_session_key_blob[48] = "\x07\x4f\xa0\x2e\xee\xc4\x5a\x46\x21\x8c\xae\x01\x45\x02\x26\xe4" "\x54\x6b\x59\x10\xcc\x5b\xd1\x96\xd0\x5c\xeb\xc2\x96\x9b\x44\x7b" "\x1c\xd9\x66\xb1\x9e\x24\xaa\x60\x4f\x89\xd1\x4e\xf8\xb9\x55\x3b"; uint8 test_mac_salt_key[16] = "\x07\x4f\xa0\x2e\xee\xc4\x5a\x46\x21\x8c\xae\x01\x45\x02\x26\xe4"; uint8 test_licensing_encryption_key[16] = "\xf3\xb1\xe0\x3b\xfe\xb4\xf2\xc5\x28\xa9\x48\xcd\x90\xf1\x93\xe5"; uint8 test_encrypted_premaster_secret[64] = "\x6b\xbc\x77\x9f\x20\x0c\x98\x39\xc1\x85\x77\xc8\x19\x87\xd8\x82" "\x93\xbd\x21\x69\x5f\x87\xe0\xd6\x4e\xad\x5e\x23\x13\x80\x8c\x63" "\x3e\xd6\x6e\x60\xc9\x40\xe9\x86\x08\x8c\xd5\xaa\xa9\x54\xfe\x27" "\x4c\x1f\x87\x57\xde\xca\xd4\xc7\x1e\x46\x9e\x00\x7a\xdb\x47\x23"; void test_license_generate_keys(void) { STREAM _s, *s; s = &_s; memcpy(license->client_random, client_random, sizeof(client_random)); memcpy(license->server_random, test_server_random, sizeof(test_server_random)); memcpy(license->premaster_secret, premaster_secret, sizeof(premaster_secret)); memcpy(license->certificate->cert_info.exponent, test_exponent, sizeof(test_exponent)); memcpy(license->certificate->cert_info.modulus.data, test_modulus, sizeof(test_modulus)); license->certificate->cert_info.modulus.length = sizeof(test_modulus); license_generate_keys(license); license_encrypt_premaster_secret(license); s->data = license->master_secret; s->p = s->data + sizeof(test_master_secret); ASSERT_STREAM(s, test_master_secret, sizeof(test_master_secret)); s->data = license->session_key_blob; s->p = s->data + sizeof(test_session_key_blob); ASSERT_STREAM(s, test_session_key_blob, sizeof(test_session_key_blob)); s->data = license->mac_salt_key; s->p = s->data + sizeof(test_mac_salt_key); ASSERT_STREAM(s, test_mac_salt_key, sizeof(test_mac_salt_key)); s->data = license->licensing_encryption_key; s->p = s->data + sizeof(test_licensing_encryption_key); ASSERT_STREAM(s, test_licensing_encryption_key, sizeof(test_licensing_encryption_key)); s->data = license->encrypted_premaster_secret->data; s->p = s->data + sizeof(test_encrypted_premaster_secret); ASSERT_STREAM(s, test_encrypted_premaster_secret, sizeof(test_encrypted_premaster_secret)); } void test_license_encrypt_premaster_secret(void) { STREAM _s, *s; s = &_s; memcpy(license->premaster_secret, premaster_secret, sizeof(premaster_secret)); memcpy(license->certificate->cert_info.exponent, test_exponent, sizeof(test_exponent)); memcpy(license->certificate->cert_info.modulus.data, test_modulus, sizeof(test_modulus)); license->certificate->cert_info.modulus.length = sizeof(test_modulus); s->data = license->encrypted_premaster_secret->data; s->p = s->data + sizeof(test_encrypted_premaster_secret); ASSERT_STREAM(s, test_encrypted_premaster_secret, sizeof(test_encrypted_premaster_secret)); } uint8 test_encrypted_platform_challenge[10] = "\x84\x0a\x42\x50\xad\x5e\xc1\x29\x30\xbd"; uint8 test_platform_challenge[10] = "\x54\x00\x45\x00\x53\x00\x54\x00\x00\x00"; void test_license_decrypt_platform_challenge(void) { STREAM _s, *s; s = &_s; memcpy(license->licensing_encryption_key, test_licensing_encryption_key, sizeof(test_licensing_encryption_key)); license->encrypted_platform_challenge->data = (uint8*) xmalloc(sizeof(test_encrypted_platform_challenge)); license->encrypted_platform_challenge->length = sizeof(test_encrypted_platform_challenge); memcpy(license->encrypted_platform_challenge->data, test_encrypted_platform_challenge, sizeof(test_encrypted_platform_challenge)); license_decrypt_platform_challenge(license); s->data = license->platform_challenge->data; s->p = s->data + sizeof(test_platform_challenge); ASSERT_STREAM(s, test_platform_challenge, sizeof(test_platform_challenge)); } FreeRDP-1.0.2/cunit/test_license.h000066400000000000000000000017341207112532300167160ustar00rootroot00000000000000/** * FreeRDP: A Remote Desktop Protocol Client * Licensing Unit Tests * * Copyright 2011 Marc-Andre Moreau * * 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. */ #include "test_freerdp.h" int init_license_suite(void); int clean_license_suite(void); int add_license_suite(void); void test_license(void); void test_license_generate_keys(void); void test_license_encrypt_premaster_secret(void); void test_license_decrypt_platform_challenge(void); FreeRDP-1.0.2/cunit/test_list.c000066400000000000000000000036441207112532300162440ustar00rootroot00000000000000/** * FreeRDP: A Remote Desktop Protocol Client * List Unit Tests * * Copyright 2011 Vic Lee * * 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. */ #include #include #include #include #include #include "test_list.h" int init_list_suite(void) { return 0; } int clean_list_suite(void) { return 0; } int add_list_suite(void) { add_test_suite(list); add_test_function(list); return 0; } struct _my_list_item { uint32 a; uint32 b; }; typedef struct _my_list_item my_list_item; void test_list(void) { LIST* list; LIST_ITEM* list_item; my_list_item* item; my_list_item* item1; my_list_item* item2; int i; list = list_new(); for (i = 0; i < 10; i++) { item = xnew(my_list_item); item->a = i; item->b = i * i; list_enqueue(list, item); } for (i = 0, list_item = list->head; list_item; i++, list_item = list_item->next) { CU_ASSERT(((my_list_item*)list_item->data)->a == i); CU_ASSERT(((my_list_item*)list_item->data)->b == i * i); /*printf("%d %d\n", item->a, item->b);*/ } item1 = xnew(my_list_item); list_add(list, item1); item2 = xnew(my_list_item); list_add(list, item2); CU_ASSERT(list_remove(list, item1) == item1); xfree(item1); CU_ASSERT(list_remove(list, item2) == item2); CU_ASSERT(list_remove(list, item2) == NULL); xfree(item2); while ((item = list_dequeue(list)) != NULL) xfree(item); list_free(list); } FreeRDP-1.0.2/cunit/test_list.h000066400000000000000000000014271207112532300162460ustar00rootroot00000000000000/** * FreeRDP: A Remote Desktop Protocol Client * List Unit Tests * * Copyright 2011 Vic Lee * * 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. */ #include "test_freerdp.h" int init_list_suite(void); int clean_list_suite(void); int add_list_suite(void); void test_list(void); FreeRDP-1.0.2/cunit/test_mcs.c000066400000000000000000000110321207112532300160410ustar00rootroot00000000000000/** * FreeRDP: A Remote Desktop Protocol Client * T.125 Multipoint Communication Service (MCS) Protocol Unit Tests * * Copyright 2011 Marc-Andre Moreau * * 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. */ #include "mcs.h" #include #include #include #include "test_mcs.h" int init_mcs_suite(void) { return 0; } int clean_mcs_suite(void) { return 0; } int add_mcs_suite(void) { add_test_suite(mcs); add_test_function(mcs_write_connect_initial); return 0; } uint8 gcc_CCrq[307] = "\x00\x05\x00\x14\x7C\x00\x01\x81\x2A\x00\x08\x00\x10\x00\x01\xC0" "\x00\x44\x75\x63\x61\x81\x1c\x01\xc0\xd8\x00\x04\x00\x08\x00\x00" "\x05\x00\x04\x01\xCA\x03\xAA\x09\x04\x00\x00\xCE\x0E\x00\x00\x45" "\x00\x4c\x00\x54\x00\x4f\x00\x4e\x00\x53\x00\x2d\x00\x44\x00\x45" "\x00\x56\x00\x32\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x04" "\x00\x00\x00\x00\x00\x00\x00\x0c\x00\x00\x00\x00\x00\x00\x00\x00" "\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00" "\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00" "\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00" "\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x01\xCA\x01\x00\x00" "\x00\x00\x00\x18\x00\x07\x00\x01\x00\x36\x00\x39\x00\x37\x00\x31" "\x00\x32\x00\x2d\x00\x37\x00\x38\x00\x33\x00\x2d\x00\x30\x00\x33" "\x00\x35\x00\x37\x00\x39\x00\x37\x00\x34\x00\x2d\x00\x34\x00\x32" "\x00\x37\x00\x31\x00\x34\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00" "\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x04" "\xC0\x0C\x00\x0D\x00\x00\x00\x00\x00\x00\x00\x02\xC0\x0C\x00\x1B" "\x00\x00\x00\x00\x00\x00\x00\x03\xC0\x2C\x00\x03\x00\x00\x00\x72" "\x64\x70\x64\x72\x00\x00\x00\x00\x00\x80\x80\x63\x6c\x69\x70\x72" "\x64\x72\x00\x00\x00\xA0\xC0\x72\x64\x70\x73\x6e\x64\x00\x00\x00" "\x00\x00\xc0"; uint8 mcs_connect_initial_expected[409] = "\x7F\x65\x82\x01\x94\x04\x01\x01\x04\x01\x01\x01\x01\xFF\x30\x19" "\x02\x01\x22\x02\x01\x02\x02\x01\x00\x02\x01\x01\x02\x01\x00\x02" "\x01\x01\x02\x02\xFF\xFF\x02\x01\x02\x30\x19\x02\x01\x01\x02\x01" "\x01\x02\x01\x01\x02\x01\x01\x02\x01\x00\x02\x01\x01\x02\x02\x04" "\x20\x02\x01\x02\x30\x1C\x02\x02\xFF\xFF\x02\x02\xFC\x17\x02\x02" "\xFF\xFF\x02\x01\x01\x02\x01\x00\x02\x01\x01\x02\x02\xFF\xFF\x02" "\x01\x02\x04\x82\x01\x33\x00\x05\x00\x14\x7C\x00\x01\x81\x2A\x00" "\x08\x00\x10\x00\x01\xC0\x00\x44\x75\x63\x61\x81\x1c\x01\xc0\xd8" "\x00\x04\x00\x08\x00\x00\x05\x00\x04\x01\xCA\x03\xAA\x09\x04\x00" "\x00\xCE\x0E\x00\x00\x45\x00\x4c\x00\x54\x00\x4f\x00\x4e\x00\x53" "\x00\x2d\x00\x44\x00\x45\x00\x56\x00\x32\x00\x00\x00\x00\x00\x00" "\x00\x00\x00\x00\x00\x04\x00\x00\x00\x00\x00\x00\x00\x0c\x00\x00" "\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00" "\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00" "\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00" "\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00" "\x00\x01\xCA\x01\x00\x00\x00\x00\x00\x18\x00\x07\x00\x01\x00\x36" "\x00\x39\x00\x37\x00\x31\x00\x32\x00\x2d\x00\x37\x00\x38\x00\x33" "\x00\x2d\x00\x30\x00\x33\x00\x35\x00\x37\x00\x39\x00\x37\x00\x34" "\x00\x2d\x00\x34\x00\x32\x00\x37\x00\x31\x00\x34\x00\x00\x00\x00" "\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00" "\x00\x00\x00\x00\x00\x04\xC0\x0C\x00\x0D\x00\x00\x00\x00\x00\x00" "\x00\x02\xC0\x0C\x00\x1B\x00\x00\x00\x00\x00\x00\x00\x03\xC0\x2C" "\x00\x03\x00\x00\x00\x72\x64\x70\x64\x72\x00\x00\x00\x00\x00\x80" "\x80\x63\x6c\x69\x70\x72\x64\x72\x00\x00\x00\xA0\xC0\x72\x64\x70" "\x73\x6e\x64\x00\x00\x00\x00\x00\xc0"; void test_mcs_write_connect_initial(void) { STREAM* s; rdpMcs* mcs; STREAM _user_data, *user_data; mcs = mcs_new((rdpTransport*) NULL); user_data = &_user_data; user_data->data = gcc_CCrq; user_data->p = user_data->data + sizeof(gcc_CCrq); s = stream_new(512); mcs_write_connect_initial(s, mcs, user_data); ASSERT_STREAM(s, (uint8*) mcs_connect_initial_expected, sizeof(mcs_connect_initial_expected)); stream_free(s); } FreeRDP-1.0.2/cunit/test_mcs.h000066400000000000000000000016011207112532300160470ustar00rootroot00000000000000/** * FreeRDP: A Remote Desktop Protocol Client * T.125 Multipoint Communication Service (MCS) Protocol Unit Tests * * Copyright 2011 Marc-Andre Moreau * * 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. */ #include "test_freerdp.h" int init_mcs_suite(void); int clean_mcs_suite(void); int add_mcs_suite(void); void test_mcs_write_connect_initial(void); FreeRDP-1.0.2/cunit/test_mppc.c000066400000000000000000001666571207112532300162460ustar00rootroot00000000000000/** * FreeRDP: A Remote Desktop Protocol Client * Microsoft Point to Point Compression (MPPC) Unit Tests * * Copyright 2011 Laxmikant Rashinkar * * 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. */ #include #include #include #include "rdp.h" #include "test_mppc.h" uint8_t compressed_rd5[] = { 0x24, 0x02, 0x03, 0x09, 0x00, 0x20, 0x0c, 0x05, 0x10, 0x01, 0x40, 0x0a, 0xbf, 0xdf, 0xc3, 0x20, 0x80, 0x00, 0x1f, 0x0a, 0x00, 0x00, 0x07, 0x43, 0x4e, 0x00, 0x68, 0x02, 0x00, 0x22, 0x00, 0x34, 0xcb, 0xfb, 0xf8, 0x18, 0x40, 0x01, 0x00, 0x27, 0xe2, 0x90, 0x0f, 0xc3, 0x91, 0xa8, 0x00, 0x08, 0x00, 0x00, 0x68, 0x50, 0x60, 0x65, 0xfc, 0x0e, 0xfe, 0x04, 0x00, 0x08, 0x00, 0x06, 0x0c, 0x00, 0x01, 0x00, 0xf8, 0x40, 0x20, 0x00, 0x00, 0x90, 0x00, 0xcf, 0x95, 0x1f, 0x44, 0x90, 0x00, 0x6e, 0x03, 0xf4, 0x40, 0x21, 0x9f, 0x26, 0x01, 0xbf, 0x88, 0x10, 0x90, 0x00, 0x08, 0x04, 0x00, 0x04, 0x30, 0x03, 0xe4, 0xc7, 0xea, 0x05, 0x1e, 0x87, 0xf8, 0x20, 0x1c, 0x00, 0x10, 0x84, 0x22, 0x1f, 0x71, 0x0d, 0x0e, 0xb9, 0x88, 0x9f, 0x5c, 0xee, 0x41, 0x97, 0xfb, 0xf8, 0x88, 0x68, 0x08, 0x6d, 0xd0, 0x44, 0xfc, 0x34, 0x06, 0xe6, 0x16, 0x21, 0x04, 0x11, 0x0f, 0xb9, 0x85, 0x86, 0x5d, 0x44, 0x4f, 0xae, 0xb7, 0x40, 0xa8, 0xcd, 0x5b, 0xed, 0x02, 0xee, 0xc2, 0x21, 0x40, 0x21, 0x21, 0x23, 0x17, 0xb7, 0x00, 0x60, 0x00, 0x3b, 0xfd, 0xfc, 0x00, 0x0c, 0x00, 0x08, 0x00, 0x34, 0x00, 0x33, 0xc7, 0xe0, 0xc0, 0x0f, 0x07, 0x12, 0x42, 0x01, 0xe8, 0x6c, 0xc7, 0x83, 0x07, 0x8c, 0xd4, 0x30, 0x07, 0x20, 0x01, 0x90, 0xa3, 0xf1, 0xdb, 0xf5, 0xd4, 0x13, 0xc2, 0x4f, 0x0f, 0xe5, 0xe2, 0xc7, 0x87, 0xf2, 0xf0, 0x93, 0xc3, 0xf9, 0x78, 0xb0, 0x1a, 0x03, 0xe1, 0xf1, 0xd0, 0x08, 0x4c, 0x66, 0xac, 0x32, 0x31, 0x70, 0x60, 0x11, 0x01, 0x11, 0x01, 0x01, 0x01, 0xf0, 0x36, 0x1f, 0xe5, 0xe0, 0x6c, 0xbc, 0x26, 0xf0, 0x36, 0x5f, 0xe5, 0xe0, 0x6c, 0xbc, 0x26, 0xf0, 0x34, 0xf9, 0x94, 0x32, 0x31, 0x74, 0x20, 0x10, 0x00, 0x00, 0x0f, 0xbf, 0x87, 0xdf, 0xef, 0xfe, 0x4b, 0xbf, 0x02, 0xfa, 0xde, 0xa7, 0x79, 0x32, 0x44, 0x7c, 0x20, 0x82, 0x00, 0x5f, 0xef, 0xff, 0x09, 0xe1, 0x05, 0x74, 0x32, 0xea, 0x09, 0xe1, 0x0f, 0x55, 0x83, 0x85, 0x2a, 0xa0, 0x1d, 0x50, 0x0e, 0x0e, 0x0b, 0x01, 0x01, 0x43, 0x06, 0x02, 0xbe, 0x5f, 0x00, 0x00, 0x0c, 0x3d, 0x4d, 0x87, 0xa6, 0x5e, 0xa6, 0xcb, 0xc3, 0xcf, 0x53, 0x65, 0xe9, 0x97, 0xa9, 0xb2, 0xf5, 0x9b, 0xd4, 0xd3, 0xee, 0xcd, 0xc0, 0x7c, 0xae, 0xe0, 0x65, 0x1f, 0xe5, 0xe0, 0x6c, 0xbc, 0x26, 0xf0, 0x36, 0x5f, 0xe5, 0xe0, 0x6c, 0xbc, 0x26, 0xf0, 0x34, 0xfb, 0xb3, 0xf2, 0x41, 0x30, 0x20, 0x04, 0xa0, 0x80, 0x93, 0xf3, 0xf2, 0x1b, 0xed, 0xf6, 0x0f, 0x04, 0x82, 0x7b, 0xcc, 0x00, 0x65, 0xef, 0x4f, 0x86, 0x02, 0xf7, 0xa7, 0xe0, 0x0a, 0x88, 0x1c, 0x34, 0x02, 0x02, 0x02, 0x60, 0x60, 0x49, 0x40, 0xc1, 0x2f, 0x14, 0xca, 0x60, 0xc1, 0x81, 0x80, 0x07, 0xc3, 0x00, 0x00, 0x39, 0xfa, 0x86, 0x38, 0x93, 0x47, 0x08, 0x27, 0x08, 0xfc, 0xb8, 0x4e, 0x38, 0x47, 0xe5, 0xc2, 0x09, 0xc2, 0x3f, 0x2e, 0x13, 0x8e, 0x11, 0xf3, 0xc3, 0x57, 0x1a, 0x88, 0x7d, 0x44, 0x3c, 0x3c, 0x04, 0x0f, 0xd4, 0x3f, 0x83, 0x8d, 0x82, 0x00, 0x25, 0x04, 0x84, 0xdf, 0xe0, 0x17, 0xf8, 0x04, 0x03, 0xe1, 0x47, 0xc4, 0xaf, 0x9c, 0x00, 0x00, 0x31, 0xf5, 0x4c, 0x71, 0x78, 0x8f, 0x54, 0xfb, 0x1c, 0x97, 0xa4, 0x04, 0x13, 0xd5, 0x2f, 0x77, 0xc7, 0xb8, 0x9e, 0xef, 0xcb, 0xc2, 0x6f, 0x77, 0xe5, 0xee, 0x27, 0xbb, 0xf2, 0xf7, 0xe3, 0xdd, 0xf3, 0xc6, 0xfb, 0x2a, 0x78, 0x6d, 0x3c, 0x34, 0x37, 0xc0, 0xaf, 0x25, 0xc7, 0x81, 0x7d, 0x6e, 0x5d, 0x5c, 0xd6, 0xe3, 0x43, 0xc0, 0x82, 0xd0, 0x95, 0x90, 0xd8, 0xbd, 0xfc, 0x00, 0x09, 0xc0, 0x34, 0x39, 0x46, 0x84, 0x20, 0x40, 0x38, 0xa3, 0x42, 0x12, 0xb0, 0x55, 0xbe, 0x28, 0xc0, 0x70, 0x64, 0x28, 0xc8, 0x48, 0x42, 0x08, 0xb2, 0x1b, 0x46, 0xa6, 0x09, 0x54, 0x2e, 0x5f, 0x73, 0x84, 0xfc, 0x28, 0x4a, 0x73, 0x79, 0xf2, 0x6c, 0x5d, 0x82, 0x82, 0x6e, 0xc2, 0x27, 0xd7, 0x6b, 0xb8, 0x4f, 0xa4, 0xa4, 0x22, 0xee, 0x22, 0x7e, 0x10, 0x03, 0x78, 0x08, 0xf4, 0x94, 0x5e, 0x02, 0x01, 0xef, 0x02, 0x27, 0xd7, 0x8b, 0xc8, 0x3f, 0xa4, 0xa4, 0x1a, 0xf3, 0xd1, 0x84, 0x0c, 0x32, 0x31, 0x75, 0x60, 0x05, 0xe2, 0x30, 0xb7, 0xad, 0x5b, 0x15, 0xd5, 0xc3, 0xc0, 0x00, 0x11, 0x81, 0x81, 0x69, 0x8f, 0x06, 0x0f, 0x14, 0xcf, 0xa6, 0xe8, 0xb1, 0x22, 0x77, 0xeb, 0xd7, 0x45, 0x89, 0xf0, 0xb6, 0x3e, 0x23, 0x06, 0x80, 0xf8, 0x5b, 0x0f, 0x04, 0x83, 0xfc, 0x2d, 0x8f, 0x88, 0xc1, 0xa0, 0x3e, 0x16, 0x1d, 0x00, 0x83, 0x74, 0x58, 0xa0, 0xc0, 0x10, 0xce, 0x8b, 0x17, 0xe0, 0x68, 0xff, 0x20, 0xff, 0x03, 0x63, 0xe5, 0xcf, 0x1f, 0xa0, 0x40, 0x00, 0x00, 0x2a, 0xff, 0xd6, 0xd1, 0xc0, 0xb9, 0xe0, 0x5f, 0x6b, 0x81, 0x73, 0xc9, 0x93, 0xd1, 0x63, 0x50, 0xf0, 0x9b, 0xf0, 0x48, 0x4f, 0xaf, 0xe0, 0x1b, 0xef, 0x82, 0x6f, 0xc2, 0x40, 0xe0, 0xe4, 0x60, 0xa0, 0x69, 0xa1, 0xa1, 0xbe, 0xba, 0x04, 0x00, 0x08, 0x00, 0x10, 0x00, 0x20, 0x00, 0x42, 0x00, 0x44, 0x00, 0x88, 0x01, 0x10, 0x02, 0x21, 0x02, 0x22, 0x04, 0x44, 0x08, 0x9c, 0x8f, 0xcd, 0xe0, 0x02, 0x20, 0x88, 0x02, 0x10, 0x40, 0x01, 0xf0, 0x60, 0x44, 0xc0, 0xce, 0xb1, 0x8f, 0xd0, 0x30, 0x00, 0x60, 0x00, 0xa0, 0x00, 0xc4, 0x00, 0xcc, 0x01, 0x98, 0x03, 0x28, 0x03, 0x31, 0x03, 0x33, 0x06, 0x66, 0x07, 0x0e, 0x2c, 0xe3, 0x7b, 0x18, 0x85, 0xc7, 0xd6, 0x51, 0x71, 0x0f, 0x0e, 0xb8, 0x88, 0x9f, 0x5c, 0x6e, 0x41, 0xde, 0xeb, 0x71, 0x20, 0x5c, 0xba, 0xf7, 0xc8, 0x6f, 0xba, 0xc1, 0xf7, 0x30, 0xd0, 0xce, 0xc1, 0x31, 0x74, 0xec, 0x13, 0x41, 0x77, 0x41, 0x13, 0xa0, 0x10, 0xbf, 0x7c, 0x45, 0xd3, 0xa5, 0xbc, 0x55, 0x84, 0xaa, 0x41, 0xc1, 0xc1, 0xe0, 0xe0, 0x29, 0x01, 0x20, 0x81, 0x00, 0x03, 0x80, 0x07, 0xc0, 0x0f, 0xe0, 0x06, 0xbe, 0x16, 0x75, 0xe7, 0x9f, 0xfb, 0x1e, 0x17, 0x90, 0xef, 0x0b, 0xbb, 0x15, 0x03, 0x7c, 0x2b, 0x7e, 0x22, 0x78, 0x56, 0x83, 0xae, 0x77, 0x40, 0xcf, 0xb0, 0xf0, 0x98, 0x28, 0x04, 0x2f, 0xaf, 0x0e, 0x40, 0xfc, 0x01, 0x1c, 0x5c, 0xb1, 0xf2, 0xbf, 0xa5, 0xd7, 0x8f, 0x97, 0xc0, 0xfe, 0x9f, 0x02, 0xe7, 0x24, 0x79, 0xe0, 0x9b, 0xa9, 0xfd, 0x74, 0x3b, 0xaf, 0x2d, 0xf8, 0x4b, 0xd2, 0xf7, 0x84, 0x54, 0x04, 0x2a, 0x02, 0x02, 0x01, 0xe1, 0x1e, 0xf0, 0x87, 0xff, 0x77, 0x07, 0x00, 0x02, 0x00, 0x0d, 0xbd, 0xe1, 0xf0, 0x01, 0x1e, 0xf0, 0xfd, 0x80, 0x4c, 0x24, 0x11, 0x2c, 0x10, 0x24, 0x02, 0x01, 0x40, 0xb0, 0x5c, 0x2c, 0x14, 0x08, 0x07, 0x1b, 0x80, 0x01, 0xa7, 0xbd, 0x3e, 0x00, 0x27, 0xde, 0x9f, 0xb0, 0x85, 0x01, 0xfb, 0xd2, 0x04, 0x0c, 0x1c, 0x2e, 0x0e, 0x06, 0x18, 0x03, 0xd4, 0x00, 0x00, 0x67, 0xef, 0x4f, 0x80, 0x0a, 0xf7, 0xa7, 0xe3, 0x94, 0xe0, 0xe0, 0x10, 0x1b, 0xfd, 0xfc, 0x74, 0x62, 0xe8, 0xc0, 0x1d, 0x62, 0x00, 0x0b, 0x00, 0xb7, 0x70, 0xe6, 0x8a, 0x68, 0x75, 0x38, 0x3c, 0x3c, 0x4c, 0x2f, 0x87, 0xef, 0x01, 0xc7, 0xb2, 0x40, 0x21, 0xa3, 0x23, 0x0a, 0x08, 0x01, 0xa1, 0xa1, 0xe1, 0x80, 0x69, 0x40, 0xe1, 0x00, 0x00, 0x40, 0xd0, 0xea, 0xe5, 0xe1, 0xc0, 0x81, 0x87, 0xed, 0x68, 0x1a, 0x08, 0x94, 0x0c, 0x0c, 0xf1, 0x7c, 0xbe, 0x5f, 0x2f, 0x8f, 0x00, 0x00, 0x0d, 0x1f, 0x68, 0x7a, 0x1a, 0x04, 0x05, 0xce, 0xe6, 0x2a, 0x0c, 0x01, 0xc2, 0x00, 0x40, 0x42, 0x61, 0xc0, 0x49, 0x41, 0x60, 0xa0, 0x80, 0x01, 0xc0, 0x03, 0xe0, 0x07, 0xf0, 0x07, 0xfa, 0x00, 0x07, 0x3b, 0x99, 0x01, 0x0f, 0x19, 0x18, 0x54, 0x40, 0xe0, 0x60, 0xee, 0xd0, 0x0e, 0x19, 0x0a, 0x03, 0xa5, 0x7d, 0x05, 0xd0, 0x83, 0x98, 0x5a, 0x96, 0x21, 0x4b, 0x10, 0x10, 0xe6, 0x17, 0xaf, 0xeb, 0xaf, 0x34, 0x3c, 0xc8, 0x0f, 0xf0, 0x64, 0x3f, 0xd0, 0x0f, 0xe0, 0x03, 0xfe, 0x10, 0x02, 0x7d, 0x47, 0x2d, 0x58, 0xfc, 0x35, 0xe0, 0xca, 0x0f, 0x19, 0x0a, 0xf9, 0xf1, 0xe0, 0xb9, 0xc0, 0x81, 0x10, 0x03, 0xe0, 0xbd, 0x4f, 0xea, 0x61, 0xf7, 0xeb, 0xf6, 0x02, 0xd4, 0x7a, 0xf9, 0xff, 0x15, 0x30, 0xfa, 0x88, 0x68, 0x68, 0xd8, 0x80, 0x12, 0x60, 0x50, 0x50, 0xf0, 0x03, 0xfc, 0x01, 0xfe, 0x01, 0x7f, 0xa0, 0x7c, 0x28, 0xbf, 0xd0, 0x3e, 0x64, 0x0f, 0x00, 0x37, 0x00, 0x08, 0x80, 0x20, 0x0b, 0x88, 0x81, 0xa5, 0x04, 0x84, 0x60, 0x40, 0x36, 0x04, 0x1b, 0x8f, 0x88, 0x01, 0x00, 0xa1, 0x80, 0x1e, 0x00, 0x36, 0xfd, 0xb9, 0x12, 0x02, 0x4c, 0x09, 0x08, 0x1e, 0x00, 0x61, 0x80, 0x20, 0x60, 0x44, 0x17, 0xdc, 0x7c, 0x62, 0x00, 0x03, 0x67, 0xdb, 0x81, 0xb1, 0x30, 0x34, 0xb0, 0xa0, 0xaf, 0xa0, 0x80, 0x75, 0x35, 0x20, 0x7c, 0x49, 0xfc, 0x0f, 0xf5, 0x0d, 0x7f, 0x7e, 0x45, 0x00, 0x53, 0x42, 0x82, 0x83, 0xc0, 0x0c, 0x28, 0x1f, 0x72, 0x3e, 0xd3, 0xf5, 0x62, 0xd4, 0x00, 0x22, 0xa8, 0x81, 0xec, 0x67, 0x96, 0x02, 0xa0, 0x49, 0x7d, 0xfd, 0x6b, 0xbf, 0xcc, 0x7c, 0x4a, 0xf8, 0xd0, 0x00, 0x00, 0xcf, 0xd5, 0xd2, 0x23, 0x35, 0x60, 0x01, 0xf1, 0x60, 0x14, 0xc0, 0xb0, 0xbe, 0xb3, 0x02, 0x0f, 0x89, 0x5f, 0x1b, 0x00, 0x02, 0x0b, 0xfd, 0x80, 0x00, 0x01, 0x9b, 0xf3, 0x40, 0x42, 0x10, 0x00, 0xd8, 0xb8, 0x0f, 0xa8, 0x17, 0xfe, 0x59, 0xef, 0x14, 0x61, 0xf2, 0x30, 0x65, 0xfc, 0x51, 0xe2, 0xc1, 0x18, 0xc0, 0x07, 0x5e, 0x68, 0x08, 0xe8, 0x46, 0xf8, 0x95, 0xf1, 0xb0, 0xf9, 0x13, 0x7f, 0xbc, 0x00, 0x00, 0x32, 0x7e, 0xa8, 0xeb, 0xcd, 0x03, 0x20, 0x09, 0xa1, 0x81, 0x97, 0xfb, 0x87, 0x80, 0xb0, 0xf9, 0x19, 0x7c, 0xa8, 0x63, 0xf3, 0xe6, 0x20, 0x22, 0xbd, 0x85, 0x9e, 0x62, 0x00, 0x8b, 0x7c, 0x87, 0x91, 0x00, 0x22, 0xff, 0x21, 0xe2, 0xa0, 0x08, 0xc7, 0xc8, 0x78, 0x20, 0x02, 0x33, 0xf2, 0x1c, 0x10, 0x41, 0xe3, 0x40, 0x69, 0x7c, 0x45, 0x72, 0x62, 0xf0, 0x04, 0x7f, 0x60, 0x68, 0x6f, 0x80, 0x00, 0x08, 0x1f, 0xf7, 0xad, 0x51, 0x03, 0xf3, 0xf8, 0xa0, 0x9d, 0xa8, 0x40, 0x00, 0x23, 0x42, 0x37, 0x46, 0x0f, 0xde, 0xa6, 0x06, 0xd3, 0x3c, 0x33, 0xe1, 0x78, 0xd8, 0x34, 0x32, 0x14, 0x67, 0xdb, 0xd2, 0x38, 0xaf, 0xc7, 0x9c, 0xdf, 0xd0, 0x21, 0xe6, 0xd7, 0x80, 0x40, 0x22, 0x3f, 0x21, 0xe8, 0xd8, 0x12, 0xf9, 0x0f, 0xb4, 0x01, 0x13, 0xf9, 0x0f, 0x46, 0xc0, 0xa7, 0x13, 0x37, 0x1e, 0x67, 0x07, 0x8b, 0x01, 0xfd, 0xfe, 0x0f, 0xf7, 0x7a, 0xf0, 0x16, 0x36, 0x0a, 0x92, 0x08, 0x08, 0xc1, 0x70, 0xb8, 0x30, 0x34, 0xf1, 0xf3, 0x72, 0x27, 0x8f, 0x4b, 0x60, 0x21, 0xc4, 0xdd, 0xe2, 0xdf, 0x0b, 0xca, 0x4f, 0x2e, 0x4f, 0x9c, 0xde, 0x59, 0xe9, 0xf1, 0x55, 0x00, 0x8d, 0xf2, 0x20, 0x53, 0x3c, 0xc4, 0xf6, 0x46, 0x7e, 0x24, 0xee, 0xf2, 0x0c, 0x0d, 0x81, 0x83, 0xf9, 0x98, 0x0e, 0x00, 0x02, 0x10, 0x11, 0x01, 0x08, 0x95, 0x2a, 0xfc, 0x28, 0x95, 0x2a, 0x84, 0x80, 0xbf, 0x81, 0x06, 0x80, 0x0d, 0x00, 0x86, 0xe0, 0x6b, 0xa5, 0xc3, 0xd8, 0x8f, 0x22, 0xa0, 0x3e, 0xe9, 0x8f, 0x90, 0xf2, 0x6b, 0x85, 0x77, 0x57, 0x99, 0x43, 0x5c, 0x66, 0x5f, 0x9e, 0x85, 0x7c, 0x3f, 0x1f, 0xb3, 0xce, 0xc0, 0x0e, 0x64, 0x20, 0x0e, 0x20, 0xdc, 0x7e, 0x18, 0x81, 0x90, 0xa3, 0x13, 0x4e, 0x52, 0x71, 0x81, 0x03, 0xa4, 0x30, 0x30, 0x6c, 0x73, 0x8f, 0xc4, 0x50, 0x60, 0x16, 0x38, 0x03, 0xbf, 0x6f, 0x89, 0x3e, 0x00, 0x77, 0x00, 0xb1, 0xc0, 0x28, 0x3d, 0x73, 0x98, 0x06, 0xfe, 0x00, 0xe9, 0x81, 0xa3, 0xb8, 0x1c, 0x85, 0x20, 0x45, 0x45, 0xe1, 0xa1, 0x23, 0x63, 0xa0, 0x29, 0x61, 0x41, 0x27, 0xf4, 0x03, 0xfa, 0x01, 0x02, 0x05, 0xff, 0xe1, 0x20, 0x34, 0x08, 0x08, 0x04, 0x04, 0x02, 0xff, 0xeb, 0x96, 0x05, 0x24, 0x8e, 0x0a, 0xb1, 0xce, 0xf2, 0x06, 0xc7, 0xb9, 0x01, 0xd7, 0x20, 0x52, 0x04, 0x03, 0xe1, 0x47, 0xc4, 0xa4, 0x0b, 0xfd, 0x03, 0x01, 0xc0, 0x47, 0xe6, 0xc0, 0x2c, 0x7c, 0x09, 0x10, 0x1c, 0x0a, 0xfd, 0x7e, 0xc0, 0xd2, 0x94, 0x7a, 0x1a, 0x06, 0x07, 0xcf, 0x12, 0x2a, 0x8c, 0x1e, 0xe7, 0x07, 0x08, 0x81, 0x81, 0x91, 0x90, 0x72, 0x26, 0x9e, 0x55, 0x44, 0x0e, 0x4d, 0x21, 0x00, 0x08, 0x40, 0x02, 0x20, 0x01, 0x17, 0x2c, 0xd4, 0x22, 0x00, 0x88, 0x80, 0x44, 0x40, 0x23, 0xcd, 0xf8, 0xf1, 0xc8, 0x9b, 0x02, 0x10, 0x0c, 0x02, 0x99, 0x30, 0x00, 0x0a, 0x06, 0x01, 0x4b, 0x18, 0x00, 0x46, 0x00, 0x29, 0x9c, 0xa3, 0x86, 0x60, 0x11, 0x98, 0x05, 0x32, 0x80, 0xcc, 0xc0, 0xf3, 0xc3, 0xb8, 0x7a, 0x21, 0x7d, 0xbe, 0xfa, 0xce, 0x2a, 0x9d, 0xfa, 0xa0, 0x3c, 0x32, 0xfb, 0x7d, 0x13, 0x22, 0x05, 0xeb, 0x0b, 0xbb, 0xb8, 0x00, 0x15, 0xfe, 0xfe, 0x1a, 0x14, 0x7e, 0x1c, 0x00, 0x01, 0x82, 0x3a, 0xa7, 0xd2, 0x6c, 0x11, 0xdd, 0x00, 0x00, 0x00, 0xc0, 0x40, 0x18, 0x23, 0x5a, 0x00, 0x80, 0xb0, 0x47, 0x84, 0x7c, 0xa8, 0x03, 0xa7, 0x82, 0x48, 0x83, 0x01, 0x50, 0x11, 0x2a, 0x37, 0xfb, 0xfc, 0x03, 0x03, 0xd1, 0xa3, 0x35, 0x68, 0xcd, 0x58, 0x40, 0x03, 0xe3, 0x47, 0xc4, 0xaf, 0x8d, 0x1f, 0x42, 0x84, 0x20, 0x81, 0x08, 0x57, 0xfb, 0xff, 0xd0, 0x98, 0x27, 0xc8, 0xaf, 0x99, 0x1f, 0x12, 0x04, 0x3e, 0x84, 0xfe, 0x08, 0x1c, 0xc1, 0x31, 0x58, 0x80, 0x3a, 0xd1, 0x99, 0x8a, 0x40, 0x02, 0x5a, 0x04, 0x00, 0x02, 0x1a, 0x38, 0xf3, 0x08, 0x00, 0x01, 0xda, 0xe3, 0x35, 0x60, 0x5f, 0x88, 0x00, 0x03, 0x6e, 0xbf, 0xdf, 0xc0, 0xbe, 0x20, 0x00, 0x42, 0x80, 0x01, 0x77, 0x9e, 0x80, 0xd0, 0x30, 0x4a, 0x32, 0x81, 0xe3, 0x94, 0x04, 0x21, 0x0a, 0x9c, 0xcc, 0x52, 0x03, 0x7d, 0xa7, 0x0c, 0x51, 0x80, 0x6f, 0xa5, 0xc0, 0x3f, 0x3e, 0x80, 0xa0, 0x22, 0x10, 0x40, 0x68, 0x17, 0x9f, 0x60, 0x1e, 0x9b, 0x09, 0x52, 0x03, 0x2d, 0x03, 0x81, 0x88, 0x41, 0x3c, 0x65, 0x14, 0x98, 0xcd, 0x58, 0x6a, 0x04, 0x21, 0x80, 0x9b, 0x81, 0x45, 0x21, 0x24, 0xe1, 0x8c, 0xf1, 0x9a, 0xb0, 0xa9, 0x38, 0xef, 0xe7, 0x90, 0xdf, 0x98, 0x00, 0x19, 0xa8, 0x18, 0x42, 0x6a, 0xc0, 0x7f, 0xda, 0x00, 0x00, 0x2b, 0x1e, 0x36, 0x7c, 0xaa, 0xa0, 0x00, 0xc0, 0xf8, 0xa0, 0xbe, 0x60, 0x2e, 0xb1, 0x09, 0xab, 0x60, 0x3e, 0x38, 0xf9, 0x6f, 0xa9, 0x3e, 0x08, 0x81, 0xa6, 0x8c, 0x13, 0xae, 0x83, 0x7e, 0x0a, 0xfb, 0x0f, 0x60, 0x86, 0x3e, 0x90, 0x6d, 0xa2, 0x33, 0x56, 0x06, 0xfa, 0xcf, 0xc5, 0x1f, 0x12, 0x38, 0x49, 0x3d, 0x04, 0x03, 0xa6, 0x42, 0x54, 0x82, 0x3e, 0xd3, 0xd1, 0xd0, 0x08, 0x58, 0x06, 0xdc, 0x10, 0x85, 0xe8, 0xf8, 0xf8, 0x94, 0x10, 0x84, 0x21, 0xe7, 0xa3, 0x85, 0xfe, 0xfe, 0xc1, 0xe9, 0x77, 0xa3, 0x27, 0xe7, 0xbd, 0x31, 0x98, 0x17, 0xa1, 0xe2, 0x13, 0xe8, 0x5a, 0xf1, 0x44, 0x7c, 0x4a, 0x00, 0x00, 0x07, 0x2d, 0x03, 0x2d, 0x05, 0xa3, 0x46, 0x6a, 0xc1, 0x9e, 0x9f, 0x9f, 0x51, 0xc0, 0x55, 0x1a, 0x13, 0x56, 0x0e, 0xf4, 0xa4, 0x85, 0xfd, 0x4c, 0x47, 0x10, 0x0d, 0x70, 0x24, 0x9b, 0xfa, 0x45, 0x41, 0x3a, 0x33, 0xea, 0x28, 0x60, 0x00, 0x80, 0x00, 0xbc, 0x00, 0x80, 0x7b, 0x2e, 0x43, 0x10, 0x0b, 0x00, 0xec, 0x1e, 0x98, 0x8a, 0xb4, 0x26, 0xac, 0x5f, 0xf9, 0x20, 0x03, 0xf2, 0xc1, 0xdf, 0xca, 0x14, 0x40, 0x07, 0x40, 0x1e, 0x00, 0x3d, 0x10, 0xe1, 0x37, 0x90, 0x64, 0x17, 0xec, 0x3d, 0x4c, 0xf5, 0x94, 0x20, 0x15, 0x80, 0xdc, 0x3e, 0x74, 0x7f, 0x87, 0x87, 0xa9, 0xa6, 0x33, 0x56, 0x16, 0xfd, 0xcf, 0xa9, 0x1f, 0x12, 0x23, 0x35, 0x60, 0xaf, 0xa4, 0x04, 0xf5, 0xb0, 0x1f, 0xe4, 0x3d, 0x75, 0x1c, 0x20, 0xeb, 0xd7, 0x19, 0x00, 0xb8, 0x04, 0x21, 0x7a, 0xd3, 0xbe, 0x15, 0xeb, 0x4a, 0xf1, 0x84, 0x78, 0x52, 0x3e, 0x25, 0x03, 0x16, 0x81, 0xc3, 0x7d, 0x59, 0x1f, 0x12, 0x30, 0x50, 0xe3, 0xe1, 0xcf, 0xc5, 0x8f, 0xa1, 0x1c, 0x0e, 0x9e, 0xd0, 0x0d, 0x7b, 0x18, 0x14, 0xcc, 0x21, 0x04, 0x1b, 0x6a, 0x8c, 0xd5, 0x86, 0xe0, 0x31, 0x9a, 0xb0, 0x4f, 0xc8, 0x0b, 0x7c, 0x40, 0x37, 0xc4, 0x5c, 0x22, 0x80, 0x3e, 0x54, 0x71, 0x10, 0xbf, 0x26, 0xf9, 0xa2, 0x1c, 0x0b, 0x82, 0xf0, 0x8f, 0x22, 0x47, 0x8a, 0xab, 0xca, 0xd4, 0x31, 0x08, 0xf1, 0xe6, 0x51, 0x9a, 0xb7, 0xcc, 0x80, 0x7f, 0xc9, 0xc2, 0x13, 0x08, 0xfd, 0x95, 0xfe, 0x23, 0xc0, 0x14, 0x0f, 0x08, 0xe1, 0xb5, 0x5f, 0x4a, 0x38, 0x10, 0x47, 0x1b, 0x17, 0x0a, 0x07, 0x1d, 0x38, 0xe3, 0xcb, 0x42, 0x10, 0x4f, 0x5d, 0x40, 0x3f, 0xf8, 0xe1, 0x0a, 0xe0, 0x45, 0xa8, 0x47, 0xe0, 0x78, 0x23, 0x0f, 0x91, 0x5f, 0x4a, 0x7f, 0xe3, 0xc9, 0x11, 0xe0, 0x4a, 0x09, 0xfe, 0x5a, 0xf0, 0xea, 0x8f, 0x21, 0x57, 0x82, 0xa3, 0xfa, 0x47, 0xc4, 0x8e, 0x0d, 0x8f, 0xcc, 0xfe, 0x11, 0xf1, 0x22, 0x33, 0x56, 0xe1, 0xf9, 0x1f, 0x9a, 0x83, 0x79, 0x2d, 0xe3, 0xf5, 0x23, 0xf6, 0x50, 0x64, 0x17, 0xce, 0x4f, 0x12, 0x58, 0x5f, 0xe0, 0xc4, 0x32, 0x0d, 0xfc, 0xab, 0xd5, 0x54, 0x15, 0x04, 0xfd, 0x91, 0xf1, 0x20, 0x32, 0x0d, 0xe1, 0x48, 0xf8, 0x91, 0xe5, 0x48, 0x09, 0xfc, 0xdb, 0x7b, 0xab, 0x84, 0x22, 0x0d, 0xfd, 0x23, 0xda, 0xd1, 0xf2, 0x20, 0x2a, 0x11, 0xfe, 0x23, 0xe7, 0x4f, 0x8c, 0x2f, 0x80, 0xe7, 0x1f, 0x09, 0x40, 0x2f, 0x00, 0xee, 0x7f, 0xf5, 0x1f, 0x12, 0x3c, 0x0d, 0x40, 0xff, 0xa9, 0xc3, 0x1b, 0x01, 0x42, 0xce, 0x18, 0x5b, 0x52, 0xd9, 0x8a, 0x79, 0xa7, 0xbc, 0xc5, 0x01, 0x08, 0x41, 0x21, 0xb5, 0xfc, 0x1b, 0x93, 0x1e, 0x8f, 0x60, 0x02, 0x98, 0xf8, 0xe0, 0x0c, 0x1c, 0x2e, 0x15, 0x00, 0xe7, 0x61, 0x08, 0x02, 0xfd, 0x16, 0x5c, 0xdb, 0xf2, 0xb8, 0x4f, 0x03, 0xfd, 0x81, 0x8a, 0x88, 0x52, 0x05, 0x20, 0x0e, 0xe9, 0xf9, 0xaa, 0xed, 0x7f, 0xbf, 0xd0, 0x0b, 0x0b, 0x42, 0x60, 0x85, 0xa1, 0x3f, 0x0a, 0x0b, 0x42, 0x40, 0x08, 0xa8, 0x02, 0x04, 0xa9, 0x60, 0x46, 0x00, 0x45, 0x40, 0x5c, 0xa7, 0xa6, 0xfa, 0x5c, 0x07, 0xf0, 0xe0, 0xa4, 0x0f, 0x94, 0xc4, 0x16, 0x82, 0x96, 0x82, 0x94, 0x83, 0x71, 0x76, 0x04, 0x94, 0x8f, 0xa1, 0xf3, 0x40, 0x00, 0x93, 0x85, 0xa2, 0x50, 0xc0, 0x00, 0x28, 0x1c, 0xbb, 0x03, 0x09, 0x12, 0x5e, 0x91, 0xaf, 0x21, 0x42, 0x05, 0x09, 0x6b, 0xe5, 0x59, 0x27, 0xcf, 0x8f, 0x88, 0x24, 0x00, 0x90, 0x7c, 0x60, 0x00, 0x00, 0x17, 0x1a, 0x02, 0x40, 0x2c, 0x03, 0x94, 0x1a, 0xf8, 0x02, 0xa0, 0x80, 0xd2, 0x15, 0xf5, 0x64, 0x00, 0xc0, 0x32, 0x01, 0x83, 0xa4, 0xc0, 0x5e, 0xb2, 0x0e, 0x70, 0x9a, 0x7b, 0x12, 0x23, 0x35, 0x6f, 0x26, 0x43, 0x7f, 0x40, 0x6a, 0x04, 0xe8, 0x14, 0x04, 0xa4, 0xb3, 0x14, 0x81, 0x30, 0x2f, 0x16, 0x84, 0xd0, 0x0c, 0x0b, 0x42, 0x6e, 0x14, 0x00, 0x9a, 0x00, 0x87, 0x76, 0x80, 0x07, 0x98, 0x2c, 0x03, 0x99, 0x9c, 0xf3, 0xbb, 0x7f, 0xb8, 0xa4, 0xdb, 0xde, 0xfc, 0x4a, 0x00, 0x05, 0xa4, 0xc2, 0x6a, 0xc0, 0xed, 0x3d, 0x15, 0xc1, 0x04, 0xe1, 0x30, 0x2e, 0x2c, 0xf1, 0x50, 0x69, 0x84, 0xa9, 0x0f, 0xf8, 0xc2, 0xbe, 0x35, 0xa8, 0x87, 0x50, 0x10, 0x0e, 0x00, 0xe5, 0x1e, 0xc6, 0xa9, 0x55, 0xfe, 0xff, 0x48, 0xf5, 0xe0, 0x53, 0xdc, 0x78, 0x80, 0x10, 0x51, 0x89, 0x52, 0xc0, 0x06, 0xab, 0x03, 0x14, 0x6f, 0xed, 0x85, 0xde, 0x80, 0x03, 0x09, 0x52, 0xe5, 0xff, 0x5e, 0x02, 0xbf, 0x8f, 0x8f, 0xc9, 0xcf, 0xe5, 0xeb, 0xf3, 0x72, 0xbb, 0x80, 0x00, 0xc6, 0x6a, 0xd8, 0x08, 0x95, 0xf4, 0xb2, 0xf9, 0x4f, 0xa1, 0xc1, 0xc2, 0x5a, 0xef, 0xf7, 0xfa, 0x81, 0xdd, 0xbd, 0xef, 0xee, 0xe0, 0xd1, 0xe5, 0x72, 0xc5, 0xcd, 0xf0, 0x2c, 0x00, 0x03, 0xcb, 0x98, 0xf0, 0x7f, 0x52, 0x00 }; uint8_t decompressed_rd5[] = { 0x24, 0x02, 0x03, 0x09, 0x00, 0x20, 0x0c, 0x05, 0x10, 0x01, 0x40, 0x0a, 0xff, 0xff, 0x0c, 0x84, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x1d, 0x0d, 0x38, 0x01, 0xc0, 0x10, 0x01, 0x10, 0x01, 0xcc, 0xff, 0x7f, 0x03, 0x08, 0x00, 0x20, 0x04, 0x05, 0x10, 0x01, 0x40, 0x0a, 0x00, 0x0c, 0x84, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x35, 0x00, 0x01, 0x00, 0x00, 0x0d, 0x0a, 0x0c, 0x0c, 0xff, 0x03, 0xff, 0x02, 0x00, 0x04, 0x00, 0x03, 0x06, 0x00, 0x00, 0x80, 0x00, 0x80, 0x00, 0x02, 0x00, 0x00, 0x09, 0x00, 0x0c, 0x80, 0x00, 0x80, 0x00, 0x06, 0x00, 0x00, 0x48, 0x00, 0x37, 0x01, 0x02, 0x00, 0x00, 0x01, 0x0c, 0x48, 0x00, 0x37, 0x01, 0x06, 0x01, 0x00, 0x00, 0x04, 0x24, 0x00, 0x02, 0x01, 0x00, 0x01, 0x0c, 0x00, 0x04, 0x24, 0x00, 0x02, 0x00, 0x00, 0x09, 0x0a, 0x3d, 0x0f, 0x00, 0x01, 0x00, 0x0e, 0x00, 0x08, 0x42, 0x11, 0x0f, 0xf1, 0x0d, 0x0e, 0xf3, 0x11, 0x3e, 0xf3, 0xf2, 0x0c, 0xff, 0xff, 0x11, 0x0d, 0x01, 0x0d, 0xf4, 0x11, 0x3f, 0x0d, 0x01, 0xf3, 0x0b, 0x10, 0x84, 0x11, 0x0f, 0xf3, 0x0b, 0x0c, 0xf5, 0x11, 0x3e, 0xf5, 0xf4, 0x0a, 0x99, 0xd6, 0x11, 0x0d, 0x01, 0x0b, 0xf6, 0x11, 0x0a, 0x01, 0x09, 0x09, 0x18, 0xfb, 0x70, 0x06, 0x00, 0x03, 0xff, 0xff, 0x00, 0x03, 0x00, 0x02, 0x00, 0x0d, 0x00, 0x0c, 0x00, 0x00, 0x80, 0x0c, 0x00, 0x0f, 0x00, 0x01, 0x49, 0x08, 0x07, 0xc3, 0x66, 0x3c, 0x18, 0x3c, 0x66, 0xc3, 0x00, 0x72, 0x00, 0x19, 0x0a, 0x3f, 0x1d, 0xfe, 0xf5, 0x04, 0xff, 0xff, 0x11, 0x0f, 0xf1, 0x0d, 0x0e, 0xf3, 0x11, 0x3e, 0xf3, 0xf2, 0x0c, 0x08, 0x42, 0x11, 0x0d, 0x01, 0x0d, 0xf4, 0x11, 0x3f, 0x0d, 0x01, 0xf3, 0x0b, 0x99, 0xd6, 0x11, 0x0f, 0xf3, 0x0b, 0x0c, 0xf5, 0x11, 0x3e, 0xf5, 0xf4, 0x0a, 0x10, 0x84, 0x11, 0x0d, 0x01, 0x0b, 0xf6, 0x11, 0x3a, 0x01, 0x09, 0x99, 0xd6, 0x19, 0x18, 0xf0, 0x60, 0x11, 0x01, 0x11, 0x01, 0x01, 0x01, 0x00, 0x19, 0x0a, 0x3f, 0x1d, 0xfe, 0xf5, 0x04, 0x08, 0x42, 0x11, 0x0f, 0xf1, 0x0d, 0x0e, 0xf3, 0x11, 0x3e, 0xf3, 0xf2, 0x0c, 0xff, 0xff, 0x11, 0x0d, 0x01, 0x0d, 0xf4, 0x11, 0x3f, 0x0d, 0x01, 0xf3, 0x0b, 0x10, 0x84, 0x11, 0x0f, 0xf3, 0x0b, 0x0c, 0xf5, 0x11, 0x3e, 0xf5, 0xf4, 0x0a, 0x99, 0xd6, 0x11, 0x0d, 0x01, 0x0b, 0xf6, 0x11, 0x0a, 0x01, 0x09, 0x19, 0x18, 0xf4, 0x20, 0x10, 0x00, 0x00, 0x0f, 0xff, 0x0f, 0xff, 0xff, 0x19, 0x0a, 0x3f, 0x1d, 0xfe, 0xf5, 0x04, 0x08, 0x42, 0x11, 0x0f, 0xf1, 0x0d, 0x0e, 0xf3, 0x11, 0x3e, 0xf3, 0xf2, 0x0c, 0xff, 0xff, 0x11, 0x0d, 0x01, 0x0d, 0xf4, 0x11, 0x3f, 0x0d, 0x01, 0xf3, 0x0b, 0x10, 0x84, 0x11, 0x0f, 0xf3, 0x0b, 0x0c, 0xf5, 0x11, 0x3e, 0xf5, 0xf4, 0x0a, 0x99, 0xd6, 0x11, 0x0d, 0x01, 0x0b, 0xf6, 0x11, 0x0a, 0x01, 0x09, 0x19, 0x18, 0xf4, 0x20, 0xff, 0xff, 0x00, 0x11, 0x01, 0x11, 0x01, 0x01, 0x11, 0xf4, 0x20, 0x10, 0x84, 0x00, 0xff, 0xff, 0xff, 0xff, 0xff, 0x19, 0x0a, 0x3f, 0xdd, 0x0c, 0xf5, 0x04, 0x08, 0x42, 0x11, 0x0f, 0xf1, 0x0d, 0x0e, 0xf3, 0x11, 0x3e, 0xf3, 0xf2, 0x0c, 0xff, 0xff, 0x11, 0x0d, 0x01, 0x0d, 0xf4, 0x11, 0x3f, 0x0d, 0x01, 0xf3, 0x0b, 0x10, 0x84, 0x11, 0x0f, 0xf3, 0x0b, 0x0c, 0xf5, 0x11, 0x3e, 0xf5, 0xf4, 0x0a, 0x99, 0xd6, 0x11, 0x0d, 0x01, 0x0b, 0xf6, 0x11, 0x0a, 0x01, 0x09, 0x19, 0x18, 0xf4, 0x60, 0x00, 0x00, 0x00, 0xd0, 0x0e, 0xd0, 0x0e, 0x0e, 0x0b, 0x01, 0x01, 0x43, 0x06, 0x02, 0xfc, 0xfc, 0x00, 0x00, 0x30, 0x00, 0x19, 0x0a, 0x3f, 0x1d, 0xfe, 0xf5, 0x04, 0xff, 0xff, 0x11, 0x0f, 0xf1, 0x0d, 0x0e, 0xf3, 0x11, 0x3e, 0xf3, 0xf2, 0x0c, 0x08, 0x42, 0x11, 0x0d, 0x01, 0x0d, 0xf4, 0x11, 0x3f, 0x0d, 0x01, 0xf3, 0x0b, 0x99, 0xd6, 0x11, 0x0f, 0xf3, 0x0b, 0x0c, 0xf5, 0x11, 0x3e, 0xf5, 0xf4, 0x0a, 0x10, 0x84, 0x11, 0x0d, 0x01, 0x0b, 0xf6, 0x11, 0x3a, 0x01, 0x09, 0x99, 0xd6, 0x19, 0x18, 0xf0, 0x60, 0x11, 0x01, 0x11, 0x01, 0x01, 0x01, 0x01, 0x19, 0x0a, 0x3f, 0x1d, 0xfe, 0xf5, 0x04, 0x08, 0x42, 0x11, 0x0f, 0xf1, 0x0d, 0x0e, 0xf3, 0x11, 0x3e, 0xf3, 0xf2, 0x0c, 0xff, 0xff, 0x11, 0x0d, 0x01, 0x0d, 0xf4, 0x11, 0x3f, 0x0d, 0x01, 0xf3, 0x0b, 0x10, 0x84, 0x11, 0x0f, 0xf3, 0x0b, 0x0c, 0xf5, 0x11, 0x3e, 0xf5, 0xf4, 0x0a, 0x99, 0xd6, 0x11, 0x0d, 0x01, 0x0b, 0xf6, 0x11, 0x0a, 0x01, 0x09, 0x19, 0x18, 0xf4, 0x20, 0x10, 0x00, 0x00, 0x0f, 0xff, 0x0f, 0xff, 0xff, 0x19, 0x0a, 0x3f, 0x1d, 0xfe, 0xf5, 0x04, 0x08, 0x42, 0x11, 0x0f, 0xf1, 0x0d, 0x0e, 0xf3, 0x11, 0x3e, 0xf3, 0xf2, 0x0c, 0xff, 0xff, 0x11, 0x0d, 0x01, 0x0d, 0xf4, 0x11, 0x3f, 0x0d, 0x01, 0xf3, 0x0b, 0x10, 0x84, 0x11, 0x0f, 0xf3, 0x0b, 0x0c, 0xf5, 0x11, 0x3e, 0xf5, 0xf4, 0x0a, 0x99, 0xd6, 0x11, 0x0d, 0x01, 0x0b, 0xf6, 0x11, 0x0a, 0x01, 0x09, 0x19, 0x18, 0xf4, 0x20, 0xff, 0xff, 0x00, 0x11, 0x01, 0x11, 0x01, 0x01, 0x11, 0xf4, 0x20, 0x10, 0x84, 0x00, 0xff, 0xff, 0xff, 0xff, 0xff, 0x19, 0x0a, 0x3f, 0xdd, 0x0c, 0xf5, 0x04, 0x08, 0x42, 0x11, 0x0f, 0xf1, 0x0d, 0x0e, 0xf3, 0x11, 0x3e, 0xf3, 0xf2, 0x0c, 0xff, 0xff, 0x11, 0x0d, 0x01, 0x0d, 0xf4, 0x11, 0x3f, 0x0d, 0x01, 0xf3, 0x0b, 0x10, 0x84, 0x11, 0x0f, 0xf3, 0x0b, 0x0c, 0xf5, 0x11, 0x3e, 0xf5, 0xf4, 0x0a, 0x99, 0xd6, 0x11, 0x0d, 0x01, 0x0b, 0xf6, 0x11, 0x0a, 0x01, 0x09, 0x19, 0x18, 0xf4, 0x60, 0x00, 0x00, 0x00, 0xd0, 0x0e, 0xd0, 0x0e, 0x0e, 0x13, 0x02, 0x00, 0x4a, 0x08, 0x09, 0x3f, 0x3f, 0x21, 0xfd, 0xfd, 0x87, 0x84, 0x84, 0xfc, 0x00, 0x00, 0x00, 0x32, 0x00, 0x19, 0x0a, 0x3f, 0x1d, 0xfe, 0xf5, 0x04, 0xff, 0xff, 0x11, 0x0f, 0xf1, 0x0d, 0x0e, 0xf3, 0x11, 0x3e, 0xf3, 0xf2, 0x0c, 0x08, 0x42, 0x11, 0x0d, 0x01, 0x0d, 0xf4, 0x11, 0x3f, 0x0d, 0x01, 0xf3, 0x0b, 0x99, 0xd6, 0x11, 0x0f, 0xf3, 0x0b, 0x0c, 0xf5, 0x11, 0x3e, 0xf5, 0xf4, 0x0a, 0x10, 0x84, 0x11, 0x0d, 0x01, 0x0b, 0xf6, 0x11, 0x3a, 0x01, 0x09, 0x99, 0xd6, 0x19, 0x18, 0xf0, 0x60, 0x11, 0x01, 0x11, 0x01, 0x01, 0x01, 0x02, 0x19, 0x0a, 0x3f, 0x1d, 0xfe, 0xf5, 0x04, 0x08, 0x42, 0x11, 0x0f, 0xf1, 0x0d, 0x0e, 0xf3, 0x11, 0x3e, 0xf3, 0xf2, 0x0c, 0xff, 0xff, 0x11, 0x0d, 0x01, 0x0d, 0xf4, 0x11, 0x3f, 0x0d, 0x01, 0xf3, 0x0b, 0x10, 0x84, 0x11, 0x0f, 0xf3, 0x0b, 0x0c, 0xf5, 0x11, 0x3e, 0xf5, 0xf4, 0x0a, 0x99, 0xd6, 0x11, 0x0d, 0x01, 0x0b, 0xf6, 0x11, 0x0a, 0x01, 0x09, 0x19, 0x18, 0xf4, 0x20, 0x10, 0x00, 0x00, 0x0f, 0xff, 0x0f, 0xff, 0xff, 0x19, 0x0a, 0x3f, 0x1d, 0xfe, 0xf5, 0x04, 0x08, 0x42, 0x11, 0x0f, 0xf1, 0x0d, 0x0e, 0xf3, 0x11, 0x3e, 0xf3, 0xf2, 0x0c, 0xff, 0xff, 0x11, 0x0d, 0x01, 0x0d, 0xf4, 0x11, 0x3f, 0x0d, 0x01, 0xf3, 0x0b, 0x10, 0x84, 0x11, 0x0f, 0xf3, 0x0b, 0x0c, 0xf5, 0x11, 0x3e, 0xf5, 0xf4, 0x0a, 0x99, 0xd6, 0x11, 0x0d, 0x01, 0x0b, 0xf6, 0x11, 0x0a, 0x01, 0x09, 0x19, 0x18, 0x54, 0x40, 0x00, 0x00, 0x00, 0x10, 0x10, 0x13, 0x03, 0x02, 0x4a, 0x06, 0x09, 0x78, 0xcc, 0xcc, 0x18, 0x30, 0x30, 0x00, 0x30, 0x30, 0x00, 0x00, 0x00, 0x73, 0x00, 0x19, 0x0a, 0x3f, 0xdd, 0x0c, 0xf5, 0x04, 0xff, 0xff, 0x11, 0x0f, 0xf1, 0x0d, 0x0e, 0xf3, 0x11, 0x3e, 0xf3, 0xf2, 0x0c, 0x08, 0x42, 0x11, 0x0d, 0x01, 0x0d, 0xf4, 0x11, 0x3f, 0x0d, 0x01, 0xf3, 0x0b, 0x99, 0xd6, 0x11, 0x0f, 0xf3, 0x0b, 0x0c, 0xf5, 0x11, 0x3e, 0xf5, 0xf4, 0x0a, 0x10, 0x84, 0x11, 0x0d, 0x01, 0x0b, 0xf6, 0x11, 0x3a, 0x01, 0x09, 0x99, 0xd6, 0x19, 0x18, 0xf0, 0x60, 0xd1, 0x0f, 0xd1, 0x0f, 0x0f, 0x01, 0x03, 0x19, 0x0a, 0x3f, 0x1d, 0xfe, 0xf5, 0x04, 0x08, 0x42, 0x11, 0x0f, 0xf1, 0x0d, 0x0e, 0xf3, 0x11, 0x3e, 0xf3, 0xf2, 0x0c, 0xff, 0xff, 0x11, 0x0d, 0x01, 0x0d, 0xf4, 0x11, 0x3f, 0x0d, 0x01, 0xf3, 0x0b, 0x10, 0x84, 0x11, 0x0f, 0xf3, 0x0b, 0x0c, 0xf5, 0x11, 0x3e, 0xf5, 0xf4, 0x0a, 0x99, 0xd6, 0x11, 0x0d, 0x01, 0x0b, 0xf6, 0x11, 0x0a, 0x01, 0x09, 0x19, 0x18, 0xf4, 0x20, 0x10, 0x00, 0x00, 0x0f, 0xff, 0x0f, 0xff, 0xff, 0x19, 0x0a, 0x3f, 0x1d, 0xfe, 0xf5, 0x04, 0x08, 0x42, 0x11, 0x0f, 0xf1, 0x0d, 0x0e, 0xf3, 0x11, 0x3e, 0xf3, 0xf2, 0x0c, 0xff, 0xff, 0x11, 0x0d, 0x01, 0x0d, 0xf4, 0x11, 0x3f, 0x0d, 0x01, 0xf3, 0x0b, 0x10, 0x84, 0x11, 0x0f, 0xf3, 0x0b, 0x0c, 0xf5, 0x11, 0x3e, 0xf5, 0xf4, 0x0a, 0x99, 0xd6, 0x11, 0x0d, 0x01, 0x0b, 0xf6, 0x11, 0x0a, 0x01, 0x09, 0x19, 0x18, 0x54, 0x40, 0x00, 0x00, 0x00, 0x10, 0x10, 0x1b, 0x04, 0x00, 0x4a, 0x09, 0x09, 0xff, 0x80, 0xff, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0xff, 0x80, 0x00, 0x00, 0x31, 0x00, 0x19, 0x0a, 0x3f, 0x1d, 0xfe, 0xf5, 0x04, 0xff, 0xff, 0x11, 0x0f, 0xf1, 0x0d, 0x0e, 0xf3, 0x11, 0x3e, 0xf3, 0xf2, 0x0c, 0x08, 0x42, 0x11, 0x0d, 0x01, 0x0d, 0xf4, 0x11, 0x3f, 0x0d, 0x01, 0xf3, 0x0b, 0x99, 0xd6, 0x11, 0x0f, 0xf3, 0x0b, 0x0c, 0xf5, 0x11, 0x3e, 0xf5, 0xf4, 0x0a, 0x10, 0x84, 0x11, 0x0d, 0x01, 0x0b, 0xf6, 0x11, 0x3a, 0x01, 0x09, 0x99, 0xd6, 0x19, 0x18, 0xf0, 0x60, 0x11, 0x01, 0x11, 0x01, 0x01, 0x01, 0x04, 0x19, 0x0a, 0x3f, 0xdd, 0x0c, 0xf5, 0x04, 0x08, 0x42, 0x11, 0x0f, 0xf1, 0x0d, 0x0e, 0xf3, 0x11, 0x3e, 0xf3, 0xf2, 0x0c, 0xff, 0xff, 0x11, 0x0d, 0x01, 0x0d, 0xf4, 0x11, 0x3f, 0x0d, 0x01, 0xf3, 0x0b, 0x10, 0x84, 0x11, 0x0f, 0xf3, 0x0b, 0x0c, 0xf5, 0x11, 0x3e, 0xf5, 0xf4, 0x0a, 0x99, 0xd6, 0x11, 0x0d, 0x01, 0x0b, 0xf6, 0x11, 0x0a, 0x01, 0x09, 0x19, 0x18, 0xf4, 0x20, 0x10, 0x00, 0x00, 0xcf, 0x0d, 0xcf, 0x0d, 0x0d, 0x19, 0x0a, 0x3f, 0x1d, 0xfe, 0xf5, 0x04, 0x08, 0x42, 0x11, 0x0f, 0xf1, 0x0d, 0x0e, 0xf3, 0x11, 0x3e, 0xf3, 0xf2, 0x0c, 0xff, 0xff, 0x11, 0x0d, 0x01, 0x0d, 0xf4, 0x11, 0x3f, 0x0d, 0x01, 0xf3, 0x0b, 0x10, 0x84, 0x11, 0x0f, 0xf3, 0x0b, 0x0c, 0xf5, 0x11, 0x3e, 0xf5, 0xf4, 0x0a, 0x99, 0xd6, 0x11, 0x0d, 0x01, 0x0b, 0xf6, 0x11, 0x0a, 0x01, 0x09, 0x19, 0x18, 0xf4, 0x20, 0xff, 0xff, 0x00, 0x11, 0x01, 0x11, 0x01, 0x01, 0x11, 0xf4, 0x20, 0x10, 0x84, 0x00, 0xff, 0xff, 0xff, 0xff, 0xff, 0x19, 0x0a, 0x3f, 0xee, 0x34, 0x3c, 0x08, 0x2d, 0x09, 0x59, 0x0d, 0x97, 0xff, 0x00, 0x02, 0x70, 0x0d, 0x0e, 0x51, 0xc2, 0x10, 0x20, 0x1c, 0x51, 0xc2, 0x12, 0xe0, 0xd6, 0x51, 0xc2, 0x12, 0x30, 0x1c, 0x19, 0x0a, 0x32, 0x12, 0x10, 0x84, 0x59, 0x0d, 0xc6, 0xcc, 0x12, 0xd0, 0xf2, 0x51, 0xc2, 0x10, 0x20, 0x1c, 0x51, 0xc2, 0x12, 0xe0, 0xd6, 0x51, 0xc2, 0x12, 0x30, 0x1c, 0x19, 0x0a, 0x3f, 0x0a, 0x12, 0xb9, 0xf9, 0x08, 0x42, 0x11, 0x0f, 0xf6, 0x0a, 0x09, 0xf6, 0x11, 0x3e, 0xf6, 0xf7, 0x09, 0xff, 0xff, 0x11, 0x0d, 0x01, 0x08, 0xf7, 0x11, 0x3f, 0x08, 0x01, 0xf8, 0x08, 0x10, 0x84, 0x11, 0x0f, 0xf8, 0x08, 0x07, 0xf8, 0x11, 0x3e, 0xf8, 0xf9, 0x07, 0x99, 0xd6, 0x11, 0x0d, 0x01, 0x06, 0xf9, 0x11, 0x0a, 0x01, 0x06, 0x19, 0x18, 0xf5, 0x60, 0x05, 0x00, 0x00, 0x00, 0xef, 0x5a, 0xec, 0x57, 0x57, 0x0f, 0x00, 0x00, 0x46, 0x06, 0x05, 0xcc, 0x78, 0x30, 0x78, 0xcc, 0x00, 0x00, 0x00, 0x72, 0x00, 0x19, 0x0a, 0x3f, 0x13, 0xfe, 0xfa, 0x04, 0xff, 0xff, 0x11, 0x0f, 0xf6, 0x0a, 0x09, 0xf6, 0x11, 0x3e, 0xf6, 0xf7, 0x09, 0x08, 0x42, 0x11, 0x0d, 0x01, 0x08, 0xf7, 0x11, 0x3f, 0x08, 0x01, 0xf8, 0x08, 0x99, 0xd6, 0x11, 0x0f, 0xf8, 0x08, 0x07, 0xf8, 0x11, 0x3e, 0xf8, 0xf9, 0x07, 0x10, 0x84, 0x11, 0x0d, 0x01, 0x06, 0xf9, 0x11, 0x3a, 0x01, 0x06, 0x99, 0xd6, 0x19, 0x18, 0xf0, 0x60, 0x0c, 0x01, 0x0c, 0x01, 0x01, 0x01, 0x00, 0x19, 0x0a, 0x3f, 0x13, 0xfe, 0xfa, 0x04, 0x08, 0x42, 0x11, 0x0f, 0xf6, 0x0a, 0x09, 0xf6, 0x11, 0x3e, 0xf6, 0xf7, 0x09, 0xff, 0xff, 0x11, 0x0d, 0x01, 0x08, 0xf7, 0x11, 0x3f, 0x08, 0x01, 0xf8, 0x08, 0x10, 0x84, 0x11, 0x0f, 0xf8, 0x08, 0x07, 0xf8, 0x11, 0x3e, 0xf8, 0xf9, 0x07, 0x99, 0xd6, 0x11, 0x0d, 0x01, 0x06, 0xf9, 0x11, 0x0a, 0x01, 0x06, 0x19, 0x18, 0xf4, 0x20, 0x10, 0x00, 0x00, 0x0a, 0xff, 0x0a, 0xff, 0xff, 0x19, 0x0a, 0x3f, 0x13, 0xfe, 0xfa, 0x04, 0x08, 0x42, 0x11, 0x0f, 0xf6, 0x0a, 0x09, 0xf6, 0x11, 0x3e, 0xf6, 0xf7, 0x09, 0xff, 0xff, 0x11, 0x0d, 0x01, 0x08, 0xf7, 0x11, 0x3f, 0x08, 0x01, 0xf8, 0x08, 0x10, 0x84, 0x11, 0x0f, 0xf8, 0x08, 0x07, 0xf8, 0x11, 0x3e, 0xf8, 0xf9, 0x07, 0x99, 0xd6, 0x11, 0x0d, 0x01, 0x06, 0xf9, 0x11, 0x0a, 0x01, 0x06, 0x19, 0x18, 0xf4, 0x20, 0xff, 0xff, 0x00, 0x0c, 0x01, 0x0c, 0x01, 0x01, 0x11, 0xf4, 0x20, 0x10, 0x84, 0x00, 0xff, 0xff, 0xff, 0xff, 0xff, 0x19, 0x0a, 0x0f, 0x09, 0xfe, 0x09, 0x09, 0x19, 0x18, 0xf5, 0x60, 0x06, 0xff, 0xff, 0x00, 0x09, 0xfe, 0x12, 0x07, 0x07, 0x23, 0x05, 0x03, 0x4d, 0x0d, 0x0d, 0x00, 0x00, 0x00, 0x08, 0x00, 0x10, 0x00, 0x20, 0x00, 0x40, 0x00, 0x88, 0x01, 0x10, 0x02, 0x20, 0x04, 0x40, 0x08, 0x88, 0x11, 0x10, 0x22, 0x20, 0x44, 0x40, 0x00, 0x00, 0x6f, 0x00, 0x11, 0x04, 0x40, 0x10, 0x84, 0x00, 0x1f, 0x06, 0x04, 0x4c, 0x0c, 0x0c, 0x00, 0x00, 0x00, 0x10, 0x00, 0x30, 0x00, 0x60, 0x00, 0xc0, 0x01, 0x90, 0x03, 0x30, 0x06, 0x60, 0x0c, 0xc0, 0x19, 0x90, 0x33, 0x30, 0x66, 0x60, 0x70, 0x00, 0x19, 0x0a, 0x37, 0xe3, 0x10, 0xf1, 0x08, 0x42, 0x11, 0x0f, 0xf1, 0x0f, 0x0e, 0xf1, 0x11, 0x3e, 0xf1, 0xf2, 0x0e, 0x99, 0xd6, 0x11, 0x0d, 0x01, 0x0d, 0xf2, 0x11, 0x3f, 0x0d, 0x01, 0xf3, 0x0d, 0x10, 0x84, 0x11, 0x0f, 0xf3, 0x0d, 0x0c, 0xf3, 0x11, 0x3e, 0xf3, 0xf4, 0x0c, 0xff, 0xff, 0x11, 0x0d, 0x01, 0x0b, 0xf4, 0x11, 0x3a, 0x01, 0x0b, 0x99, 0xd6, 0x19, 0x18, 0xf4, 0x60, 0x00, 0x00, 0x00, 0xd6, 0x12, 0xd2, 0x0e, 0x0e, 0x0f, 0x07, 0x01, 0x48, 0x09, 0x04, 0x08, 0x00, 0x1c, 0x00, 0x3e, 0x00, 0x7f, 0x00, 0x35, 0x00, 0x19, 0x0a, 0x3f, 0x1d, 0xfe, 0xf5, 0x04, 0x10, 0x84, 0x11, 0x0f, 0xf1, 0x0f, 0x0e, 0xf1, 0x11, 0x0e, 0xf1, 0xf2, 0x0e, 0x11, 0x0d, 0x01, 0x0d, 0xf2, 0x11, 0x3f, 0x0d, 0x01, 0xf3, 0x0d, 0x99, 0xd6, 0x11, 0x0f, 0xf3, 0x0d, 0x0c, 0xf3, 0x11, 0x0e, 0xf3, 0xf4, 0x0c, 0x11, 0x0d, 0x01, 0x0b, 0xf4, 0x11, 0x0a, 0x01, 0x0b, 0x19, 0x18, 0xf0, 0x60, 0x11, 0x01, 0x11, 0x01, 0x01, 0x01, 0x07, 0x19, 0x0a, 0x3f, 0x1d, 0xfe, 0xf5, 0x04, 0x08, 0x42, 0x11, 0x0f, 0xf1, 0x0f, 0x0e, 0xf1, 0x11, 0x3e, 0xf1, 0xf2, 0x0e, 0x99, 0xd6, 0x11, 0x0d, 0x01, 0x0d, 0xf2, 0x11, 0x3f, 0x0d, 0x01, 0xf3, 0x0d, 0x10, 0x84, 0x11, 0x0f, 0xf3, 0x0d, 0x0c, 0xf3, 0x11, 0x3e, 0xf3, 0xf4, 0x0c, 0xff, 0xff, 0x11, 0x0d, 0x01, 0x0b, 0xf4, 0x11, 0x3a, 0x01, 0x0b, 0x99, 0xd6, 0x19, 0x18, 0xf4, 0x20, 0x10, 0x00, 0x00, 0x0f, 0xff, 0x0f, 0xff, 0xff, 0x19, 0x0a, 0x3f, 0x1d, 0xfe, 0xf5, 0x04, 0x08, 0x42, 0x11, 0x0f, 0xf1, 0x0f, 0x0e, 0xf1, 0x11, 0x3e, 0xf1, 0xf2, 0x0e, 0x99, 0xd6, 0x11, 0x0d, 0x01, 0x0d, 0xf2, 0x11, 0x3f, 0x0d, 0x01, 0xf3, 0x0d, 0x10, 0x84, 0x11, 0x0f, 0xf3, 0x0d, 0x0c, 0xf3, 0x11, 0x3e, 0xf3, 0xf4, 0x0c, 0xff, 0xff, 0x11, 0x0d, 0x01, 0x0b, 0xf4, 0x11, 0x3a, 0x01, 0x0b, 0x99, 0xd6, 0x19, 0x18, 0xf4, 0x20, 0xff, 0xff, 0x00, 0x11, 0x01, 0x11, 0x01, 0x01, 0x11, 0xf4, 0x20, 0x10, 0x84, 0x00, 0xff, 0xff, 0xff, 0xff, 0xff, 0x19, 0x0a, 0x3f, 0xdd, 0x0e, 0xf5, 0x04, 0x08, 0x42, 0x11, 0x0f, 0xf1, 0x0f, 0x0e, 0xf1, 0x11, 0x3e, 0xf1, 0xf2, 0x0e, 0x99, 0xd6, 0x11, 0x0d, 0x01, 0x0d, 0xf2, 0x11, 0x3f, 0x0d, 0x01, 0xf3, 0x0d, 0x10, 0x84, 0x11, 0x0f, 0xf3, 0x0d, 0x0c, 0xf3, 0x11, 0x3e, 0xf3, 0xf4, 0x0c, 0xff, 0xff, 0x11, 0x0d, 0x01, 0x0b, 0xf4, 0x11, 0x3a, 0x01, 0x0b, 0x99, 0xd6, 0x19, 0x18, 0xf4, 0x60, 0x00, 0x00, 0x00, 0xd0, 0x10, 0xd0, 0x10, 0x10, 0x0f, 0x08, 0x01, 0x48, 0x09, 0x04, 0x7f, 0x00, 0x3e, 0x00, 0x1c, 0x00, 0x08, 0x00, 0x36, 0x00, 0x19, 0x0a, 0x3f, 0x1d, 0xfe, 0xf5, 0x04, 0x10, 0x84, 0x11, 0x0f, 0xf1, 0x0f, 0x0e, 0xf1, 0x11, 0x0e, 0xf1, 0xf2, 0x0e, 0x11, 0x0d, 0x01, 0x0d, 0xf2, 0x11, 0x3f, 0x0d, 0x01, 0xf3, 0x0d, 0x99, 0xd6, 0x11, 0x0f, 0xf3, 0x0d, 0x0c, 0xf3, 0x11, 0x0e, 0xf3, 0xf4, 0x0c, 0x11, 0x0d, 0x01, 0x0b, 0xf4, 0x11, 0x0a, 0x01, 0x0b, 0x19, 0x18, 0xf0, 0x60, 0x11, 0x01, 0x11, 0x01, 0x01, 0x01, 0x08, 0x19, 0x0a, 0x3f, 0x1d, 0xfe, 0xf5, 0x04, 0x08, 0x42, 0x11, 0x0f, 0xf1, 0x0f, 0x0e, 0xf1, 0x11, 0x3e, 0xf1, 0xf2, 0x0e, 0x99, 0xd6, 0x11, 0x0d, 0x01, 0x0d, 0xf2, 0x11, 0x3f, 0x0d, 0x01, 0xf3, 0x0d, 0x10, 0x84, 0x11, 0x0f, 0xf3, 0x0d, 0x0c, 0xf3, 0x11, 0x3e, 0xf3, 0xf4, 0x0c, 0xff, 0xff, 0x11, 0x0d, 0x01, 0x0b, 0xf4, 0x11, 0x3a, 0x01, 0x0b, 0x99, 0xd6, 0x19, 0x18, 0xf4, 0x20, 0x10, 0x00, 0x00, 0x0f, 0xff, 0x0f, 0xff, 0xff, 0x19, 0x0a, 0x3f, 0x1d, 0xfe, 0xf5, 0x04, 0x08, 0x42, 0x11, 0x0f, 0xf1, 0x0f, 0x0e, 0xf1, 0x11, 0x3e, 0xf1, 0xf2, 0x0e, 0x99, 0xd6, 0x11, 0x0d, 0x01, 0x0d, 0xf2, 0x11, 0x3f, 0x0d, 0x01, 0xf3, 0x0d, 0x10, 0x84, 0x11, 0x0f, 0xf3, 0x0d, 0x0c, 0xf3, 0x11, 0x3e, 0xf3, 0xf4, 0x0c, 0xff, 0xff, 0x11, 0x0d, 0x01, 0x0b, 0xf4, 0x11, 0x3a, 0x01, 0x0b, 0x99, 0xd6, 0x19, 0x18, 0xf4, 0x20, 0xff, 0xff, 0x00, 0x11, 0x01, 0x11, 0x01, 0x01, 0x11, 0xf4, 0x20, 0x10, 0x84, 0x00, 0xff, 0xff, 0xff, 0xff, 0xff, 0x19, 0x0a, 0x3f, 0xdd, 0x0e, 0xf5, 0x04, 0x08, 0x42, 0x11, 0x0f, 0xf1, 0x0f, 0x0e, 0xf1, 0x11, 0x3e, 0xf1, 0xf2, 0x0e, 0x99, 0xd6, 0x11, 0x0d, 0x01, 0x0d, 0xf2, 0x11, 0x3f, 0x0d, 0x01, 0xf3, 0x0d, 0x10, 0x84, 0x11, 0x0f, 0xf3, 0x0d, 0x0c, 0xf3, 0x11, 0x3e, 0xf3, 0xf4, 0x0c, 0xff, 0xff, 0x11, 0x0d, 0x01, 0x0b, 0xf4, 0x11, 0x3a, 0x01, 0x0b, 0x99, 0xd6, 0x19, 0x18, 0xf4, 0x60, 0x00, 0x00, 0x00, 0xd0, 0x10, 0xd0, 0x10, 0x10, 0x13, 0x09, 0x04, 0x4b, 0x04, 0x09, 0x00, 0x80, 0xc0, 0xe0, 0xf0, 0xe0, 0xc0, 0x80, 0x00, 0x00, 0x00, 0x00, 0x34, 0x00, 0x19, 0x0a, 0x3f, 0x1d, 0xfe, 0xf5, 0x04, 0x10, 0x84, 0x11, 0x0f, 0xf1, 0x0f, 0x0e, 0xf1, 0x11, 0x0e, 0xf1, 0xf2, 0x0e, 0x11, 0x0d, 0x01, 0x0d, 0xf2, 0x11, 0x3f, 0x0d, 0x01, 0xf3, 0x0d, 0x99, 0xd6, 0x11, 0x0f, 0xf3, 0x0d, 0x0c, 0xf3, 0x11, 0x0e, 0xf3, 0xf4, 0x0c, 0x11, 0x0d, 0x01, 0x0b, 0xf4, 0x11, 0x0a, 0x01, 0x0b, 0x19, 0x18, 0xf0, 0x60, 0x11, 0x01, 0x11, 0x01, 0x01, 0x01, 0x09, 0x19, 0x0a, 0x3f, 0x1d, 0xfe, 0xf5, 0x04, 0x08, 0x42, 0x11, 0x0f, 0xf1, 0x0f, 0x0e, 0xf1, 0x11, 0x3e, 0xf1, 0xf2, 0x0e, 0x99, 0xd6, 0x11, 0x0d, 0x01, 0x0d, 0xf2, 0x11, 0x3f, 0x0d, 0x01, 0xf3, 0x0d, 0x10, 0x84, 0x11, 0x0f, 0xf3, 0x0d, 0x0c, 0xf3, 0x11, 0x3e, 0xf3, 0xf4, 0x0c, 0xff, 0xff, 0x11, 0x0d, 0x01, 0x0b, 0xf4, 0x11, 0x3a, 0x01, 0x0b, 0x99, 0xd6, 0x19, 0x18, 0xf4, 0x20, 0x10, 0x00, 0x00, 0x0f, 0xff, 0x0f, 0xff, 0xff, 0x19, 0x0a, 0x3f, 0x1d, 0xfe, 0xf5, 0x04, 0x08, 0x42, 0x11, 0x0f, 0xf1, 0x0f, 0x0e, 0xf1, 0x11, 0x3e, 0xf1, 0xf2, 0x0e, 0x99, 0xd6, 0x11, 0x0d, 0x01, 0x0d, 0xf2, 0x11, 0x3f, 0x0d, 0x01, 0xf3, 0x0d, 0x10, 0x84, 0x11, 0x0f, 0xf3, 0x0d, 0x0c, 0xf3, 0x11, 0x3e, 0xf3, 0xf4, 0x0c, 0xff, 0xff, 0x11, 0x0d, 0x01, 0x0b, 0xf4, 0x11, 0x3a, 0x01, 0x0b, 0x99, 0xd6, 0x19, 0x18, 0xf4, 0x20, 0xff, 0xff, 0x00, 0x11, 0x01, 0x11, 0x01, 0x01, 0x11, 0xf4, 0x20, 0x10, 0x84, 0x00, 0xff, 0xff, 0xff, 0xff, 0xff, 0x19, 0x0a, 0x3f, 0xdd, 0x0e, 0xf5, 0x04, 0x08, 0x42, 0x11, 0x0f, 0xf1, 0x0f, 0x0e, 0xf1, 0x11, 0x3e, 0xf1, 0xf2, 0x0e, 0x99, 0xd6, 0x11, 0x0d, 0x01, 0x0d, 0xf2, 0x11, 0x3f, 0x0d, 0x01, 0xf3, 0x0d, 0x10, 0x84, 0x11, 0x0f, 0xf3, 0x0d, 0x0c, 0xf3, 0x11, 0x3e, 0xf3, 0xf4, 0x0c, 0xff, 0xff, 0x11, 0x0d, 0x01, 0x0b, 0xf4, 0x11, 0x3a, 0x01, 0x0b, 0x99, 0xd6, 0x19, 0x18, 0xf4, 0x60, 0x00, 0x00, 0x00, 0xd0, 0x10, 0xd0, 0x10, 0x10, 0x13, 0x0a, 0x03, 0x4b, 0x04, 0x09, 0x00, 0x10, 0x30, 0x70, 0xf0, 0x70, 0x30, 0x10, 0x00, 0x00, 0x00, 0x00, 0x33, 0x00, 0x19, 0x0a, 0x3f, 0x1d, 0xfe, 0xf5, 0x04, 0x10, 0x84, 0x11, 0x0f, 0xf1, 0x0f, 0x0e, 0xf1, 0x11, 0x0e, 0xf1, 0xf2, 0x0e, 0x11, 0x0d, 0x01, 0x0d, 0xf2, 0x11, 0x3f, 0x0d, 0x01, 0xf3, 0x0d, 0x99, 0xd6, 0x11, 0x0f, 0xf3, 0x0d, 0x0c, 0xf3, 0x11, 0x0e, 0xf3, 0xf4, 0x0c, 0x11, 0x0d, 0x01, 0x0b, 0xf4, 0x11, 0x0a, 0x01, 0x0b, 0x19, 0x18, 0xf0, 0x60, 0x11, 0x01, 0x11, 0x01, 0x01, 0x01, 0x0a, 0x19, 0x0a, 0x3f, 0x1d, 0xfe, 0xf5, 0x04, 0x08, 0x42, 0x11, 0x0f, 0xf1, 0x0f, 0x0e, 0xf1, 0x11, 0x3e, 0xf1, 0xf2, 0x0e, 0x99, 0xd6, 0x11, 0x0d, 0x01, 0x0d, 0xf2, 0x11, 0x3f, 0x0d, 0x01, 0xf3, 0x0d, 0x10, 0x84, 0x11, 0x0f, 0xf3, 0x0d, 0x0c, 0xf3, 0x11, 0x3e, 0xf3, 0xf4, 0x0c, 0xff, 0xff, 0x11, 0x0d, 0x01, 0x0b, 0xf4, 0x11, 0x3a, 0x01, 0x0b, 0x99, 0xd6, 0x19, 0x18, 0xf4, 0x20, 0x10, 0x00, 0x00, 0x0f, 0xff, 0x0f, 0xff, 0xff, 0x19, 0x0a, 0x3f, 0x1d, 0xfe, 0xf5, 0x04, 0x08, 0x42, 0x11, 0x0f, 0xf1, 0x0f, 0x0e, 0xf1, 0x11, 0x3e, 0xf1, 0xf2, 0x0e, 0x99, 0xd6, 0x11, 0x0d, 0x01, 0x0d, 0xf2, 0x11, 0x3f, 0x0d, 0x01, 0xf3, 0x0d, 0x10, 0x84, 0x11, 0x0f, 0xf3, 0x0d, 0x0c, 0xf3, 0x11, 0x3e, 0xf3, 0xf4, 0x0c, 0xff, 0xff, 0x11, 0x0d, 0x01, 0x0b, 0xf4, 0x11, 0x3a, 0x01, 0x0b, 0x99, 0xd6, 0x19, 0x18, 0xf4, 0x20, 0xff, 0xff, 0x00, 0x11, 0x01, 0x11, 0x01, 0x01, 0x11, 0xf4, 0x20, 0x10, 0x84, 0x00, 0xff, 0xff, 0xff, 0xff, 0xff, 0x19, 0x0a, 0x3f, 0xce, 0x0e, 0x01, 0x01, 0xff, 0xff, 0x1d, 0x18, 0xf4, 0x60, 0x0e, 0xe2, 0x00, 0x0b, 0x00, 0xee, 0x00, 0x00, 0x00, 0x00, 0xcd, 0x0e, 0xce, 0x0f, 0x0f, 0x13, 0x0b, 0x04, 0x4b, 0x04, 0x09, 0x00, 0x80, 0xc0, 0xe0, 0xf0, 0xe0, 0xc0, 0x80, 0x00, 0x00, 0x00, 0x00, 0x38, 0x00, 0x19, 0x0a, 0x01, 0x0d, 0x19, 0x18, 0x50, 0x40, 0x0d, 0x0d, 0x0f, 0x0c, 0x03, 0x4a, 0x07, 0x08, 0x00, 0x02, 0x06, 0x8e, 0xdc, 0xf8, 0x70, 0x20, 0x61, 0x00, 0x19, 0x0a, 0x01, 0x0d, 0x19, 0x18, 0x50, 0x40, 0x0d, 0x0d, 0x0f, 0x0d, 0x04, 0x4a, 0x06, 0x06, 0x78, 0xfc, 0xfc, 0xfc, 0xfc, 0x78, 0x00, 0x00, 0x68, 0x00, 0x19, 0x0a, 0x3d, 0x0d, 0x02, 0x02, 0x99, 0xd6, 0x19, 0x18, 0xd0, 0x60, 0x0e, 0x10, 0x02, 0x02, 0x13, 0x0e, 0x02, 0x4a, 0x0b, 0x05, 0x04, 0x00, 0x0e, 0x00, 0x1f, 0x00, 0x3f, 0x80, 0x7f, 0xc0, 0x00, 0x00, 0x35, 0x00, 0x19, 0x0a, 0x01, 0x0f, 0x19, 0x18, 0x54, 0x40, 0x10, 0x00, 0x00, 0x0f, 0x0f, 0x01, 0x0e, 0x19, 0x0a, 0x03, 0xca, 0x0f, 0x19, 0x18, 0xf4, 0x20, 0xff, 0xff, 0x00, 0xcb, 0x10, 0xcb, 0x10, 0x10, 0x11, 0xf4, 0x20, 0x10, 0x84, 0x00, 0xff, 0xff, 0xff, 0xff, 0xff, 0x19, 0x0a, 0x01, 0x0f, 0x19, 0x18, 0x54, 0x40, 0x00, 0x00, 0x00, 0x0f, 0x0f, 0x13, 0x0f, 0x02, 0x4a, 0x0b, 0x05, 0x7f, 0xc0, 0x3f, 0x80, 0x1f, 0x00, 0x0e, 0x00, 0x04, 0x00, 0x00, 0x00, 0x36, 0x00, 0x19, 0x0a, 0x01, 0x0f, 0x19, 0x18, 0x54, 0x40, 0x10, 0x00, 0x00, 0x0f, 0x0f, 0x01, 0x0f, 0x19, 0x0a, 0x01, 0x0f, 0x19, 0x18, 0xf4, 0x20, 0xff, 0xff, 0x00, 0x10, 0x01, 0x10, 0x01, 0x01, 0x11, 0xf4, 0x20, 0x10, 0x84, 0x00, 0xff, 0xff, 0xff, 0xff, 0xff, 0x19, 0x0a, 0x3f, 0xd3, 0x0f, 0xfe, 0xfe, 0xff, 0xff, 0x19, 0x18, 0xf4, 0x60, 0x00, 0x00, 0x00, 0xd3, 0x0f, 0xd1, 0x0d, 0x0d, 0x1b, 0x10, 0x02, 0x4c, 0x0a, 0x0a, 0x1e, 0x00, 0x7f, 0x80, 0x7f, 0x80, 0xff, 0xc0, 0xff, 0xc0, 0xff, 0xc0, 0xff, 0xc0, 0x7f, 0x80, 0x7f, 0x80, 0x1e, 0x00, 0x6e, 0x00, 0x11, 0x00, 0x40, 0x17, 0x11, 0x03, 0x4a, 0x09, 0x08, 0x01, 0x00, 0x00, 0x80, 0x00, 0x80, 0x00, 0x80, 0x00, 0x80, 0x01, 0x00, 0xc3, 0x00, 0x3c, 0x00, 0x6d, 0x00, 0x11, 0x00, 0x40, 0x17, 0x12, 0x02, 0x4c, 0x09, 0x08, 0x1e, 0x00, 0x61, 0x80, 0x40, 0x00, 0x80, 0x00, 0x80, 0x00, 0x80, 0x00, 0x80, 0x00, 0x40, 0x00, 0x6c, 0x00, 0x11, 0x00, 0x40, 0x1b, 0x13, 0x03, 0x4b, 0x0a, 0x0a, 0x00, 0x80, 0x00, 0x80, 0x00, 0x40, 0x00, 0x40, 0x00, 0x40, 0x00, 0x40, 0x00, 0x80, 0x00, 0x80, 0xc3, 0x00, 0x3c, 0x00, 0x6b, 0x00, 0x11, 0x00, 0x40, 0x1b, 0x14, 0x01, 0x4d, 0x0a, 0x0a, 0x0f, 0x00, 0x30, 0xc0, 0x40, 0x00, 0x40, 0x00, 0x80, 0x00, 0x80, 0x00, 0x80, 0x00, 0x80, 0x00, 0x40, 0x00, 0x40, 0x00, 0x6a, 0x00, 0x11, 0x54, 0x40, 0xff, 0xff, 0x00, 0x0d, 0x0d, 0x1b, 0x15, 0x02, 0x4b, 0x09, 0x09, 0xff, 0x80, 0xff, 0x80, 0xff, 0x80, 0xff, 0x80, 0xff, 0x80, 0xff, 0x80, 0xff, 0x80, 0xff, 0x80, 0xff, 0x80, 0x00, 0x00, 0x67, 0x00, 0x11, 0x04, 0x40, 0x99, 0xd6, 0x00, 0x1f, 0x16, 0x01, 0x4c, 0x0b, 0x0b, 0x00, 0x20, 0x00, 0x20, 0x00, 0x20, 0x00, 0x20, 0x00, 0x20, 0x00, 0x20, 0x00, 0x20, 0x00, 0x20, 0x00, 0x20, 0x00, 0x20, 0xff, 0xe0, 0x00, 0x00, 0x66, 0x00, 0x11, 0x04, 0x40, 0x08, 0x42, 0x00, 0x1b, 0x17, 0x01, 0x4c, 0x0a, 0x0a, 0xff, 0xc0, 0x80, 0x00, 0x80, 0x00, 0x80, 0x00, 0x80, 0x00, 0x80, 0x00, 0x80, 0x00, 0x80, 0x00, 0x80, 0x00, 0x80, 0x00, 0x65, 0x00, 0x11, 0x04, 0x40, 0xff, 0xff, 0x00, 0x23, 0x18, 0x00, 0x4d, 0x0d, 0x0d, 0x00, 0x08, 0x00, 0x08, 0x00, 0x08, 0x00, 0x08, 0x00, 0x08, 0x00, 0x08, 0x00, 0x08, 0x00, 0x08, 0x00, 0x08, 0x00, 0x08, 0x00, 0x08, 0x00, 0x08, 0xff, 0xf8, 0x00, 0x00, 0x64, 0x00, 0x11, 0x04, 0x40, 0x10, 0x84, 0x00, 0x1f, 0x19, 0x00, 0x4d, 0x0c, 0x0c, 0xff, 0xf0, 0x80, 0x00, 0x80, 0x00, 0x80, 0x00, 0x80, 0x00, 0x80, 0x00, 0x80, 0x00, 0x80, 0x00, 0x80, 0x00, 0x80, 0x00, 0x80, 0x00, 0x80, 0x00, 0x63, 0x00, 0x11, 0x54, 0x40, 0xff, 0xff, 0x00, 0x0d, 0x0d, 0x01, 0x15, 0x11, 0x04, 0x40, 0x99, 0xd6, 0x00, 0x01, 0x16, 0x11, 0x04, 0x40, 0x08, 0x42, 0x00, 0x01, 0x17, 0x11, 0x04, 0x40, 0xff, 0xff, 0x00, 0x01, 0x18, 0x11, 0x04, 0x40, 0x10, 0x84, 0x00, 0x01, 0x19, 0x11, 0x04, 0x40, 0x00, 0x00, 0x00, 0x0f, 0x1a, 0x03, 0x4b, 0x07, 0x08, 0x00, 0x02, 0x06, 0x8e, 0xdc, 0xf8, 0x70, 0x20, 0x62, 0x00, 0x11, 0x54, 0x40, 0x99, 0xd6, 0x00, 0x0d, 0x0d, 0x01, 0x15, 0x11, 0x00, 0x40, 0x01, 0x16, 0x11, 0x04, 0x40, 0x08, 0x42, 0x00, 0x01, 0x17, 0x11, 0x04, 0x40, 0xff, 0xff, 0x00, 0x01, 0x18, 0x11, 0x04, 0x40, 0x10, 0x84, 0x00, 0x01, 0x19, 0x11, 0x54, 0x40, 0x99, 0xd6, 0x00, 0x0d, 0x0d, 0x01, 0x15, 0x11, 0x00, 0x40, 0x01, 0x16, 0x11, 0x04, 0x40, 0x08, 0x42, 0x00, 0x01, 0x17, 0x11, 0x04, 0x40, 0xff, 0xff, 0x00, 0x01, 0x18, 0x11, 0x04, 0x40, 0x10, 0x84, 0x00, 0x01, 0x19, 0x11, 0x04, 0x40, 0x00, 0x00, 0x00, 0x01, 0x1a, 0x11, 0xf4, 0x60, 0x99, 0xd6, 0x00, 0xcc, 0x0d, 0xcc, 0x0d, 0x0d, 0x01, 0x15, 0x11, 0x00, 0x40, 0x01, 0x16, 0x11, 0x04, 0x40, 0x08, 0x42, 0x00, 0x01, 0x17, 0x11, 0x04, 0x40, 0xff, 0xff, 0x00, 0x01, 0x18, 0x11, 0x04, 0x40, 0x10, 0x84, 0x00, 0x01, 0x19, 0x11, 0x00, 0x40, 0x01, 0x1a, 0x19, 0x0a, 0x33, 0x0d, 0x0d, 0x00, 0x00, 0x19, 0x18, 0x54, 0x40, 0xff, 0xff, 0x00, 0x0d, 0x0d, 0x01, 0x10, 0x11, 0x04, 0x40, 0x99, 0xd6, 0x00, 0x01, 0x11, 0x11, 0x04, 0x40, 0x08, 0x42, 0x00, 0x01, 0x12, 0x11, 0x04, 0x40, 0xff, 0xff, 0x00, 0x01, 0x13, 0x11, 0x04, 0x40, 0x10, 0x84, 0x00, 0x01, 0x14, 0x19, 0x0a, 0x01, 0x0d, 0x19, 0x18, 0x54, 0x40, 0xff, 0xff, 0x00, 0x0d, 0x0d, 0x01, 0x10, 0x11, 0x04, 0x40, 0x99, 0xd6, 0x00, 0x01, 0x11, 0x11, 0x04, 0x40, 0x08, 0x42, 0x00, 0x01, 0x12, 0x11, 0x04, 0x40, 0xff, 0xff, 0x00, 0x01, 0x13, 0x11, 0x04, 0x40, 0x10, 0x84, 0x00, 0x01, 0x14, 0x11, 0x04, 0x40, 0x00, 0x00, 0x00, 0x0b, 0x1b, 0x05, 0x49, 0x04, 0x04, 0x60, 0xf0, 0xf0, 0x60, 0x69, 0x00, 0x19, 0x0a, 0x01, 0x0d, 0x19, 0x18, 0x54, 0x40, 0x99, 0xd6, 0x00, 0x0d, 0x0d, 0x01, 0x10, 0x11, 0x00, 0x40, 0x01, 0x11, 0x11, 0x04, 0x40, 0x08, 0x42, 0x00, 0x01, 0x12, 0x11, 0x04, 0x40, 0xff, 0xff, 0x00, 0x01, 0x13, 0x11, 0x04, 0x40, 0x10, 0x84, 0x00, 0x01, 0x14, 0x19, 0x0a, 0x01, 0x0d, 0x19, 0x18, 0x54, 0x40, 0x99, 0xd6, 0x00, 0x0d, 0x0d, 0x01, 0x10, 0x11, 0x00, 0x40, 0x01, 0x11, 0x11, 0x04, 0x40, 0x08, 0x42, 0x00, 0x01, 0x12, 0x11, 0x04, 0x40, 0xff, 0xff, 0x00, 0x01, 0x13, 0x11, 0x04, 0x40, 0x10, 0x84, 0x00, 0x01, 0x14, 0x11, 0x04, 0x40, 0x00, 0x00, 0x00, 0x01, 0x1b, 0x19, 0x0a, 0x03, 0xcc, 0x0d, 0x19, 0x18, 0xf4, 0x60, 0x99, 0xd6, 0x00, 0xcc, 0x0d, 0xcc, 0x0d, 0x0d, 0x01, 0x10, 0x11, 0x00, 0x40, 0x01, 0x11, 0x11, 0x04, 0x40, 0x08, 0x42, 0x00, 0x01, 0x12, 0x11, 0x04, 0x40, 0xff, 0xff, 0x00, 0x01, 0x13, 0x11, 0x04, 0x40, 0x10, 0x84, 0x00, 0x01, 0x14, 0x11, 0x00, 0x40, 0x01, 0x1b, 0x03, 0x07, 0x00, 0x00, 0x00, 0x07, 0x00, 0x01, 0x08, 0x08, 0x81, 0x08, 0xaa, 0x55, 0xaa, 0x55, 0xaa, 0x55, 0xaa, 0x55, 0x09, 0x01, 0x7f, 0x02, 0x0d, 0x00, 0x1a, 0x01, 0x0d, 0x00, 0x0d, 0x00, 0xf0, 0xff, 0xff, 0x00, 0x99, 0xd6, 0x00, 0x81, 0x19, 0x18, 0x54, 0x40, 0x99, 0xd6, 0x00, 0x0d, 0x0d, 0x01, 0x16, 0x11, 0x04, 0x40, 0x08, 0x42, 0x00, 0x01, 0x17, 0x11, 0x04, 0x40, 0xff, 0xff, 0x00, 0x01, 0x18, 0x11, 0x04, 0x40, 0x10, 0x84, 0x00, 0x01, 0x19, 0x11, 0x00, 0x40, 0x01, 0x1a, 0x11, 0x54, 0x40, 0x99, 0xd6, 0x00, 0x0d, 0x0d, 0x01, 0x15, 0x11, 0x00, 0x40, 0x01, 0x16, 0x11, 0x04, 0x40, 0x08, 0x42, 0x00, 0x01, 0x17, 0x11, 0x04, 0x40, 0xff, 0xff, 0x00, 0x01, 0x18, 0x11, 0x04, 0x40, 0x10, 0x84, 0x00, 0x01, 0x19, 0x11, 0x00, 0x40, 0x01, 0x1a, 0x11, 0x54, 0x40, 0x99, 0xd6, 0x00, 0x0d, 0x0d, 0x01, 0x15, 0x11, 0x00, 0x40, 0x01, 0x16, 0x11, 0x04, 0x40, 0x08, 0x42, 0x00, 0x01, 0x17, 0x11, 0x04, 0x40, 0xff, 0xff, 0x00, 0x01, 0x18, 0x11, 0x04, 0x40, 0x10, 0x84, 0x00, 0x01, 0x19, 0x11, 0x00, 0x40, 0x01, 0x1a, 0x19, 0x0a, 0x31, 0x34, 0xff, 0xff, 0x19, 0x18, 0x54, 0x40, 0x00, 0x00, 0x00, 0x0c, 0x0c, 0x1b, 0x1c, 0x02, 0x4b, 0x09, 0x09, 0xc1, 0x80, 0xe3, 0x80, 0x77, 0x00, 0x3e, 0x00, 0x1c, 0x00, 0x3e, 0x00, 0x77, 0x00, 0xe3, 0x80, 0xc1, 0x80, 0x00, 0x00, 0x72, 0x00, 0x19, 0x0a, 0x03, 0xcc, 0x0d, 0x1d, 0x18, 0xf0, 0x60, 0xa0, 0x45, 0x45, 0xcc, 0x0d, 0xcc, 0x0d, 0x0d, 0x1b, 0x1d, 0x01, 0x4b, 0x0a, 0x09, 0x3f, 0xc0, 0x3f, 0xc0, 0x20, 0x40, 0xff, 0x40, 0xff, 0x40, 0x81, 0xc0, 0x81, 0x00, 0x81, 0x00, 0xff, 0x00, 0x00, 0x00, 0x32, 0x00, 0x19, 0x0a, 0x01, 0x0d, 0x19, 0x18, 0x50, 0x40, 0x0d, 0x0d, 0x1b, 0x1e, 0x01, 0x4c, 0x0a, 0x0a, 0xff, 0xc0, 0xff, 0xc0, 0x80, 0x40, 0x80, 0x40, 0x80, 0x40, 0x80, 0x40, 0x80, 0x40, 0x80, 0x40, 0x80, 0x40, 0xff, 0xc0, 0x31, 0x00, 0x19, 0x0a, 0x01, 0x0d, 0x19, 0x18, 0x50, 0x40, 0x0d, 0x0d, 0x0b, 0x1f, 0x02, 0x44, 0x07, 0x02, 0xfe, 0xfe, 0x00, 0x00, 0x30, 0x00, 0x19, 0x0a, 0x3d, 0x0d, 0x03, 0x03, 0x99, 0xd6, 0x19, 0x18, 0xd4, 0x60, 0xff, 0xff, 0x00, 0x0e, 0x11, 0x03, 0x03, 0x23, 0x20, 0x00, 0x4d, 0x0d, 0x0d, 0x00, 0x00, 0x80, 0x00, 0x40, 0x00, 0x20, 0x00, 0x10, 0x00, 0x88, 0x00, 0x44, 0x00, 0x22, 0x00, 0x11, 0x00, 0x88, 0x80, 0x44, 0x40, 0x22, 0x20, 0x11, 0x10, 0x00, 0x00, 0x78, 0x00, 0x11, 0x04, 0x40, 0x10, 0x84, 0x00, 0x1f, 0x21, 0x00, 0x4c, 0x0c, 0x0c, 0x00, 0x00, 0x80, 0x00, 0xc0, 0x00, 0x60, 0x00, 0x30, 0x00, 0x98, 0x00, 0xcc, 0x00, 0x66, 0x00, 0x33, 0x00, 0x99, 0x80, 0xcc, 0xc0, 0x66, 0x60, 0x79, 0x00, 0x19, 0x0a, 0x3d, 0x10, 0xfd, 0xfd, 0xff, 0xff, 0x19, 0x18, 0xd4, 0x60, 0x00, 0x00, 0x00, 0x0f, 0x0c, 0xfd, 0xfd, 0x13, 0x22, 0x05, 0x4b, 0x04, 0x09, 0x00, 0x10, 0x30, 0x70, 0xf0, 0x70, 0x30, 0x10, 0x00, 0x00, 0x00, 0x00, 0x77, 0x00, 0x02, 0xff, 0xff, 0x0d, 0x0a, 0x3f, 0x0e, 0x00, 0x00, 0xff, 0x03, 0xff, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x04, 0x00, 0x03, 0x00, 0x00, 0x06, 0x02, 0x00, 0x48, 0x00, 0x37, 0x01, 0x02, 0x02, 0x00, 0x09, 0x00, 0x0c, 0x48, 0x00, 0x37, 0x01, 0x03, 0xcf, 0x04, 0xa2, 0x0c, 0x05, 0x40, 0x44, 0xd1, 0xff, 0xff, 0x80, 0x00, 0xff, 0xff, 0x99, 0xd6, 0x99, 0xd6, 0x10, 0x00, 0x99, 0xd6, 0x99, 0xd6, 0x99, 0xd6, 0x99, 0xd6, 0x99, 0xd6, 0x99, 0xd6, 0x99, 0xd6, 0x10, 0x00, 0x99, 0xd6, 0x99, 0xd6, 0x10, 0x84, 0x08, 0x42, 0xff, 0xff, 0x99, 0xd6, 0x99, 0xd6, 0x10, 0x84, 0xff, 0xff, 0x99, 0xd6, 0x99, 0xd6, 0x99, 0xd6, 0x99, 0xd6, 0x99, 0xd6, 0x99, 0xd6, 0x10, 0x84, 0xff, 0xff, 0x99, 0xd6, 0x10, 0x84, 0x08, 0x42, 0x1c, 0x84, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x75, 0xc6, 0x66, 0x29, 0x00, 0x09, 0x68, 0x10, 0x00, 0x08, 0x68, 0x10, 0x84, 0x00, 0x20, 0x00, 0x07, 0x6b, 0x99, 0xd6, 0x05, 0x6b, 0x99, 0xd6, 0x00, 0x03, 0x6e, 0xff, 0xff, 0x02, 0x6e, 0xff, 0xff, 0x00, 0x10, 0xc0, 0x00, 0xf7, 0xbd, 0x01, 0xc0, 0x00, 0x08, 0x42, 0xc0, 0x00, 0xff, 0xff, 0x81, 0x08, 0x42, 0xce, 0x66, 0x29, 0x01, 0xfd, 0xce, 0x18, 0xc6, 0x01, 0xfd, 0x2e, 0x01, 0x81, 0x08, 0x42, 0xce, 0x66, 0x29, 0x02, 0x81, 0x10, 0x84, 0x06, 0x82, 0x00, 0x00, 0x00, 0x00, 0x07, 0xcd, 0x89, 0x52, 0x03, 0x2d, 0x03, 0x83, 0x10, 0x84, 0x99, 0xd6, 0x99, 0xd6, 0xc9, 0x99, 0xd6, 0x1a, 0x82, 0x10, 0x00, 0x10, 0x00, 0x0a, 0x29, 0x09, 0x27, 0x0c, 0x67, 0x99, 0xd6, 0x15, 0x27, 0x1d, 0x82, 0x00, 0x00, 0x00, 0x00, 0x0d, 0x67, 0x99, 0xd6, 0x00, 0x19, 0xd0, 0x30, 0x89, 0xd6, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xd8, 0x99, 0xd6, 0x05, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xc0, 0x01, 0x83, 0x99, 0xd6, 0x00, 0x00, 0x00, 0x00, 0x0b, 0xd8, 0x89, 0xd6, 0x05, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xc0, 0x01, 0x83, 0x99, 0xd6, 0x10, 0x00, 0x10, 0x00, 0x1a, 0x68, 0x00, 0x00, 0x09, 0x86, 0x99, 0xd6, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x99, 0xd6, 0x18, 0x68, 0x00, 0x00, 0x1b, 0x68, 0x99, 0xd6, 0x06, 0x86, 0x99, 0xd6, 0x10, 0x00, 0x10, 0x00, 0x10, 0x00, 0x10, 0x00, 0x99, 0xd6, 0x19, 0x6b, 0x99, 0xd6, 0x03, 0xcc, 0x89, 0x52, 0x08, 0x68, 0x99, 0xd6, 0x05, 0x6b, 0x99, 0xd6, 0x04, 0x2c, 0x03, 0x6e, 0x08, 0x42, 0x02, 0x6e, 0xff, 0xff, 0x02, 0x6e, 0xff, 0xff, 0x02, 0x6e, 0x08, 0x42, 0x10, 0x81, 0x08, 0x42, 0x70, 0xff, 0xff, 0x60, 0x00, 0x08, 0x42, 0xfd, 0xce, 0x18, 0xc6, 0x01, 0x81, 0x08, 0x42, 0xce, 0x66, 0x29, 0x01, 0xfd, 0xce, 0x18, 0xc6, 0x01, 0xfd, 0x2e, 0x02, 0xcd, 0x89, 0x52, 0x03, 0x89, 0x10, 0x84, 0x99, 0xd6, 0x99, 0xd6, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x07, 0x2d, 0x03, 0x2d, 0x05, 0xc6, 0x99, 0xd6, 0x0c, 0x84, 0x99, 0xd6, 0x99, 0xd6, 0x99, 0xd6, 0x99, 0xd6, 0x0a, 0xc6, 0x89, 0xd6, 0x0e, 0x82, 0x00, 0x00, 0x00, 0x00, 0x0b, 0x84, 0x99, 0xd6, 0x99, 0xd6, 0x99, 0xd6, 0x99, 0xd6, 0x1c, 0x40, 0x35, 0x0f, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xd0, 0x4e, 0x99, 0xd6, 0x03, 0x00, 0x00, 0x60, 0x00, 0x80, 0x01, 0x78, 0x01, 0x00, 0x82, 0x10, 0x00, 0x10, 0x00, 0x0c, 0x40, 0x2c, 0x03, 0xe0, 0x05, 0x00, 0x00, 0x00, 0xd6, 0x89, 0xd6, 0x2f, 0x00, 0x00, 0x00, 0x00, 0x00, 0xd0, 0x4e, 0x99, 0xd6, 0x3b, 0x00, 0x00, 0x00, 0x28, 0x80, 0x1d, 0x00, 0x78, 0x00, 0x86, 0x99, 0xd6, 0x99, 0xd6, 0x10, 0x00, 0x99, 0xd6, 0x99, 0xd6, 0x99, 0xd6, 0x0c, 0x85, 0x00, 0x00, 0x00, 0x00, 0x99, 0xd6, 0x99, 0xd6, 0x00, 0x00, 0x40, 0x2b, 0x01, 0xf0, 0x00, 0x00, 0x00, 0x00, 0xd6, 0x89, 0xd6, 0x0f, 0x00, 0x00, 0x00, 0x00, 0x00, 0x69, 0x99, 0xd6, 0x16, 0x86, 0x99, 0xd6, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x99, 0xd6, 0x0a, 0x69, 0x99, 0xd6, 0x04, 0xcc, 0x89, 0x52, 0x07, 0x69, 0x99, 0xd6, 0x08, 0x68, 0x99, 0xd6, 0x03, 0x6e, 0xff, 0xff, 0x02, 0x6e, 0x08, 0x42, 0x02, 0x6e, 0xff, 0xff, 0x02, 0x6e, 0xff, 0xff, 0x01, 0x70, 0x08, 0x42, 0x70, 0xff, 0xff, 0x60, 0x00, 0x08, 0x42, 0xfd, 0xce, 0x18, 0xc6, 0x01, 0x81, 0x08, 0x42, 0xce, 0x66, 0x29, 0x01, 0xfd, 0xce, 0x18, 0xc6, 0x01, 0xfd, 0x2e, 0x02, 0xcd, 0x89, 0x52, 0x03, 0x8a, 0x10, 0x84, 0x99, 0xd6, 0x99, 0xd6, 0x99, 0xd6, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x06, 0x2d, 0x03, 0x8d, 0x99, 0xd6, 0x99, 0xd6, 0x99, 0xd6, 0x99, 0xd6, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x99, 0xd6, 0x99, 0xd6, 0x99, 0xd6, 0x06, 0xc6, 0x99, 0xd6, 0x1a, 0xc6, 0x89, 0xd6, 0x0a, 0x66, 0x10, 0x84, 0x1b, 0x6a, 0x99, 0xd6, 0x1b, 0x81, 0x99, 0xd6, 0x09, 0x6a, 0x99, 0xd6, 0x16, 0x6a, 0x99, 0xd6, 0x06, 0x6a, 0x99, 0xd6, 0xf0, 0x94, 0x01, 0xcc, 0x89, 0x52, 0x00, 0x03, 0x6e, 0xff, 0xff, 0x02, 0x6e, 0x08, 0x42, 0x02, 0x6e, 0xff, 0xff, 0x02, 0x6e, 0xff, 0xff, 0x01, 0x70, 0x08, 0x42, 0x70, 0xff, 0xff, 0x60, 0x00, 0x08, 0x42, 0xfd, 0xce, 0x18, 0xc6, 0x01, 0x81, 0x08, 0x42, 0xce, 0x66, 0x29, 0x01, 0xfd, 0xce, 0x18, 0xc6, 0x01, 0xfd, 0x2e, 0x02, 0xcd, 0x89, 0x52, 0x03, 0x10, 0x2d, 0x03, 0x2d, 0x17, 0x88, 0x00, 0x00, 0x00, 0x00, 0x99, 0xd6, 0x99, 0xd6, 0x99, 0xd6, 0x99, 0xd6, 0x00, 0x00, 0x00, 0x00, 0x18, 0x88, 0xff, 0xff, 0xff, 0xff, 0x99, 0xd6, 0x99, 0xd6, 0x99, 0xd6, 0x99, 0xd6, 0xff, 0xff, 0xff, 0xff, 0x07, 0x88, 0x00, 0x00, 0x00, 0x00, 0x99, 0xd6, 0x99, 0xd6, 0x99, 0xd6, 0x99, 0xd6, 0x00, 0x00, 0x00, 0x00, 0x09, 0x88, 0x99, 0xd6, 0x00, 0x00, 0x00, 0x00, 0x99, 0xd6, 0x99, 0xd6, 0x00, 0x00, 0x00, 0x00, 0x99, 0xd6, 0x07, 0x88, 0x10, 0x00, 0x10, 0x00, 0x99, 0xd6, 0x99, 0xd6, 0x99, 0xd6, 0x99, 0xd6, 0x10, 0x00, 0x10, 0x00, 0x08, 0x89, 0x10, 0x84, 0x10, 0x84, 0xff, 0xff, 0xff, 0xff, 0x99, 0xd6, 0x99, 0xd6, 0x10, 0x84, 0x10, 0x84, 0x99, 0xd6, 0x07, 0x88, 0x99, 0xd6, 0x00, 0x00, 0x00, 0x00, 0x99, 0xd6, 0x99, 0xd6, 0x00, 0x00, 0x00, 0x00, 0x99, 0xd6, 0x0a, 0x86, 0x99, 0xd6, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x99, 0xd6, 0x08, 0x88, 0x99, 0xd6, 0x10, 0x00, 0x10, 0x00, 0x99, 0xd6, 0x99, 0xd6, 0x10, 0x00, 0x10, 0x00, 0x99, 0xd6, 0x08, 0x88, 0x99, 0xd6, 0x10, 0x84, 0x10, 0x84, 0xff, 0xff, 0xff, 0xff, 0x10, 0x84, 0x10, 0x84, 0x99, 0xd6, 0x09, 0x86, 0x99, 0xd6, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x99, 0xd6, 0x0c, 0x84, 0x99, 0xd6, 0x00, 0x00, 0x00, 0x00, 0x99, 0xd6, 0x0a, 0x86, 0x99, 0xd6, 0x10, 0x00, 0x10, 0x00, 0x10, 0x00, 0x10, 0x00, 0x99, 0xd6, 0x0a, 0x86, 0x99, 0xd6, 0x10, 0x84, 0x10, 0x84, 0x10, 0x84, 0x10, 0x84, 0x99, 0xd6, 0x0b, 0x84, 0x99, 0xd6, 0x00, 0x00, 0x00, 0x00, 0x99, 0xd6, 0x0d, 0x84, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0b, 0x84, 0x99, 0xd6, 0x10, 0x00, 0x10, 0x00, 0x99, 0xd6, 0x0c, 0x85, 0x99, 0xd6, 0x10, 0x84, 0x10, 0x84, 0xff, 0xff, 0xff, 0xff, 0x0b, 0x84, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0c, 0x86, 0x00, 0x00, 0x00, 0x00, 0x99, 0xd6, 0x99, 0xd6, 0x00, 0x00, 0x00, 0x00, 0x0a, 0x84, 0x10, 0x00, 0x10, 0x00, 0x10, 0x00, 0x10, 0x00, 0x0c, 0x86, 0x10, 0x84, 0x10, 0x84, 0x10, 0x84, 0x10, 0x84, 0xff, 0xff, 0xff, 0xff, 0x09, 0x86, 0x00, 0x00, 0x00, 0x00, 0x99, 0xd6, 0x99, 0xd6, 0x00, 0x00, 0x00, 0x00, 0x0a, 0x88, 0x00, 0x00, 0x00, 0x00, 0x99, 0xd6, 0x99, 0xd6, 0x99, 0xd6, 0x99, 0xd6, 0x00, 0x00, 0x00, 0x00, 0x08, 0x86, 0x10, 0x00, 0x10, 0x00, 0x99, 0xd6, 0x99, 0xd6, 0x10, 0x00, 0x10, 0x00, 0x0a, 0x88, 0x10, 0x84, 0x10, 0x84, 0x99, 0xd6, 0x99, 0xd6, 0x10, 0x84, 0x10, 0x84, 0xff, 0xff, 0xff, 0xff, 0x07, 0x88, 0x00, 0x00, 0x00, 0x00, 0x99, 0xd6, 0x99, 0xd6, 0x99, 0xd6, 0x99, 0xd6, 0x00, 0x00, 0x00, 0x00, 0x09, 0x6a, 0x99, 0xd6, 0x05, 0x88, 0x10, 0x00, 0x10, 0x00, 0x99, 0xd6, 0x99, 0xd6, 0x99, 0xd6, 0x99, 0xd6, 0x10, 0x00, 0x10, 0x00, 0x08, 0x89, 0x10, 0x84, 0x10, 0x84, 0x99, 0xd6, 0x99, 0xd6, 0x99, 0xd6, 0x99, 0xd6, 0x10, 0x84, 0x10, 0x84, 0x99, 0xd6, 0x07, 0x6a, 0x99, 0xd6, 0x16, 0x6a, 0x99, 0xd6, 0x06, 0x6a, 0x99, 0xd6, 0x14, 0x2c, 0x00, 0x03, 0x6e, 0xff, 0xff, 0x02, 0x6e, 0x08, 0x42, 0x02, 0x6e, 0xff, 0xff, 0x02, 0xcb, 0x66, 0x29, 0x84, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x08, 0x42, 0x09, 0x0d, 0xdf, 0x01, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x40, 0x00, 0x40, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0x7f, 0x03, 0x15, 0x00, 0xa2, 0x0c, 0x05, 0x40, 0x40, 0x17, 0xff, 0xff, 0x00, 0x1c, 0x84, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xf0, 0xbc, 0x0f, 0x84, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x51, 0x0a, 0x40, 0xc8, 0x03, 0xf4, 0x00, 0xa2, 0x0c, 0x05, 0x40, 0x40, 0xf6, 0xff, 0xff, 0xc0, 0x2c, 0x2d, 0x09, 0x84, 0x2d, 0x09, 0x2d, 0x09, 0x2d, 0x09, 0x2d, 0x09, 0x00, 0x22, 0xc0, 0x10, 0x25, 0x4b, 0x02, 0x30, 0x02, 0x2a, 0x02, 0xfd, 0xce, 0x18, 0xc6, 0x01, 0xfd, 0x2e, 0x03, 0xfd, 0x2e, 0x03, 0xfd, 0x29, 0x03, 0xcd, 0x89, 0x52, 0x03, 0x2d, 0x05, 0x2d, 0x05, 0x29, 0x06, 0xc6, 0x99, 0xd6, 0x09, 0x29, 0x1f, 0x43, 0x03, 0x00, 0x00, 0x01, 0x27, 0x0b, 0x44, 0xc3, 0x00, 0x00, 0xc0, 0x68, 0x99, 0xd6, 0x18, 0x48, 0xa5, 0x00, 0x60, 0x00, 0x00, 0x00, 0x00, 0x00, 0x40, 0xc2, 0x5a, 0x00, 0x60, 0x00, 0x00, 0x00, 0x00, 0x00, 0x24, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x24, 0x00, 0xa0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0x81, 0x99, 0xd6, 0x48, 0x05, 0x80, 0x05, 0x00, 0x00, 0xfc, 0x01, 0x50, 0x40, 0x69, 0x0a, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x30, 0x0c, 0x80, 0x06, 0x00, 0x00, 0x02, 0x6a, 0x99, 0xd6, 0x1c, 0x86, 0x99, 0xd6, 0x99, 0xd6, 0x99, 0xd6, 0x99, 0xd6, 0x2d, 0x09, 0x2d, 0x09, 0x6f, 0xff, 0xff, 0x02, 0x6e, 0xff, 0xff, 0x04, 0x6e, 0xff, 0xff, 0x04, 0xc9, 0x66, 0x29, 0x02, 0x60, 0x5e, 0x2d, 0x09, 0xc0, 0x30, 0x2d, 0x09, 0xf0, 0xc0, 0x09, 0xc0, 0x10, 0x08, 0x42, 0x00, 0x00, 0xfd, 0xce, 0x18, 0xc6, 0x01, 0xfd, 0x2e, 0x00, 0x02, 0xcd, 0x89, 0x52, 0x03, 0x83, 0x99, 0xd6, 0x99, 0xd6, 0x99, 0xd6, 0xc9, 0xef, 0x7b, 0x81, 0x99, 0xd6, 0x00, 0x05, 0xc9, 0x89, 0xd6, 0x07, 0x69, 0x10, 0x84, 0x00, 0x08, 0x27, 0x09, 0x82, 0xff, 0xff, 0x99, 0xd6, 0xd0, 0x69, 0x89, 0x52, 0x1f, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x51, 0x0e, 0xc0, 0x40, 0x38, 0x03, 0xa8, 0x00, 0xa2, 0x0c, 0x05, 0x40, 0x40, 0xaa, 0xff, 0xff, 0xc8, 0x2d, 0x09, 0x00, 0x14, 0x84, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x20, 0xc6, 0x25, 0x4b, 0x00, 0x1a, 0xd8, 0x18, 0xc6, 0x1f, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xf7, 0xc0, 0x01, 0x89, 0x52, 0x0f, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xf7, 0x00, 0x01, 0x99, 0xd6, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x84, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xd0, 0x3b, 0xef, 0x7b, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x68, 0x2d, 0x09, 0x00, 0x58, 0xf3, 0x7c, 0x0b, 0x00, 0x00, 0x84, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x51, 0x0a, 0x40, 0xc8, }; int init_mppc_suite(void) { return 0; } int clean_mppc_suite(void) { return 0; } int add_mppc_suite(void) { add_test_suite(mppc); add_test_function(mppc); return 0; } void test_mppc(void) { rdpRdp rdp; struct rdp_mppc rmppc; uint32_t roff; uint32_t rlen; long int dur; struct timeval start_time; struct timeval end_time; rdp.mppc = &rmppc; rdp.mppc->history_buf = calloc(1, RDP6_HISTORY_BUF_SIZE); CU_ASSERT(rdp.mppc->history_buf != NULL) rdp.mppc->history_ptr = rdp.mppc->history_buf; /* save starting time */ gettimeofday(&start_time, NULL); /* uncompress data */ CU_ASSERT(decompress_rdp_5(&rdp, compressed_rd5, sizeof(compressed_rd5), PACKET_COMPRESSED, &roff, &rlen) == true); /* get end time */ gettimeofday(&end_time, NULL); CU_ASSERT(memcmp(decompressed_rd5, rdp.mppc->history_buf, sizeof(decompressed_rd5)) == 0); free(rdp.mppc->history_buf); /* print time taken */ dur = ((end_time.tv_sec - start_time.tv_sec) * 1000000) + (end_time.tv_usec - start_time.tv_usec); //printf("test_mppc: decompressed data in %ld micro seconds\n", dur); } FreeRDP-1.0.2/cunit/test_mppc.h000066400000000000000000000015431207112532300162310ustar00rootroot00000000000000/** * FreeRDP: A Remote Desktop Protocol Client * Microsoft Point to Point compression (MPPC) Unit Tests * * Copyright 2011 Laxmikant Rashinkar * * 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. */ #include "test_freerdp.h" int init_mppc_suite(void); int clean_mppc_suite(void); int add_mppc_suite(void); void test_mppc(void); FreeRDP-1.0.2/cunit/test_orders.c000066400000000000000000000551451207112532300165720ustar00rootroot00000000000000/** * FreeRDP: A Remote Desktop Protocol Client * Drawing Orders Unit Tests * * Copyright 2011 Marc-Andre Moreau * * 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. */ #include #include #include #include "test_orders.h" #include "libfreerdp-core/orders.h" #include "libfreerdp-core/update.h" ORDER_INFO* orderInfo; int init_orders_suite(void) { orderInfo = (ORDER_INFO*) malloc(sizeof(ORDER_INFO)); return 0; } int clean_orders_suite(void) { free(orderInfo); return 0; } int add_orders_suite(void) { add_test_suite(orders); add_test_function(read_dstblt_order); add_test_function(read_patblt_order); add_test_function(read_scrblt_order); add_test_function(read_opaque_rect_order); add_test_function(read_draw_nine_grid_order); add_test_function(read_multi_opaque_rect_order); add_test_function(read_line_to_order); add_test_function(read_polyline_order); add_test_function(read_glyph_index_order); add_test_function(read_fast_index_order); add_test_function(read_fast_glyph_order); add_test_function(read_polygon_cb_order); add_test_function(read_cache_bitmap_order); add_test_function(read_cache_bitmap_v2_order); add_test_function(read_cache_bitmap_v3_order); add_test_function(read_cache_brush_order); add_test_function(read_create_offscreen_bitmap_order); add_test_function(read_switch_surface_order); add_test_function(update_recv_orders); return 0; } uint8 dstblt_order[] = "\x48\x00\x37\x01"; void test_read_dstblt_order(void) { STREAM _s, *s; DSTBLT_ORDER dstblt; s = &_s; s->p = s->data = dstblt_order; memset(orderInfo, 0, sizeof(ORDER_INFO)); orderInfo->fieldFlags = 0x0C; memset(&dstblt, 0, sizeof(DSTBLT_ORDER)); update_read_dstblt_order(s, orderInfo, &dstblt); CU_ASSERT(dstblt.nLeftRect == 0); CU_ASSERT(dstblt.nTopRect == 0); CU_ASSERT(dstblt.nWidth == 72); CU_ASSERT(dstblt.nHeight == 311); CU_ASSERT(dstblt.bRop == 0); CU_ASSERT(stream_get_length(s) == (sizeof(dstblt_order) - 1)); } uint8 patblt_order[] = "\x1a\x00\xc3\x01\x0d\x00\x0d\x00\xf0\xff\xff\x00\x5b\xef\x00\x81"; void test_read_patblt_order(void) { STREAM _s, *s; PATBLT_ORDER patblt; s = &_s; s->p = s->data = patblt_order; memset(orderInfo, 0, sizeof(ORDER_INFO)); orderInfo->fieldFlags = 0x027F; memset(&patblt, 0, sizeof(PATBLT_ORDER)); update_read_patblt_order(s, orderInfo, &patblt); CU_ASSERT(patblt.nLeftRect == 26); CU_ASSERT(patblt.nTopRect == 451); CU_ASSERT(patblt.nWidth == 13); CU_ASSERT(patblt.nHeight == 13); CU_ASSERT(patblt.bRop == 240); CU_ASSERT(patblt.backColor == 0x00FFFF); CU_ASSERT(patblt.foreColor == 0x00EF5B); CU_ASSERT(patblt.brush.x == 0); CU_ASSERT(patblt.brush.y == 0); CU_ASSERT(patblt.brush.style == (BMF_1BPP | CACHED_BRUSH)); CU_ASSERT(stream_get_length(s) == (sizeof(patblt_order) - 1)); } uint8 scrblt_order[] = "\x07\x00\xa1\x01\xf1\x00\xcc\x2f\x01\x8e\x00"; void test_read_scrblt_order(void) { STREAM _s, *s; SCRBLT_ORDER scrblt; s = &_s; s->p = s->data = scrblt_order; memset(orderInfo, 0, sizeof(ORDER_INFO)); orderInfo->fieldFlags = 0x7D; memset(&scrblt, 0, sizeof(SCRBLT_ORDER)); update_read_scrblt_order(s, orderInfo, &scrblt); CU_ASSERT(scrblt.nLeftRect == 7); CU_ASSERT(scrblt.nTopRect == 0); CU_ASSERT(scrblt.nWidth == 417); CU_ASSERT(scrblt.nHeight == 241); CU_ASSERT(scrblt.bRop == 204); CU_ASSERT(scrblt.nXSrc == 303); CU_ASSERT(scrblt.nYSrc == 142); CU_ASSERT(stream_get_length(s) == (sizeof(scrblt_order) - 1)); } uint8 opaque_rect_order[] = "\x00\x04\x00\x03\x73\x02\x06"; void test_read_opaque_rect_order(void) { STREAM _s, *s; OPAQUE_RECT_ORDER opaque_rect; s = &_s; s->p = s->data = opaque_rect_order; memset(orderInfo, 0, sizeof(ORDER_INFO)); orderInfo->fieldFlags = 0x7C; memset(&opaque_rect, 0, sizeof(OPAQUE_RECT_ORDER)); update_read_opaque_rect_order(s, orderInfo, &opaque_rect); CU_ASSERT(opaque_rect.nLeftRect == 0); CU_ASSERT(opaque_rect.nTopRect == 0); CU_ASSERT(opaque_rect.nWidth == 1024); CU_ASSERT(opaque_rect.nHeight == 768); CU_ASSERT(opaque_rect.color == 0x00060273); CU_ASSERT(stream_get_length(s) == (sizeof(opaque_rect_order) - 1)); } uint8 draw_nine_grid_order[] = "\xfb\xf9\x0d\x00"; void test_read_draw_nine_grid_order(void) { STREAM _s, *s; DRAW_NINE_GRID_ORDER draw_nine_grid; s = &_s; s->p = s->data = draw_nine_grid_order; memset(orderInfo, 0, sizeof(ORDER_INFO)); orderInfo->fieldFlags = 0x1C; orderInfo->deltaCoordinates = true; memset(&draw_nine_grid, 0, sizeof(DRAW_NINE_GRID_ORDER)); draw_nine_grid.srcRight = 38; draw_nine_grid.srcBottom = 40; update_read_draw_nine_grid_order(s, orderInfo, &draw_nine_grid); CU_ASSERT(draw_nine_grid.srcLeft == 0); CU_ASSERT(draw_nine_grid.srcTop == 0); CU_ASSERT(draw_nine_grid.srcRight == 33); CU_ASSERT(draw_nine_grid.srcBottom == 33); CU_ASSERT(draw_nine_grid.bitmapId == 13); CU_ASSERT(stream_get_length(s) == (sizeof(draw_nine_grid_order) - 1)); } uint8 multi_opaque_rect_order[] = "\x87\x01\x1c\x01\xf1\x00\x12\x00\x5c\xef\x04\x16\x00\x08\x40\x81" "\x87\x81\x1c\x80\xf1\x01\x01\x01\x10\x80\xf0\x01\x10\xff\x10\x10" "\x80\xf1\x01"; void test_read_multi_opaque_rect_order(void) { STREAM _s, *s; MULTI_OPAQUE_RECT_ORDER multi_opaque_rect; s = &_s; s->p = s->data = multi_opaque_rect_order; memset(orderInfo, 0, sizeof(ORDER_INFO)); orderInfo->fieldFlags = 0x01BF; memset(&multi_opaque_rect, 0, sizeof(MULTI_OPAQUE_RECT_ORDER)); update_read_multi_opaque_rect_order(s, orderInfo, &multi_opaque_rect); CU_ASSERT(multi_opaque_rect.nLeftRect == 391); CU_ASSERT(multi_opaque_rect.nTopRect == 284); CU_ASSERT(multi_opaque_rect.nWidth == 241); CU_ASSERT(multi_opaque_rect.nHeight == 18); CU_ASSERT(multi_opaque_rect.color == 0x0000EF5C); CU_ASSERT(multi_opaque_rect.cbData == 22); CU_ASSERT(multi_opaque_rect.numRectangles == 4); CU_ASSERT(multi_opaque_rect.rectangles[1].left == 391); CU_ASSERT(multi_opaque_rect.rectangles[1].top == 284); CU_ASSERT(multi_opaque_rect.rectangles[1].width == 241); CU_ASSERT(multi_opaque_rect.rectangles[1].height == 1); CU_ASSERT(multi_opaque_rect.rectangles[2].left == 391); CU_ASSERT(multi_opaque_rect.rectangles[2].top == 285); CU_ASSERT(multi_opaque_rect.rectangles[2].width == 1); CU_ASSERT(multi_opaque_rect.rectangles[2].height == 16); CU_ASSERT(multi_opaque_rect.rectangles[3].left == 631); CU_ASSERT(multi_opaque_rect.rectangles[3].top == 285); CU_ASSERT(multi_opaque_rect.rectangles[3].width == 1); CU_ASSERT(multi_opaque_rect.rectangles[3].height == 16); CU_ASSERT(multi_opaque_rect.rectangles[4].left == 391); CU_ASSERT(multi_opaque_rect.rectangles[4].top == 301); CU_ASSERT(multi_opaque_rect.rectangles[4].width == 241); CU_ASSERT(multi_opaque_rect.rectangles[4].height == 1); CU_ASSERT(stream_get_length(s) == (sizeof(multi_opaque_rect_order) - 1)); } uint8 line_to_order[] = "\x03\xb1\x0e\xa6\x5b\xef\x00"; void test_read_line_to_order(void) { STREAM _s, *s; LINE_TO_ORDER line_to; s = &_s; s->p = s->data = line_to_order; memset(orderInfo, 0, sizeof(ORDER_INFO)); orderInfo->fieldFlags = 0x021E; orderInfo->deltaCoordinates = true; memset(&line_to, 0, sizeof(LINE_TO_ORDER)); line_to.nXStart = 826; line_to.nYStart = 350; line_to.nXEnd = 829; line_to.nYEnd = 347; update_read_line_to_order(s, orderInfo, &line_to); CU_ASSERT(line_to.nXStart == 829); CU_ASSERT(line_to.nYStart == 271); CU_ASSERT(line_to.nXEnd == 843); CU_ASSERT(line_to.nYEnd == 257); CU_ASSERT(line_to.backColor == 0); CU_ASSERT(line_to.bRop2 == 0); CU_ASSERT(line_to.penStyle == 0); CU_ASSERT(line_to.penWidth == 0); CU_ASSERT(line_to.penColor == 0x00EF5B); CU_ASSERT(stream_get_length(s) == (sizeof(line_to_order) - 1)); } uint8 polyline_order[] = "\xf8\x01\xb8\x02\x00\xc0\x00\x20\x6c\x00\x00\x00\x00\x00\x04\x00" "\x00\xff\x7e\x76\xff\x41\x6c\xff\x24\x62\xff\x2b\x59\xff\x55\x51" "\xff\x9c\x49\x73\x43\x80\x4d\xff\xbe\x80\x99\xff\xba\x80\xcd\xff" "\xb7\x80\xde\xff\xb6\x80\xca\xff\xb6\x80\x96\xff\xb7\x80\x48\xff" "\xba\x6f\xff\xbe\xff\x97\x43\xff\x52\x4a\xff\x2b\x51\xff\x24\x59" "\xff\x44\x63\xff\x81\x6c\x56\x76\x2f\x80\x82\x0a\x80\xbf\x14\x80" "\xdd\x1e\x80\xd4\x27\x80\xab\x2f\x80\x64\x37\x0d\x3d\xff\xb3\x80" "\x42\xff\x67\x80\x46"; void test_read_polyline_order(void) { STREAM _s, *s; POLYLINE_ORDER polyline; s = &_s; s->p = s->data = polyline_order; memset(orderInfo, 0, sizeof(ORDER_INFO)); orderInfo->fieldFlags = 0x73; memset(&polyline, 0, sizeof(POLYLINE_ORDER)); update_read_polyline_order(s, orderInfo, &polyline); CU_ASSERT(polyline.xStart == 504); CU_ASSERT(polyline.yStart == 696); CU_ASSERT(polyline.bRop2 == 0); CU_ASSERT(polyline.penColor == 0x0000C000); CU_ASSERT(polyline.numPoints == 32); CU_ASSERT(polyline.cbData == 108); CU_ASSERT(polyline.points[0].x == -130); CU_ASSERT(polyline.points[1].x == -191); CU_ASSERT(polyline.points[2].x == -220); CU_ASSERT(polyline.points[3].x == -213); CU_ASSERT(polyline.points[4].x == -171); CU_ASSERT(polyline.points[5].x == -100); CU_ASSERT(polyline.points[6].x == -13); CU_ASSERT(polyline.points[7].x == 77); CU_ASSERT(polyline.points[8].x == 153); CU_ASSERT(polyline.points[9].x == 205); CU_ASSERT(polyline.points[10].x == 222); CU_ASSERT(polyline.points[11].x == 202); CU_ASSERT(polyline.points[12].x == 150); CU_ASSERT(polyline.points[13].x == 72); CU_ASSERT(polyline.points[14].x == -17); CU_ASSERT(polyline.points[15].x == -105); CU_ASSERT(polyline.points[16].x == -174); CU_ASSERT(polyline.points[17].x == -213); CU_ASSERT(polyline.points[18].x == -220); CU_ASSERT(polyline.points[19].x == -188); CU_ASSERT(polyline.points[20].x == -127); CU_ASSERT(polyline.points[21].x == -42); CU_ASSERT(polyline.points[22].x == 47); CU_ASSERT(polyline.points[23].x == 130); CU_ASSERT(polyline.points[24].x == 191); CU_ASSERT(polyline.points[25].x == 221); CU_ASSERT(polyline.points[26].x == 212); CU_ASSERT(polyline.points[27].x == 171); CU_ASSERT(polyline.points[28].x == 100); CU_ASSERT(polyline.points[29].x == 13); CU_ASSERT(polyline.points[30].x == -77); CU_ASSERT(polyline.points[31].x == -153); CU_ASSERT(polyline.points[32].x == 0); CU_ASSERT(stream_get_length(s) == (sizeof(polyline_order) - 1)); } uint8 glyph_index_order_1[] = "\x6a\x02\x27\x38\x00\x39\x07\x3a\x06\x3b\x07\x3c\x06\x3d\x06\x18" "\x04\x1f\x06\x17\x02\x14\x04\x1b\x06\x19\x06\x45\x05\x18\x06\x1f" "\x06\x1f\x02\x14\x02\x46\x06\xff\x15\x24"; uint8 glyph_index_order_2[] = "\x00\xff\xff\xff\x0c\x02\x6e\x01\x4d\x02\x7b\x01\x09\x02\x6e\x01" "\xf6\x02\x7b\x01\x0c\x02\x79\x01\x03\xfe\x04\x00"; void test_read_glyph_index_order(void) { STREAM _s, *s; GLYPH_INDEX_ORDER glyph_index; s = &_s; s->p = s->data = glyph_index_order_1; memset(orderInfo, 0, sizeof(ORDER_INFO)); orderInfo->fieldFlags = 0x200100; orderInfo->deltaCoordinates = true; memset(&glyph_index, 0, sizeof(GLYPH_INDEX_ORDER)); update_read_glyph_index_order(s, orderInfo, &glyph_index); CU_ASSERT(glyph_index.bkRight == 618); CU_ASSERT(stream_get_length(s) == (sizeof(glyph_index_order_1) - 1)); s->p = s->data = glyph_index_order_2; memset(orderInfo, 0, sizeof(ORDER_INFO)); orderInfo->fieldFlags = 0x383FE8; orderInfo->deltaCoordinates = true; memset(&glyph_index, 0, sizeof(GLYPH_INDEX_ORDER)); update_read_glyph_index_order(s, orderInfo, &glyph_index); CU_ASSERT(glyph_index.fOpRedundant == 0); CU_ASSERT(glyph_index.foreColor == 0x00FFFFFF); CU_ASSERT(glyph_index.bkLeft == 524); CU_ASSERT(glyph_index.bkTop == 366); CU_ASSERT(glyph_index.bkRight == 589); CU_ASSERT(glyph_index.bkBottom == 379); CU_ASSERT(glyph_index.opLeft == 521); CU_ASSERT(glyph_index.opTop == 366); CU_ASSERT(glyph_index.opRight == 758); CU_ASSERT(glyph_index.opBottom == 379); CU_ASSERT(glyph_index.x == 524); CU_ASSERT(glyph_index.y == 377); CU_ASSERT(stream_get_length(s) == (sizeof(glyph_index_order_2) - 1)); } uint8 fast_index_order[] = "\x07\x00\x03\xff\xff\x00\x74\x3b\x00\x0e\x00\x71\x00\x42\x00\x7e" "\x00\x00\x80\x7c\x00\x15\x00\x00\x01\x06\x02\x04\x03\x08\x05\x09" "\x06\x06\x06\x06\x07\x06\x08\x02\xff\x00\x12"; void test_read_fast_index_order(void) { STREAM _s, *s; FAST_INDEX_ORDER fast_index; s = &_s; s->p = s->data = fast_index_order; memset(orderInfo, 0, sizeof(ORDER_INFO)); orderInfo->fieldFlags = 0x70FF; memset(&fast_index, 0, sizeof(FAST_INDEX_ORDER)); update_read_fast_index_order(s, orderInfo, &fast_index); CU_ASSERT(fast_index.cacheId == 7); CU_ASSERT(fast_index.flAccel == 3); CU_ASSERT(fast_index.ulCharInc == 0); CU_ASSERT(fast_index.backColor == 0x0000FFFF); CU_ASSERT(fast_index.foreColor == 0x00003B74); CU_ASSERT(fast_index.bkLeft == 14); CU_ASSERT(fast_index.bkTop == 113); CU_ASSERT(fast_index.bkRight == 66); CU_ASSERT(fast_index.bkBottom == 126); CU_ASSERT(fast_index.opLeft == 0); CU_ASSERT(fast_index.opTop == 0); CU_ASSERT(fast_index.opRight == 0); CU_ASSERT(fast_index.opBottom == 0); CU_ASSERT(fast_index.x == -32768); CU_ASSERT(fast_index.y == 124); CU_ASSERT(stream_get_length(s) == (sizeof(fast_index_order) - 1)); } uint8 fast_glyph_order[] = "\x06\x00\x03\xff\xff\x00\x8b\x00\xb1\x00\x93\x00\xbe\x00\x0d\x00" "\xfe\x7f\x00\x80\x00\x80\xbb\x00\x13\x00\x01\x4a\x06\x0a\x80\x80" "\x80\xb8\xc4\x84\x84\x84\x84\x84\x00\x00\x68\x00"; void test_read_fast_glyph_order(void) { STREAM _s, *s; FAST_GLYPH_ORDER fast_glyph; s = &_s; s->p = s->data = fast_glyph_order; memset(orderInfo, 0, sizeof(ORDER_INFO)); orderInfo->fieldFlags = 0x7EFB; memset(&fast_glyph, 0, sizeof(FAST_GLYPH_ORDER)); update_read_fast_glyph_order(s, orderInfo, &fast_glyph); CU_ASSERT(fast_glyph.backColor == 0); CU_ASSERT(fast_glyph.foreColor == 0x0000FFFF); CU_ASSERT(fast_glyph.bkLeft == 139); CU_ASSERT(fast_glyph.bkTop == 177); CU_ASSERT(fast_glyph.bkRight == 147); CU_ASSERT(fast_glyph.bkBottom == 190); CU_ASSERT(fast_glyph.opLeft == 0); CU_ASSERT(fast_glyph.opTop == 13); CU_ASSERT(fast_glyph.opRight == 32766); CU_ASSERT(fast_glyph.opBottom == -32768); CU_ASSERT(fast_glyph.x == -32768); CU_ASSERT(fast_glyph.y == 187); CU_ASSERT(stream_get_length(s) == (sizeof(fast_glyph_order) - 1)); } uint8 polygon_cb_order[] = "\xea\x00\x46\x01\x0d\x01\x08\x00\x00\x04\x03\x81\x08\x03\x05\x88" "\x09\x26\x09\x77"; void test_read_polygon_cb_order(void) { STREAM _s, *s; POLYGON_CB_ORDER polygon_cb; s = &_s; s->p = s->data = polygon_cb_order; memset(orderInfo, 0, sizeof(ORDER_INFO)); orderInfo->fieldFlags = 0x1BEF; memset(&polygon_cb, 0, sizeof(POLYGON_CB_ORDER)); update_read_polygon_cb_order(s, orderInfo, &polygon_cb); CU_ASSERT(polygon_cb.xStart == 234); CU_ASSERT(polygon_cb.yStart == 326); CU_ASSERT(polygon_cb.bRop2 == 0x0D); CU_ASSERT(polygon_cb.fillMode == 1); CU_ASSERT(polygon_cb.backColor == 0); CU_ASSERT(polygon_cb.foreColor == 0x00000008); CU_ASSERT(polygon_cb.brush.x == 4); CU_ASSERT(polygon_cb.brush.y == 3); CU_ASSERT(polygon_cb.brush.style == 0x81); CU_ASSERT(polygon_cb.nDeltaEntries == 3); CU_ASSERT(polygon_cb.cbData == 5); CU_ASSERT(stream_get_length(s) == (sizeof(polygon_cb_order) - 1)); } uint8 cache_bitmap_order[] = "\x00\x00\x10\x01\x08\x01\x00\x00\x00\x10"; void test_read_cache_bitmap_order(void) { STREAM _s, *s; uint16 extraFlags; CACHE_BITMAP_ORDER cache_bitmap; s = &_s; extraFlags = 0x0400; s->p = s->data = cache_bitmap_order; memset(&cache_bitmap, 0, sizeof(CACHE_BITMAP_ORDER)); update_read_cache_bitmap_order(s, &cache_bitmap, true, extraFlags); CU_ASSERT(cache_bitmap.cacheId == 0); CU_ASSERT(cache_bitmap.bitmapWidth == 16); CU_ASSERT(cache_bitmap.bitmapHeight == 1); CU_ASSERT(cache_bitmap.bitmapBpp == 8); CU_ASSERT(cache_bitmap.bitmapLength == 1); CU_ASSERT(cache_bitmap.cacheIndex == 0); CU_ASSERT(stream_get_length(s) == (sizeof(cache_bitmap_order) - 1)); } uint8 cache_bitmap_v2_order[] = "\x20\x40\xdc\xff\xff\x85\xff\xff\x99\xd6\x99\xd6\x99\xd6\x99\xd6" "\x06\x8b\x99\xd6\x99\xd6\x99\xd6\x10\x84\x08\x42\x08\x42\x10\x84" "\x99\xd6\x99\xd6\x99\xd6\x99\xd6\x06\x84\x99\xd6\x99\xd6\x99\xd6" "\xff\xff\x16\x69\x99\xd6\x06\x69\x99\xd6\x04\xcc\x89\x52\x03\x6e" "\xff\xff\x02\x6e\x08\x42\x01\x70\x08\x42\x71\xff\xff\xce\x18\xc6" "\x01\x81\x08\x42\xce\x66\x29\x02\xcd\x89\x52\x03\x88\x10\x84\x99" "\xd6\x99\xd6\x99\xd6\x00\x00\x00\x00\x00\x00\x00\x00\xd8\x99\xd6" "\x03\xf8\x01\x00\x00\x00\x00\xf0\x66\x99\xd6\x05\x6a\x99\xd6\x00" "\xc4\xcc\x89\x52\x03\x6e\xff\xff\x02\x6e\x08\x42\x01\x70\x08\x42" "\x71\xff\xff\xce\x18\xc6\x01\x81\x08\x42\xce\x66\x29\x02\xcd\x89" "\x52\x03\x00\x04\xd6\x99\xd6\xc3\x80\x61\x00\xa5\x80\x40\xec\x52" "\x00\x5a\x00\x2d\x00\x24\x00\x12\x00\x24\x00\x12\x00\x5a\x00\x2d" "\x00\xa5\x80\x52\x00\xc3\x80\x61\x00\x00\x00\x00\x00\xcc\x89\x52" "\x03\x6e\xff\xff\x02\xcb\x18\xc6\x84\x08\x42\x08\x42\x08\x42\xff" "\xff"; void test_read_cache_bitmap_v2_order(void) { STREAM _s, *s; uint16 extraFlags; CACHE_BITMAP_V2_ORDER cache_bitmap_v2; s = &_s; extraFlags = 0x0CA1; s->p = s->data = cache_bitmap_v2_order; memset(&cache_bitmap_v2, 0, sizeof(CACHE_BITMAP_V2_ORDER)); update_read_cache_bitmap_v2_order(s, &cache_bitmap_v2, true, extraFlags); CU_ASSERT(cache_bitmap_v2.cacheId == 1); CU_ASSERT(cache_bitmap_v2.bitmapBpp == 16); CU_ASSERT(cache_bitmap_v2.flags == 0x19); CU_ASSERT(cache_bitmap_v2.bitmapWidth == 32); CU_ASSERT(cache_bitmap_v2.bitmapHeight == 32); CU_ASSERT(cache_bitmap_v2.bitmapLength == 220); CU_ASSERT(cache_bitmap_v2.cacheIndex == 32767); CU_ASSERT(stream_get_length(s) == (sizeof(cache_bitmap_v2_order) - 1)); } uint8 cache_bitmap_v3_order[] = "\xff\x7f\x35\x50\xec\xbc\x74\x52\x65\xb7\x20\x00\x00\x00\x05\x00" "\x02\x00\x28\x00\x00\x00\x5b\x4f\x45\xff\x5b\x4f\x45\xff\x5b\x4f" "\x45\xff\x5b\x4f\x45\xff\x5b\x4f\x45\xff\x5b\x50\x45\xff\x5b\x50" "\x45\xff\x5b\x50\x45\xff\x5b\x50\x45\xff\x5b\x50\x45\xff"; void test_read_cache_bitmap_v3_order(void) { STREAM _s, *s; uint16 extraFlags; CACHE_BITMAP_V3_ORDER cache_bitmap_v3; s = &_s; extraFlags = 0x0C30; s->p = s->data = cache_bitmap_v3_order; memset(&cache_bitmap_v3, 0, sizeof(CACHE_BITMAP_V3_ORDER)); update_read_cache_bitmap_v3_order(s, &cache_bitmap_v3, true, extraFlags); CU_ASSERT(cache_bitmap_v3.cacheIndex == 32767); CU_ASSERT(cache_bitmap_v3.key1 == 0xBCEC5035); CU_ASSERT(cache_bitmap_v3.key2 == 0xB7655274); CU_ASSERT(cache_bitmap_v3.bpp == 32); CU_ASSERT(cache_bitmap_v3.bitmapData.bpp == 32); CU_ASSERT(cache_bitmap_v3.bitmapData.codecID == 0); CU_ASSERT(cache_bitmap_v3.bitmapData.width == 5); CU_ASSERT(cache_bitmap_v3.bitmapData.height == 2); CU_ASSERT(cache_bitmap_v3.bitmapData.length == 40); CU_ASSERT(stream_get_length(s) == (sizeof(cache_bitmap_v3_order) - 1)); } uint8 cache_brush_order[] = "\x00\x01\x08\x08\x81\x08\xaa\x55\xaa\x55\xaa\x55\xaa\x55"; void test_read_cache_brush_order(void) { STREAM _s, *s; CACHE_BRUSH_ORDER cache_brush; s = &_s; s->p = s->data = cache_brush_order; memset(&cache_brush, 0, sizeof(CACHE_BRUSH_ORDER)); update_read_cache_brush_order(s, &cache_brush, 0); CU_ASSERT(cache_brush.index == 0); CU_ASSERT(cache_brush.bpp == 1); CU_ASSERT(cache_brush.cx == 8); CU_ASSERT(cache_brush.cy == 8); CU_ASSERT(cache_brush.style == 0x81); CU_ASSERT(cache_brush.length == 8); CU_ASSERT(stream_get_length(s) == (sizeof(cache_brush_order) - 1)); } uint8 create_offscreen_bitmap_order[] = "\x00\x80\x60\x01\x10\x00\x01\x00\x02\x00"; void test_read_create_offscreen_bitmap_order(void) { STREAM _s, *s; OFFSCREEN_DELETE_LIST* deleteList; CREATE_OFFSCREEN_BITMAP_ORDER create_offscreen_bitmap; s = &_s; s->p = s->data = create_offscreen_bitmap_order; memset(&create_offscreen_bitmap, 0, sizeof(CREATE_OFFSCREEN_BITMAP_ORDER)); deleteList = &(create_offscreen_bitmap.deleteList); deleteList->cIndices = 0; deleteList->sIndices = 16; deleteList->indices = malloc(sizeof(uint16) * deleteList->sIndices); update_read_create_offscreen_bitmap_order(s, &create_offscreen_bitmap); CU_ASSERT(create_offscreen_bitmap.id == 0); CU_ASSERT(create_offscreen_bitmap.cx == 352); CU_ASSERT(create_offscreen_bitmap.cy == 16); CU_ASSERT(create_offscreen_bitmap.deleteList.cIndices == 1); CU_ASSERT(stream_get_length(s) == (sizeof(create_offscreen_bitmap_order) - 1)); } uint8 switch_surface_order[] = "\xff\xff"; void test_read_switch_surface_order(void) { STREAM _s, *s; SWITCH_SURFACE_ORDER switch_surface; s = &_s; s->p = s->data = switch_surface_order; memset(&switch_surface, 0, sizeof(SWITCH_SURFACE_ORDER)); update_read_switch_surface_order(s, &switch_surface); CU_ASSERT(switch_surface.bitmapId == 0xFFFF); CU_ASSERT(stream_get_length(s) == (sizeof(switch_surface_order) - 1)); } int opaque_rect_count; int polyline_count; int patblt_count; uint8 orders_update_1[] = "\x00\x00\x33\xd0\x07\x00\x80\xba\x0d\x0a\x7f\x1e\x2c\x4d\x00\x36" "\x02\xd3\x00\x47\x00\x4d\x00\xf0\x01\x87\x00\xc2\xdc\xff\x05\x7f" "\x0f\x67\x01\x90\x01\x8e\x01\xa5\x01\x67\x01\x90\x01\x28\x00\x16" "\x00\xf0\xf0\xf0\x15\x0f\xf0\x2d\x01\x19\xfe\x2d\x01\xec\xfd\x0d" "\x16\x77\xf0\xff\xff\x01\x01\xa8\x01\x90\x01\x0d\xf0\xf0\xf0\x04" "\x05\x66\x6b\x14\x15\x6c\x1d\x0a\x0f\xd0\x16\x64\x01\x15\xff\x50" "\x03\x15\x0f\xf0\x65\x01\x15\xfe\x65\x01\xb0\xfd\x1d\x16\x01\xf0" "\xff\xff\x01\x01\x7a"; uint8 orders_update_2[] = "\x00\x00\x45\x62\x03\x00\x93\x14\x55\x01\x50\xff\xff\xff\x55\x01" "\x50\x01\x01\x01\x55\x01\x50\xff\xff\xff\x16\x00\x17\x00\xea\x03" "\xea\x03\x02\x00\x85\x02\x16\x00\x02\x00\x00\x00\x03\x00\x14\xb2"; void test_opaque_rect(rdpContext* context, OPAQUE_RECT_ORDER* opaque_rect) { opaque_rect_count++; } void test_polyline(rdpContext* context, POLYLINE_ORDER* polyline) { polyline_count++; } void test_patblt(rdpContext* context, PATBLT_ORDER* patblt) { patblt_count++; } void test_update_recv_orders(void) { rdpRdp* rdp; STREAM _s, *s; rdpUpdate* update; s = &_s; rdp = rdp_new(NULL); update = update_new(rdp); update->context = malloc(sizeof(rdpContext)); update->context->rdp = rdp; opaque_rect_count = 0; polyline_count = 0; patblt_count = 0; update->primary->OpaqueRect = test_opaque_rect; update->primary->Polyline = test_polyline; update->primary->PatBlt = test_patblt; s->p = s->data = orders_update_1; s->size = sizeof(orders_update_1); update_recv(update, s); CU_ASSERT(opaque_rect_count == 5); CU_ASSERT(polyline_count == 2); update->primary->order_info.orderType = ORDER_TYPE_PATBLT; s->p = s->data = orders_update_2; s->size = sizeof(orders_update_2); update_recv(update, s); CU_ASSERT(patblt_count == 3); free(update->context); } FreeRDP-1.0.2/cunit/test_orders.h000066400000000000000000000030701207112532300165650ustar00rootroot00000000000000/** * FreeRDP: A Remote Desktop Protocol Client * Drawing Orders Unit Tests * * Copyright 2011 Marc-Andre Moreau * * 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. */ #include "test_freerdp.h" int init_orders_suite(void); int clean_orders_suite(void); int add_orders_suite(void); void test_read_dstblt_order(void); void test_read_patblt_order(void); void test_read_scrblt_order(void); void test_read_opaque_rect_order(void); void test_read_draw_nine_grid_order(void); void test_read_multi_opaque_rect_order(void); void test_read_line_to_order(void); void test_read_polyline_order(void); void test_read_glyph_index_order(void); void test_read_fast_index_order(void); void test_read_fast_glyph_order(void); void test_read_polygon_cb_order(void); void test_read_cache_bitmap_order(void); void test_read_cache_bitmap_v2_order(void); void test_read_cache_bitmap_v3_order(void); void test_read_cache_brush_order(void); void test_read_create_offscreen_bitmap_order(void); void test_read_switch_surface_order(void); void test_update_recv_orders(void); FreeRDP-1.0.2/cunit/test_pcap.c000066400000000000000000000046541207112532300162160ustar00rootroot00000000000000/** * FreeRDP: A Remote Desktop Protocol Client * pcap File Format Unit Tests * * Copyright 2011 Marc-Andre Moreau * * 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. */ #include #include #include #include "test_pcap.h" int init_pcap_suite(void) { return 0; } int clean_pcap_suite(void) { return 0; } int add_pcap_suite(void) { add_test_suite(pcap); add_test_function(pcap); return 0; } uint8 test_packet_1[16] = "\xAA\xAA\xAA\xAA\xAA\xAA\xAA\xAA\xAA\xAA\xAA\xAA\xAA\xAA\xAA\xAA"; uint8 test_packet_2[32] = "\xBB\xBB\xBB\xBB\xBB\xBB\xBB\xBB\xBB\xBB\xBB\xBB\xBB\xBB\xBB\xBB" "\xBB\xBB\xBB\xBB\xBB\xBB\xBB\xBB\xBB\xBB\xBB\xBB\xBB\xBB\xBB\xBB"; uint8 test_packet_3[64] = "\xCC\xCC\xCC\xCC\xCC\xCC\xCC\xCC\xCC\xCC\xCC\xCC\xCC\xCC\xCC\xCC" "\xCC\xCC\xCC\xCC\xCC\xCC\xCC\xCC\xCC\xCC\xCC\xCC\xCC\xCC\xCC\xCC" "\xCC\xCC\xCC\xCC\xCC\xCC\xCC\xCC\xCC\xCC\xCC\xCC\xCC\xCC\xCC\xCC" "\xCC\xCC\xCC\xCC\xCC\xCC\xCC\xCC\xCC\xCC\xCC\xCC\xCC\xCC\xCC\xCC"; typedef struct { void* data; uint32 length; } test_packet; void test_pcap(void) { rdpPcap* pcap; pcap_record record; test_packet packets[3]; packets[0].data = test_packet_1; packets[0].length = sizeof(test_packet_1); packets[1].data = test_packet_2; packets[1].length = sizeof(test_packet_2); packets[2].data = test_packet_3; packets[2].length = sizeof(test_packet_3); pcap = pcap_open("/tmp/test.pcap", true); pcap_add_record(pcap, test_packet_1, sizeof(test_packet_1)); pcap_flush(pcap); pcap_add_record(pcap, test_packet_2, sizeof(test_packet_2)); pcap_flush(pcap); pcap_add_record(pcap, test_packet_3, sizeof(test_packet_3)); pcap_close(pcap); pcap = pcap_open("/tmp/test.pcap", false); int i = 0; while (pcap_has_next_record(pcap)) { pcap_get_next_record(pcap, &record); CU_ASSERT(record.length == packets[i].length) i++; } CU_ASSERT(i == 3); pcap_close(pcap); } FreeRDP-1.0.2/cunit/test_pcap.h000066400000000000000000000015121207112532300162110ustar00rootroot00000000000000/** * FreeRDP: A Remote Desktop Protocol Client * pcap File Format Unit Tests * * Copyright 2011 Marc-Andre Moreau * * 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. */ #include "test_freerdp.h" int init_pcap_suite(void); int clean_pcap_suite(void); int add_pcap_suite(void); void test_pcap(void); FreeRDP-1.0.2/cunit/test_per.c000066400000000000000000000031211207112532300160450ustar00rootroot00000000000000/** * FreeRDP: A Remote Desktop Protocol Client * Packed Encoding Rules (PER) Unit Tests * * Copyright 2011 Marc-Andre Moreau * * 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. */ #include #include #include #include "test_per.h" #include "libfreerdp-core/per.h" int init_per_suite(void) { return 0; } int clean_per_suite(void) { return 0; } int add_per_suite(void) { add_test_suite(per); add_test_function(per_write_length); add_test_function(per_write_object_identifier); return 0; } uint8 per_length_expected[2] = "\x81\x2A"; void test_per_write_length(void) { STREAM* s = stream_new(2); per_write_length(s, 298); ASSERT_STREAM(s, (uint8*) per_length_expected, sizeof(per_length_expected)); } uint8 per_oid[6] = { 0, 0, 20, 124, 0, 1 }; uint8 per_oid_expected[6] = "\x05\x00\x14\x7C\x00\x01"; void test_per_write_object_identifier(void) { STREAM* s = stream_new(6); per_write_object_identifier(s, per_oid); ASSERT_STREAM(s, (uint8*) per_oid_expected, sizeof(per_oid_expected)); } FreeRDP-1.0.2/cunit/test_per.h000066400000000000000000000016131207112532300160560ustar00rootroot00000000000000/** * FreeRDP: A Remote Desktop Protocol Client * Packed Encoding Rules (PER) Unit Tests * * Copyright 2011 Marc-Andre Moreau * * 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. */ #include "test_freerdp.h" int init_per_suite(void); int clean_per_suite(void); int add_per_suite(void); void test_per_write_length(void); void test_per_write_object_identifier(void); FreeRDP-1.0.2/cunit/test_rail.c000066400000000000000000000665031207112532300162230ustar00rootroot00000000000000/* FreeRDP: A Remote Desktop Protocol client. RAIL(TS RemoteApp) Virtual Channel Unit Tests Copyright 2011 Vic Lee Copyright 2011 Roman Barabanov 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. */ #include #include #include #include #include #include #include #include #include #include #include #include #include #include "test_rail.h" #define HCF_HIGHCONTRASTON 0x00000001 #define HCF_AVAILABLE 0x00000002 #define HCF_HOTKEYACTIVE 0x00000004 #define HCF_CONFIRMHOTKEY 0x00000008 #define HCF_HOTKEYSOUND 0x00000010 #define HCF_INDICATOR 0x00000020 #define HCF_HOTKEYAVAILABLE 0x00000040 int init_rail_suite(void) { freerdp_channels_global_init(); return 0; } int clean_rail_suite(void) { freerdp_channels_global_uninit(); return 0; } int add_rail_suite(void) { add_test_suite(rail); add_test_function(rail_plugin); return 0; } static uint8 client_handshake[] = { 0x05, 0x00, 0x08, 0x00, 0xb0, 0x1d, 0x00, 0x00 }; static uint8 client_info_pdu[] = { 0x0b, 0x00, 0x08, 0x00, 0x01, 0x00, 0x00, 0x00 }; // Flags: TS_RAIL_EXEC_FLAG_EXPAND_ARGUMENTS // ExeOrFile : ||iexplore // WorkingDir: f:\windows\system32 // Arguments: www.bing.com static uint8 client_execute_pdu[] = { 0x01,0x00,0x5e,0x00,0x08,0x00,0x14,0x00,0x26,0x00,0x18,0x00,0x7c,0x00, 0x7c,0x00,0x69,0x00,0x65,0x00,0x78,0x00,0x70,0x00,0x6c,0x00,0x6f,0x00, 0x72,0x00,0x65,0x00,0x66,0x00,0x3a,0x00,0x5c,0x00,0x77,0x00,0x69,0x00, 0x6e,0x00,0x64,0x00,0x6f,0x00,0x77,0x00,0x73,0x00,0x5c,0x00,0x73,0x00, 0x79,0x00,0x73,0x00,0x74,0x00,0x65,0x00,0x6d,0x00,0x33,0x00,0x32,0x00, 0x77,0x00,0x77,0x00,0x77,0x00,0x2e,0x00,0x62,0x00,0x69,0x00,0x6e,0x00, 0x67,0x00,0x2e,0x00,0x63,0x00,0x6f,0x00,0x6d,0x00 }; static uint8 client_activate_pdu[] = { 0x02,0x00, 0x09,0x00, 0x8e,0x00,0x07,0x00, 0x01 }; static uint8 client_sysparam_highcontrast_pdu[] = { 0x03,0x00, 0x12,0x00, 0x43,0x00,0x00,0x00, // SPI_SETHIGHCONTRAST 0x7e,0x00,0x00,0x00, // HCF_AVAILABLE | HCF_HOTKEYACTIVE | HCF_CONFIRMHOTKEY // HCF_HOTKEYSOUND | HCF_INDICATOR | HCF_HOTKEYAVAILABLE 0x02,0x00,0x00,0x00, // Minimum length 2 0x00,0x00 // Unicode String }; static uint8 client_sysparam_taskbarpos_pdu[] = { 0x03,0x00, 0x10,0x00, 0x00,0xf0,0x00,0x00, // RAIL_SPI_TASKBARPOS 0x00,0x00, // 0 0x9a,0x03, // 0x039a 0x90,0x06, // 0x0690 0xc2,0x03 // 0x03c2 }; static uint8 client_sysparam_mousebuttonswap_pdu[] = { 0x03,0x00, 0x09,0x00, 0x21,0x00,0x00,0x00, // SPI_SETMOUSEBUTTONSWAP 0x00 // false }; static uint8 client_sysparam_keyboardpref_pdu[] = { 0x03,0x00, 0x09,0x00, 0x45,0x00,0x00,0x00, // SPI_SETKEYBOARDPREF 0x00 // false }; static uint8 client_sysparam_dragfullwindow_pdu[] = { 0x03,0x00, 0x09,0x00, 0x25,0x00,0x00,0x00, // SPI_SETDRAGFULLWINDOWS 0x01 // true }; static uint8 client_sysparam_keyboardcues_pdu[] = { 0x03,0x00, 0x09,0x00, 0x0b,0x10,0x00,0x00, //SPI_SETKEYBOARDCUES 0x00 // false }; static uint8 client_sysparam_setworkarea_pdu[] = { 0x03,0x00, 0x10,0x00, 0x2f,0x00,0x00,0x00, //SPI_SETWORKAREA 0x00,0x00, // 0 0x00,0x00, // 0 0x90,0x06, // 0x0690 0x9a,0x03 // 0x039a }; static uint8 client_syscommand_pdu[] = { 0x04,0x00, 0x0a,0x00, 0x52,0x00,0x02,0x00, 0x20,0xf0 }; static uint8 client_notify_pdu[] = { 0x06,0x00, 0x10,0x00, 0xaa,0x01,0x02,0x00, 0x02,0x00,0x00,0x00, 0x04,0x02,0x00,0x00 }; static uint8 client_windowmove_pdu[] = { 0x08,0x00, 0x10,0x00, 0x20,0x00,0x02,0x00, 0x09,0x03, 0x00,0x01, 0xdb,0x05, 0x88,0x01 }; static uint8 client_system_menu_pdu[] = { 0x0c,0x00, 0x0c,0x00, 0x22,0x01,0x09,0x00, 0xa4,0xff, 0x4a,0x02 }; static uint8 client_langbar_pdu[] = { 0x0D,0x00,0x08,0x00,0x01,0x00,0x00,0x00 }; static uint8 client_get_app_id_req_pdu[] = { 0x0E,0x00,0x08,0x00,0x52,0x00,0x02,0x00 }; static uint8 server_handshake[] = { 0x05, 0x00, 0x08, 0x00, 0xb0, 0x1d, 0x00, 0x00 }; static uint8 server_exec_result_pdu[] = { 0x80,0x00,0x24,0x00,0x08,0x00,0x03,0x00,0x15,0x00,0x00,0x00,0x00,0x00, 0x14,0x00,0x7c,0x00,0x7c,0x00,0x57,0x00,0x72,0x00,0x6f,0x00,0x6e,0x00, 0x67,0x00,0x41,0x00,0x70,0x00,0x70,0x00 }; static uint8 server_exec_result_exe_or_file[] = { 0x7c,0x00,0x7c,0x00,0x57,0x00,0x72,0x00,0x6f,0x00,0x6e,0x00, 0x67,0x00,0x41,0x00,0x70,0x00,0x70,0x00 }; static uint8 server_sysparam1_pdu[] = { 0x03,0x00, 0x09,0x00, 0x77,0x00,0x00,0x00, 0x00 }; static uint8 server_sysparam2_pdu[] = { 0x03,0x00, 0x09,0x00, 0x11,0x00,0x00,0x00, 0x00 }; static uint8 server_localmovesize_start_pdu[] = { 0x09,0x00,0x10,0x00,0x8e,0x00,0x07,0x00,0x01,0x00,0x09,0x00,0x7e,0x01, 0x0a,0x00 }; static uint8 server_localmovesize_stop_pdu[] = { 0x09,0x00,0x10,0x00,0x8e,0x00,0x07,0x00,0x00,0x00,0x09,0x00,0xa6,0x00, 0x44,0x00 }; static uint8 server_minmaxinfo_pdu[] = { 0x0a,0x00,0x18,0x00,0x8e,0x00,0x07,0x00,0x08,0x04,0xd6,0x02,0x00,0x00, 0x00,0x00,0x70,0x00,0x1b,0x00,0x0c,0x04,0x0c,0x03 }; static uint8 server_langbar_pdu[] = { 0x0D,0x00,0x08,0x00,0x01,0x00,0x00,0x00 }; static uint8 server_app_get_resp_pdu[] = { 0x0F,0x00,0x08,0x02,0x52,0x00,0x02,0x00,0x6d,0x00,0x69,0x00,0x63,0x00, 0x72,0x00,0x6f,0x00,0x73,0x00,0x6f,0x00,0x66,0x00,0x74,0x00,0x2e,0x00, 0x77,0x00,0x69,0x00,0x6e,0x6f,0x00,0x77,0x00,0x73,0x00,0x2e,0x00,0x6e, 0x00,0x6f,0x00,0x74,0x00,0x65,0x00,0x70,0x00,0x61,0x00,0x64,0x00,0x00, 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 0x00,0x00, 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 0x00,0x00, 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 0x00,0x00, 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 0x00,0x00, 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 0x00,0x00, 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00,0x00,0x00 }; static uint8 server_app_get_resp_app_id[] = { 0x6d,0x00,0x69,0x00,0x63,0x00,0x72,0x00,0x6f,0x00,0x73,0x00,0x6f,0x00, 0x66,0x00,0x74,0x00,0x2e,0x00,0x77,0x00,0x69,0x00,0x6e,0x6f,0x00,0x77, 0x00,0x73,0x00,0x2e,0x00,0x6e,0x00,0x6f,0x00,0x74,0x00,0x65,0x00,0x70, 0x00,0x61,0x00,0x64,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 0x00,0x00, 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 0x00,0x00, 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 0x00,0x00, 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 0x00,0x00, 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00,0x00,0x00 }; #define EMULATE_SERVER_SEND_CHANNEL_DATA(inst, byte_array) \ emulate_server_send_channel_data(inst, byte_array, RAIL_ARRAY_SIZE(byte_array)) #define STREAM_EQUAL_TO_DUMP(stream, dump) \ (stream_equal_dump((stream)->data, (stream)->size, dump, RAIL_ARRAY_SIZE(dump))) #define UNICODE_STRING_EQUAL_TO_DUMP(ustring, dump) \ (stream_equal_dump((ustring)->string, (ustring)->length, dump, RAIL_ARRAY_SIZE(dump))) typedef struct { RAIL_HANDSHAKE_ORDER handshake; RAIL_CLIENT_STATUS_ORDER client_status; RAIL_EXEC_ORDER exec; RAIL_EXEC_RESULT_ORDER exec_result; RAIL_SYSPARAM_ORDER sysparam; RAIL_ACTIVATE_ORDER activate; RAIL_SYSMENU_ORDER sysmenu; RAIL_SYSCOMMAND_ORDER syscommand; RAIL_NOTIFY_EVENT_ORDER notify_event; RAIL_MINMAXINFO_ORDER minmaxinfo; RAIL_LOCALMOVESIZE_ORDER localmovesize; RAIL_WINDOW_MOVE_ORDER window_move; RAIL_LANGBAR_INFO_ORDER langbar_info; RAIL_GET_APPID_REQ_ORDER get_appid_req; RAIL_GET_APPID_RESP_ORDER get_appid_resp; } RAIL_ORDERS; typedef struct { RAIL_ORDERS order_info; uint32 event_type; } RAIL_EVENT; typedef struct { rdpChannels* chan_man; freerdp* instance; int th_count; int th_to_finish; RAIL_ORDERS out_rail_orders; RAIL_EVENT in_events[20]; size_t in_events_number; STREAM in_streams[20]; size_t in_streams_number; RDP_PLUGIN_DATA plugin_data; } thread_param; static thread_param* global_thread_params = NULL; //----------------------------------------------------------------------------- int stream_equal_dump(void * dataS, size_t sizeS, void * data, size_t size) { size_t i; if (sizeS != size) { printf("----------------- stream_equal_dump -----------------\n"); printf("Stream and dump have different length (%d != %d)\n", (int) sizeS, (int) size); printf("Stream hexdump:\n"); freerdp_hexdump(dataS, sizeS); printf("Dump hexdump:\n"); freerdp_hexdump(data, size); printf("----------------- stream_equal_dump -----------------\n"); return 0; } for (i=0; i < size; i++) { if (((uint8*)dataS)[i] != ((uint8*)data)[i]) { printf("----------------- stream_equal_dump -----------------\n"); printf("Stream and dump have different content from %d offset.\n", (int) i); printf("Stream hexdump:\n"); freerdp_hexdump(dataS, sizeS); printf("Dump hexdump:\n"); freerdp_hexdump(data, size); printf("----------------- stream_equal_dump -----------------\n"); return 0; } } return 1; } //----------------------------------------------------------------------------- static void test_on_free_rail_client_event(RDP_EVENT* event) { if (event->event_class == RDP_EVENT_CLASS_RAIL) { rail_free_cloned_order(event->event_type, event->user_data); } } //----------------------------------------------------------------------------- static void send_ui_event2plugin( rdpChannels* chan_man, uint16 event_type, void * data ) { RDP_EVENT* out_event = NULL; void * payload = NULL; payload = rail_clone_order(event_type, data); if (payload != NULL) { out_event = freerdp_event_new(RDP_EVENT_CLASS_RAIL, event_type, test_on_free_rail_client_event, payload); freerdp_channels_send_event(chan_man, out_event); } } //----------------------------------------------------------------------------- static void emulate_server_send_channel_data( freerdp* instance, void* data, size_t size ) { static int counter = 0; counter++; printf("Emulate server packet (%d packet):\n", counter); freerdp_hexdump(data, size); freerdp_channels_data(instance, 0, (char*)data, size, CHANNEL_FLAG_FIRST | CHANNEL_FLAG_LAST, size); usleep(10*1000); } static void save_dump(void* data, size_t size) { thread_param * p = global_thread_params; if (p->in_streams_number < RAIL_ARRAY_SIZE(p->in_streams)) { STREAM* s = &p->in_streams[p->in_streams_number]; s->data = malloc(size); s->size = size; memcpy(s->data, data, size); p->in_streams_number++; } } //----------------------------------------------------------------------------- static int emulate_client_send_channel_data( freerdp* freerdp, int channelId, uint8* data, int size ) { static int counter = 0; counter++; printf("Client send to server (%d packet):\n", counter); freerdp_hexdump(data, size); // add to global dumps list save_dump(data, size); return 0; } //----------------------------------------------------------------------------- void save_event(RDP_EVENT* event, RAIL_EVENT* rail_event) { rail_event->event_type = event->event_type; switch (event->event_type) { case RDP_EVENT_TYPE_RAIL_CHANNEL_GET_SYSPARAMS: printf("UI receive Get Sysparams Event\n"); break; case RDP_EVENT_TYPE_RAIL_CHANNEL_EXEC_RESULTS: { RAIL_EXEC_RESULT_ORDER* exec_result = (RAIL_EXEC_RESULT_ORDER*)event->user_data; printf("UI receive Exec Results Event\n"); memcpy(&rail_event->order_info.exec_result, event->user_data, sizeof(RAIL_EXEC_RESULT_ORDER)); rail_unicode_string_alloc(&rail_event->order_info.exec_result.exeOrFile, exec_result->exeOrFile.length); memcpy(rail_event->order_info.exec_result.exeOrFile.string, exec_result->exeOrFile.string, exec_result->exeOrFile.length); } break; case RDP_EVENT_TYPE_RAIL_CHANNEL_SERVER_SYSPARAM: printf("UI receive Server Sysparam Event\n"); memcpy(&rail_event->order_info.sysparam, event->user_data, sizeof(RAIL_SYSPARAM_ORDER)); break; case RDP_EVENT_TYPE_RAIL_CHANNEL_SERVER_MINMAXINFO: printf("UI receive Server Minmax Info Event\n"); memcpy(&rail_event->order_info.minmaxinfo, event->user_data, sizeof(RAIL_MINMAXINFO_ORDER)); break; case RDP_EVENT_TYPE_RAIL_CHANNEL_SERVER_LOCALMOVESIZE: printf("UI receive Server Local Movesize Event\n"); memcpy(&rail_event->order_info.localmovesize, event->user_data, sizeof(RAIL_LOCALMOVESIZE_ORDER)); break; case RDP_EVENT_TYPE_RAIL_CHANNEL_APPID_RESP: printf("UI receive AppId Response Event\n"); memcpy(&rail_event->order_info.get_appid_resp, event->user_data, sizeof(RAIL_GET_APPID_RESP_ORDER)); rail_event->order_info.get_appid_resp.applicationId.string = &rail_event->order_info.get_appid_resp.applicationIdBuffer[0]; break; case RDP_EVENT_TYPE_RAIL_CHANNEL_LANGBARINFO: printf("UI receive Language Info Event\n"); memcpy(&rail_event->order_info.langbar_info, event->user_data, sizeof(RAIL_LANGBAR_INFO_ORDER)); break; } } //----------------------------------------------------------------------------- static void process_events_and_channel_data_from_plugin(thread_param* param) { RDP_EVENT* event; param->th_count++; while (param->th_to_finish == 0) { freerdp_channels_check_fds(param->chan_man, param->instance); while (1) { event = freerdp_channels_pop_event(param->chan_man); if (event == NULL) break; static int counter = 0; counter++; printf("UI receive event. (type=%d counter=%d).\n", event->event_type, counter); // add to global event list if (param->in_events_number < RAIL_ARRAY_SIZE(param->in_events)) { save_event(event, ¶m->in_events[param->in_events_number]); param->in_events_number++; } freerdp_event_free(event); } usleep(1000); } param->th_count--; } //----------------------------------------------------------------------------- void* thread_func(void* param) { thread_param* th_param = (thread_param*)param; process_events_and_channel_data_from_plugin(th_param); pthread_detach(pthread_self()); return NULL; } //----------------------------------------------------------------------------- void test_rail_plugin(void) { thread_param param; pthread_t thread; rdpChannels* chan_man; rdpSettings settings = { 0 }; freerdp s_inst = { 0 }; freerdp* inst = &s_inst; size_t sn = 0; size_t en = 0; STREAM* ss = NULL; RAIL_EVENT* ee = NULL; printf("\n"); settings.hostname = "testhost"; inst->settings = &settings; inst->SendChannelData = emulate_client_send_channel_data; chan_man = freerdp_channels_new(); freerdp_channels_load_plugin(chan_man, &settings, "../channels/rail/rail.so", NULL); freerdp_channels_pre_connect(chan_man, inst); freerdp_channels_post_connect(chan_man, inst); memset(¶m, 0, sizeof(param)); param.chan_man = chan_man; param.instance = inst; param.th_count = 0; param.th_to_finish = 0; global_thread_params = ¶m; pthread_create(&thread, 0, thread_func, ¶m); // 1. Emulate server handshake binary EMULATE_SERVER_SEND_CHANNEL_DATA(inst, server_handshake); EMULATE_SERVER_SEND_CHANNEL_DATA(inst, server_exec_result_pdu); EMULATE_SERVER_SEND_CHANNEL_DATA(inst, server_sysparam1_pdu); EMULATE_SERVER_SEND_CHANNEL_DATA(inst, server_sysparam2_pdu); EMULATE_SERVER_SEND_CHANNEL_DATA(inst, server_localmovesize_start_pdu); EMULATE_SERVER_SEND_CHANNEL_DATA(inst, server_localmovesize_stop_pdu); EMULATE_SERVER_SEND_CHANNEL_DATA(inst, server_minmaxinfo_pdu); EMULATE_SERVER_SEND_CHANNEL_DATA(inst, server_langbar_pdu); EMULATE_SERVER_SEND_CHANNEL_DATA(inst, server_app_get_resp_pdu); // 2. Send UI events param.out_rail_orders.sysparam.params = 0; param.out_rail_orders.sysparam.params |= SPI_MASK_SET_HIGH_CONTRAST; param.out_rail_orders.sysparam.highContrast.flags = 0x7e; param.out_rail_orders.sysparam.highContrast.colorScheme.length = 0; param.out_rail_orders.sysparam.highContrast.colorScheme.string = NULL; param.out_rail_orders.sysparam.params |= SPI_MASK_TASKBAR_POS; param.out_rail_orders.sysparam.taskbarPos.left = 0; param.out_rail_orders.sysparam.taskbarPos.top = 0x039a; param.out_rail_orders.sysparam.taskbarPos.right = 0x0690; param.out_rail_orders.sysparam.taskbarPos.bottom = 0x03c2; param.out_rail_orders.sysparam.params |= SPI_MASK_SET_MOUSE_BUTTON_SWAP; param.out_rail_orders.sysparam.mouseButtonSwap = false; param.out_rail_orders.sysparam.params |= SPI_MASK_SET_KEYBOARD_PREF; param.out_rail_orders.sysparam.keyboardPref = false; param.out_rail_orders.sysparam.params |= SPI_MASK_SET_DRAG_FULL_WINDOWS; param.out_rail_orders.sysparam.dragFullWindows = true; param.out_rail_orders.sysparam.params |= SPI_MASK_SET_KEYBOARD_CUES; param.out_rail_orders.sysparam.keyboardCues = false; param.out_rail_orders.sysparam.params |= SPI_MASK_SET_WORK_AREA; param.out_rail_orders.sysparam.workArea.left = 0; param.out_rail_orders.sysparam.workArea.top = 0; param.out_rail_orders.sysparam.workArea.right = 0x0690; param.out_rail_orders.sysparam.workArea.bottom = 0x039a; send_ui_event2plugin(chan_man, RDP_EVENT_TYPE_RAIL_CLIENT_SET_SYSPARAMS, ¶m.out_rail_orders.sysparam); param.plugin_data.size = sizeof(RDP_PLUGIN_DATA); param.plugin_data.data[0] = "||iexplore"; param.plugin_data.data[1] = "f:\\windows\\system32"; param.plugin_data.data[2] = "www.bing.com"; send_ui_event2plugin(chan_man, RDP_EVENT_TYPE_RAIL_CLIENT_EXEC_REMOTE_APP, ¶m.plugin_data); param.out_rail_orders.activate.enabled = true; param.out_rail_orders.activate.windowId = 0x0007008e; send_ui_event2plugin(chan_man, RDP_EVENT_TYPE_RAIL_CLIENT_ACTIVATE, ¶m.out_rail_orders.activate); param.out_rail_orders.syscommand.windowId = 0x00020052; param.out_rail_orders.syscommand.command = 0xf020; send_ui_event2plugin(chan_man, RDP_EVENT_TYPE_RAIL_CLIENT_SYSCOMMAND, ¶m.out_rail_orders.syscommand); param.out_rail_orders.notify_event.windowId = 0x000201aa; param.out_rail_orders.notify_event.notifyIconId = 0x02; param.out_rail_orders.notify_event.message = 0x0204; send_ui_event2plugin(chan_man, RDP_EVENT_TYPE_RAIL_CLIENT_NOTIFY_EVENT, ¶m.out_rail_orders.notify_event); param.out_rail_orders.window_move.windowId = 0x00020020; param.out_rail_orders.window_move.left = 0x0309; param.out_rail_orders.window_move.top = 0x0100; param.out_rail_orders.window_move.right = 0x05db; param.out_rail_orders.window_move.bottom = 0x0188; send_ui_event2plugin(chan_man, RDP_EVENT_TYPE_RAIL_CLIENT_WINDOW_MOVE, ¶m.out_rail_orders.window_move); param.out_rail_orders.sysmenu.windowId = 0x00090122; param.out_rail_orders.sysmenu.left = 0xffa4; // TODO: possible negative values? param.out_rail_orders.sysmenu.top = 0x024a; send_ui_event2plugin(chan_man, RDP_EVENT_TYPE_RAIL_CLIENT_SYSMENU, ¶m.out_rail_orders.sysmenu); param.out_rail_orders.langbar_info.languageBarStatus = 0x00000001; send_ui_event2plugin(chan_man, RDP_EVENT_TYPE_RAIL_CLIENT_LANGBARINFO, ¶m.out_rail_orders.langbar_info); param.out_rail_orders.get_appid_req.windowId = 0x00020052; send_ui_event2plugin(chan_man, RDP_EVENT_TYPE_RAIL_CLIENT_APPID_REQ, ¶m.out_rail_orders.get_appid_req); // Waiting for possible events or data sleep(1); // Finishing thread and wait for it param.th_to_finish = 1; while (param.th_count > 0) { usleep(1000); } // We need to collected all events and data dumps and then to. // create CU_ASSERT series here! sn = param.in_streams_number; en = param.in_events_number; ss = ¶m.in_streams[0]; ee = ¶m.in_events[0]; CU_ASSERT(sn > 0 && STREAM_EQUAL_TO_DUMP(&ss[ 0], client_handshake)); CU_ASSERT(sn > 1 && STREAM_EQUAL_TO_DUMP(&ss[ 1], client_info_pdu)); CU_ASSERT(sn > 2 && STREAM_EQUAL_TO_DUMP(&ss[ 2], client_sysparam_highcontrast_pdu)); CU_ASSERT(sn > 3 && STREAM_EQUAL_TO_DUMP(&ss[ 3], client_sysparam_taskbarpos_pdu)); CU_ASSERT(sn > 4 && STREAM_EQUAL_TO_DUMP(&ss[ 4], client_sysparam_mousebuttonswap_pdu)); CU_ASSERT(sn > 5 && STREAM_EQUAL_TO_DUMP(&ss[ 5], client_sysparam_keyboardpref_pdu)); CU_ASSERT(sn > 6 && STREAM_EQUAL_TO_DUMP(&ss[ 6], client_sysparam_dragfullwindow_pdu)); CU_ASSERT(sn > 7 && STREAM_EQUAL_TO_DUMP(&ss[ 7], client_sysparam_keyboardcues_pdu)); CU_ASSERT(sn > 8 && STREAM_EQUAL_TO_DUMP(&ss[ 8], client_sysparam_setworkarea_pdu)); CU_ASSERT(sn > 9 && STREAM_EQUAL_TO_DUMP(&ss[ 9], client_execute_pdu)); CU_ASSERT(sn >10 && STREAM_EQUAL_TO_DUMP(&ss[10], client_activate_pdu)); CU_ASSERT(sn >11 && STREAM_EQUAL_TO_DUMP(&ss[11], client_syscommand_pdu)); CU_ASSERT(sn >12 && STREAM_EQUAL_TO_DUMP(&ss[12], client_notify_pdu)); CU_ASSERT(sn >13 && STREAM_EQUAL_TO_DUMP(&ss[13], client_windowmove_pdu)); CU_ASSERT(sn >14 && STREAM_EQUAL_TO_DUMP(&ss[14], client_system_menu_pdu)); CU_ASSERT(sn >15 && STREAM_EQUAL_TO_DUMP(&ss[15], client_langbar_pdu)); CU_ASSERT(sn >16 && STREAM_EQUAL_TO_DUMP(&ss[16], client_get_app_id_req_pdu)); CU_ASSERT(en > 0 && ee[ 0].event_type == RDP_EVENT_TYPE_RAIL_CHANNEL_GET_SYSPARAMS); CU_ASSERT(en > 1 && ee[ 1].event_type == RDP_EVENT_TYPE_RAIL_CHANNEL_EXEC_RESULTS && ee[ 1].order_info.exec_result.flags == 0x08 && ee[ 1].order_info.exec_result.execResult == 0x03 && UNICODE_STRING_EQUAL_TO_DUMP( &ee[ 1].order_info.exec_result.exeOrFile, server_exec_result_exe_or_file) ); CU_ASSERT(en > 2 && ee[ 2].event_type == RDP_EVENT_TYPE_RAIL_CHANNEL_SERVER_SYSPARAM && ee[ 2].order_info.sysparam.setScreenSaveSecure == false ); CU_ASSERT(en > 3 && ee[ 3].event_type == RDP_EVENT_TYPE_RAIL_CHANNEL_SERVER_SYSPARAM && ee[ 3].order_info.sysparam.setScreenSaveActive == false ); CU_ASSERT(en > 4 && ee[ 4].event_type == RDP_EVENT_TYPE_RAIL_CHANNEL_SERVER_LOCALMOVESIZE && ee[ 4].order_info.localmovesize.windowId == 0x0007008e && ee[ 4].order_info.localmovesize.isMoveSizeStart == true && ee[ 4].order_info.localmovesize.moveSizeType == RAIL_WMSZ_MOVE && ee[ 4].order_info.localmovesize.posX == 0x017e && ee[ 4].order_info.localmovesize.posY == 0x000a ); CU_ASSERT(en > 5 && ee[ 5].event_type == RDP_EVENT_TYPE_RAIL_CHANNEL_SERVER_LOCALMOVESIZE && ee[ 5].order_info.localmovesize.windowId == 0x0007008e && ee[ 5].order_info.localmovesize.isMoveSizeStart == false && ee[ 5].order_info.localmovesize.moveSizeType == RAIL_WMSZ_MOVE && ee[ 5].order_info.localmovesize.posX == 0x00a6 && ee[ 5].order_info.localmovesize.posY == 0x0044 ); CU_ASSERT(en > 6 && ee[ 6].event_type == RDP_EVENT_TYPE_RAIL_CHANNEL_SERVER_MINMAXINFO && ee[ 6].order_info.minmaxinfo.windowId == 0x0007008e && ee[ 6].order_info.minmaxinfo.maxWidth == 0x0408 && ee[ 6].order_info.minmaxinfo.maxHeight == 0x02d6 && ee[ 6].order_info.minmaxinfo.maxPosX == 0x0000 && ee[ 6].order_info.minmaxinfo.maxPosY == 0x0000 && ee[ 6].order_info.minmaxinfo.minTrackWidth == 0x0070 && ee[ 6].order_info.minmaxinfo.minTrackHeight == 0x001b && ee[ 6].order_info.minmaxinfo.maxTrackWidth == 0x040c && ee[ 6].order_info.minmaxinfo.maxTrackHeight == 0x030c ); CU_ASSERT(en > 7 && ee[ 7].event_type == RDP_EVENT_TYPE_RAIL_CHANNEL_LANGBARINFO && ee[ 7].order_info.langbar_info.languageBarStatus == TF_SFT_SHOWNORMAL ); CU_ASSERT(en > 8 && ee[ 8].event_type == RDP_EVENT_TYPE_RAIL_CHANNEL_APPID_RESP && ee[ 8].order_info.get_appid_resp.windowId == 0x00020052 && UNICODE_STRING_EQUAL_TO_DUMP( &ee[ 8].order_info.get_appid_resp.applicationId, server_app_get_resp_app_id ) ); freerdp_channels_close(chan_man, inst); freerdp_channels_free(chan_man); } FreeRDP-1.0.2/cunit/test_rail.h000066400000000000000000000015261207112532300162220ustar00rootroot00000000000000/* FreeRDP: A Remote Desktop Protocol client. RAIL(TS RemoteApp) Virtual Channel Unit Tests Copyright 2011 Roman Barabanov 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. */ #include "test_freerdp.h" int init_rail_suite(void); int clean_rail_suite(void); int add_rail_suite(void); void test_rail_plugin(void); FreeRDP-1.0.2/cunit/test_stream.c000066400000000000000000000031371207112532300165610ustar00rootroot00000000000000/** * FreeRDP: A Remote Desktop Protocol Client * Stream Unit Tests * * Copyright 2011 Vic Lee * * 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. */ #include #include #include #include #include #include #include "test_stream.h" int init_stream_suite(void) { return 0; } int clean_stream_suite(void) { return 0; } int add_stream_suite(void) { add_test_suite(stream); add_test_function(stream); return 0; } void test_stream(void) { STREAM * stream; int pos; uint32 n; uint64 n64; stream = stream_new(1); pos = stream_get_pos(stream); stream_write_uint8(stream, 0xFE); stream_check_size(stream, 14); stream_write_uint16(stream, 0x0102); stream_write_uint32(stream, 0x03040506); stream_write_uint64(stream, 0x0708091011121314LL); /* freerdp_hexdump(stream->buffer, 15); */ stream_set_pos(stream, pos); stream_seek(stream, 3); stream_read_uint32(stream, n); stream_read_uint64(stream, n64); CU_ASSERT(n == 0x03040506); CU_ASSERT(n64 == 0x0708091011121314LL); stream_free(stream); } FreeRDP-1.0.2/cunit/test_stream.h000066400000000000000000000014411207112532300165620ustar00rootroot00000000000000/** * FreeRDP: A Remote Desktop Protocol Client * Stream Unit Tests * * Copyright 2011 Vic Lee * * 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. */ #include "test_freerdp.h" int init_stream_suite(void); int clean_stream_suite(void); int add_stream_suite(void); void test_stream(void); FreeRDP-1.0.2/cunit/test_utils.c000066400000000000000000000406431207112532300164310ustar00rootroot00000000000000/** * FreeRDP: A Remote Desktop Protocol Client * Utils Unit Tests * * Copyright 2011 Vic Lee, 2011 Shea Levy * * 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. */ #define _XOPEN_SOURCE 700 #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include "test_utils.h" int init_utils_suite(void) { return 0; } int clean_utils_suite(void) { return 0; } int add_utils_suite(void) { add_test_suite(utils); add_test_function(mutex); add_test_function(semaphore); add_test_function(load_plugin); add_test_function(wait_obj); add_test_function(args); add_test_function(passphrase_read); add_test_function(handle_signals); return 0; } void test_mutex(void) { freerdp_mutex mutex; mutex = freerdp_mutex_new(); freerdp_mutex_lock(mutex); freerdp_mutex_unlock(mutex); freerdp_mutex_free(mutex); } void test_semaphore(void) { freerdp_sem sem; sem = freerdp_sem_new(1); freerdp_sem_wait(sem); freerdp_sem_signal(sem); freerdp_sem_free(sem); } void test_load_plugin(void) { void* entry; #ifdef _WIN32 /* untested */ entry = freerdp_load_plugin("..\\channels\\cliprdr\\cliprdr", "VirtualChannelEntry"); #else entry = freerdp_load_plugin("../channels/cliprdr/cliprdr.so", "VirtualChannelEntry"); #endif CU_ASSERT(entry != NULL); } void test_wait_obj(void) { struct wait_obj* wo; int set; wo = wait_obj_new(); set = wait_obj_is_set(wo); CU_ASSERT(set == 0); wait_obj_set(wo); set = wait_obj_is_set(wo); CU_ASSERT(set == 1); wait_obj_clear(wo); set = wait_obj_is_set(wo); CU_ASSERT(set == 0); wait_obj_select(&wo, 1, 1000); wait_obj_free(wo); } static int process_plugin_args(rdpSettings* settings, const char* name, RDP_PLUGIN_DATA* plugin_data, void* user_data) { /*printf("load plugin: %s\n", name);*/ return 1; } static int process_ui_args(rdpSettings* settings, const char* opt, const char* val, void* user_data) { /*printf("ui arg: %s %s\n", opt, val);*/ return 1; } void test_args(void) { char* argv_c[] = { "freerdp", "-a", "8", "-u", "testuser", "-d", "testdomain", "-g", "640x480", "address1:3389", "freerdp", "-a", "16", "-u", "testuser", "-d", "testdomain", "-g", "1280x960", "address2:3390" }; char** argv = argv_c; int argc = sizeof(argv_c) / sizeof(char*); int i; int c; rdpSettings* settings; i = 0; while (argc > 0) { settings = settings_new(NULL); i++; c = freerdp_parse_args(settings, argc, argv, process_plugin_args, NULL, process_ui_args, NULL); CU_ASSERT(c > 0); if (c == 0) { settings_free(settings); break; } CU_ASSERT(settings->color_depth == i * 8); CU_ASSERT(settings->width == i * 640); CU_ASSERT(settings->height == i * 480); CU_ASSERT(settings->port == i + 3388); settings_free(settings); argc -= c; argv += c; } CU_ASSERT(i == 2); } void passphrase_read_prompts_to_tty() { static const int read_nbyte = 11; int masterfd; char* slavedevice; char read_buf[read_nbyte]; fd_set fd_set_write; masterfd = posix_openpt(O_RDWR|O_NOCTTY); if (masterfd == -1 || grantpt (masterfd) == -1 || unlockpt (masterfd) == -1 || (slavedevice = ptsname (masterfd)) == NULL) CU_FAIL_FATAL("Could not create pty"); switch (fork()) { case -1: CU_FAIL_FATAL("Could not fork"); case 0: { static const int password_size = 512; char buffer[password_size]; int slavefd; if (setsid() == (pid_t) -1) CU_FAIL_FATAL("Could not create new session"); if ((slavefd = open(slavedevice, O_RDWR)) == 0) CU_FAIL_FATAL("Could not open slave end of pty"); close(STDIN_FILENO); close(STDOUT_FILENO); close(STDERR_FILENO); close(masterfd); freerdp_passphrase_read("Password: ", buffer, password_size); close(slavefd); exit(EXIT_SUCCESS); } } read_buf[read_nbyte - 1] = '\0'; FD_ZERO(&fd_set_write); FD_SET(masterfd, &fd_set_write); if (select(masterfd + 1, NULL, &fd_set_write, NULL, NULL) == -1) CU_FAIL_FATAL("Master end of pty not writeable"); if (read(masterfd, read_buf, read_nbyte) == (ssize_t) -1) CU_FAIL_FATAL("Nothing written to slave end of pty"); CU_ASSERT_STRING_EQUAL(read_buf, "Password: "); write(masterfd, "\n", (size_t) 2); close(masterfd); return; } void passphrase_read_reads_from_tty() { static const int read_nbyte = 11; int masterfd; int pipe_ends[2]; char* slavedevice; char read_buf[read_nbyte]; fd_set fd_set_write; masterfd = posix_openpt(O_RDWR|O_NOCTTY); if (masterfd == -1 || grantpt (masterfd) == -1 || unlockpt (masterfd) == -1 || (slavedevice = ptsname (masterfd)) == NULL) CU_FAIL_FATAL("Could not create pty"); if (pipe(pipe_ends) != 0) CU_FAIL_FATAL("Could not create pipe"); switch (fork()) { case -1: CU_FAIL_FATAL("Could not fork"); case 0: { static const int password_size = 512; char buffer[password_size]; int slavefd; if (setsid() == (pid_t) -1) CU_FAIL_FATAL("Could not create new session"); if ((slavefd = open(slavedevice, O_RDWR)) == 0) CU_FAIL_FATAL("Could not open slave end of pty"); close(STDIN_FILENO); close(STDOUT_FILENO); close(STDERR_FILENO); close(masterfd); close(pipe_ends[0]); freerdp_passphrase_read("Password: ", buffer, password_size); write(pipe_ends[1], buffer, password_size); close(slavefd); close(pipe_ends[1]); exit(EXIT_SUCCESS); } } close(pipe_ends[1]); read_buf[read_nbyte - 1] = '\0'; FD_ZERO(&fd_set_write); FD_SET(masterfd, &fd_set_write); if (select(masterfd + 1, NULL, &fd_set_write, NULL, NULL) == -1) CU_FAIL_FATAL("Master end of pty not writeable"); if (read(masterfd, read_buf, read_nbyte) == (ssize_t) -1) CU_FAIL_FATAL("Nothing written to slave end of pty"); write(masterfd, "passw0rd\n", sizeof "passw0rd\n"); if (read(pipe_ends[0], read_buf, read_nbyte) == (ssize_t) -1) CU_FAIL_FATAL("Nothing written to pipe"); CU_ASSERT_STRING_EQUAL(read_buf, "passw0rd"); close(masterfd); close(pipe_ends[0]); return; } void passphrase_read_turns_off_echo_during_read() { static const int read_nbyte = 11; int masterfd, slavefd; char* slavedevice; char read_buf[read_nbyte]; fd_set fd_set_write; struct termios term_flags; masterfd = posix_openpt(O_RDWR|O_NOCTTY); if (masterfd == -1 || grantpt (masterfd) == -1 || unlockpt (masterfd) == -1 || (slavedevice = ptsname (masterfd)) == NULL) CU_FAIL_FATAL("Could not create pty"); slavefd = open(slavedevice, O_RDWR|O_NOCTTY); if (slavefd == -1) CU_FAIL_FATAL("Could not open slave end of pty"); if (tcgetattr(slavefd, &term_flags) != 0) CU_FAIL_FATAL("Could not get slave pty attributes"); if (!(term_flags.c_lflag & ECHO)) { term_flags.c_lflag |= ECHO; if (tcsetattr(slavefd, TCSANOW, &term_flags) != 0) CU_FAIL_FATAL("Could not turn ECHO on on slave pty"); } switch (fork()) { case -1: CU_FAIL_FATAL("Could not fork"); case 0: { static const int password_size = 512; int child_slavefd; char buffer[password_size]; if (setsid() == (pid_t) -1) CU_FAIL_FATAL("Could not create new session"); if ((child_slavefd = open(slavedevice, O_RDWR)) == 0) CU_FAIL_FATAL("Could not open slave end of pty"); close(STDIN_FILENO); close(STDOUT_FILENO); close(STDERR_FILENO); close(masterfd); close(slavefd); freerdp_passphrase_read("Password: ", buffer, password_size); close(child_slavefd); exit(EXIT_SUCCESS); } } read_buf[read_nbyte - 1] = '\0'; FD_ZERO(&fd_set_write); FD_SET(masterfd, &fd_set_write); if (select(masterfd + 1, NULL, &fd_set_write, NULL, NULL) == -1) CU_FAIL_FATAL("Master end of pty not writeable"); if (read(masterfd, read_buf, read_nbyte) == (ssize_t) -1) CU_FAIL_FATAL("Nothing written to slave end of pty"); if (tcgetattr(slavefd, &term_flags) != 0) CU_FAIL_FATAL("Could not get slave pty attributes"); CU_ASSERT(!(term_flags.c_lflag & ECHO)) write(masterfd, "\n", (size_t) 2); close(masterfd); close(slavefd); return; } void passphrase_read_resets_terminal_after_read() { static const int read_nbyte = 11; int masterfd, slavefd, status; char* slavedevice; char read_buf[read_nbyte]; fd_set fd_set_write; struct termios term_flags; pid_t child; masterfd = posix_openpt(O_RDWR|O_NOCTTY); if (masterfd == -1 || grantpt (masterfd) == -1 || unlockpt (masterfd) == -1 || (slavedevice = ptsname (masterfd)) == NULL) CU_FAIL_FATAL("Could not create pty"); slavefd = open(slavedevice, O_RDWR|O_NOCTTY); if (slavefd == -1) CU_FAIL_FATAL("Could not open slave end of pty"); if (tcgetattr(slavefd, &term_flags) != 0) CU_FAIL_FATAL("Could not get slave pty attributes"); if (!(term_flags.c_lflag & ECHO)) { term_flags.c_lflag |= ECHO; if (tcsetattr(slavefd, TCSANOW, &term_flags) != 0) CU_FAIL_FATAL("Could not turn ECHO on on slave pty"); } switch (child = fork()) { case -1: CU_FAIL_FATAL("Could not fork"); case 0: { static const int password_size = 512; int child_slavefd; char buffer[password_size]; if (setsid() == (pid_t) -1) CU_FAIL_FATAL("Could not create new session"); if ((child_slavefd = open(slavedevice, O_RDWR)) == 0) CU_FAIL_FATAL("Could not open slave end of pty"); close(STDIN_FILENO); close(STDOUT_FILENO); close(STDERR_FILENO); close(masterfd); close(slavefd); freerdp_passphrase_read("Password: ", buffer, password_size); close(child_slavefd); exit(EXIT_SUCCESS); } } read_buf[read_nbyte - 1] = '\0'; FD_ZERO(&fd_set_write); FD_SET(masterfd, &fd_set_write); if (select(masterfd + 1, NULL, &fd_set_write, NULL, NULL) == -1) CU_FAIL_FATAL("Master end of pty not writeable"); if (read(masterfd, read_buf, read_nbyte) == (ssize_t) -1) CU_FAIL_FATAL("Nothing written to slave end of pty"); write(masterfd, "\n", (size_t) 2); waitpid(child, &status, WUNTRACED); if (tcgetattr(slavefd, &term_flags) != 0) CU_FAIL_FATAL("Could not get slave pty attributes"); CU_ASSERT(term_flags.c_lflag & ECHO) close(masterfd); close(slavefd); return; } void passphrase_read_turns_on_newline_echo_during_read() { static const int read_nbyte = 11; int masterfd, slavefd; char* slavedevice; char read_buf[read_nbyte]; fd_set fd_set_write; struct termios term_flags; masterfd = posix_openpt(O_RDWR|O_NOCTTY); if (masterfd == -1 || grantpt (masterfd) == -1 || unlockpt (masterfd) == -1 || (slavedevice = ptsname (masterfd)) == NULL) CU_FAIL_FATAL("Could not create pty"); slavefd = open(slavedevice, O_RDWR|O_NOCTTY); if (slavefd == -1) CU_FAIL_FATAL("Could not open slave end of pty"); if (tcgetattr(slavefd, &term_flags) != 0) CU_FAIL_FATAL("Could not get slave pty attributes"); if (term_flags.c_lflag & ECHONL) { term_flags.c_lflag &= ~ECHONL; if (tcsetattr(slavefd, TCSANOW, &term_flags) != 0) CU_FAIL_FATAL("Could not turn ECHO on on slave pty"); } switch (fork()) { case -1: CU_FAIL_FATAL("Could not fork"); case 0: { static const int password_size = 512; int child_slavefd; char buffer[password_size]; if (setsid() == (pid_t) -1) CU_FAIL_FATAL("Could not create new session"); if ((child_slavefd = open(slavedevice, O_RDWR)) == 0) CU_FAIL_FATAL("Could not open slave end of pty"); close(STDIN_FILENO); close(STDOUT_FILENO); close(STDERR_FILENO); close(masterfd); close(slavefd); freerdp_passphrase_read("Password: ", buffer, password_size); close(child_slavefd); exit(EXIT_SUCCESS); } } read_buf[read_nbyte - 1] = '\0'; FD_ZERO(&fd_set_write); FD_SET(masterfd, &fd_set_write); if (select(masterfd + 1, NULL, &fd_set_write, NULL, NULL) == -1) CU_FAIL_FATAL("Master end of pty not writeable"); if (read(masterfd, read_buf, read_nbyte) == (ssize_t) -1) CU_FAIL_FATAL("Nothing written to slave end of pty"); if (tcgetattr(slavefd, &term_flags) != 0) CU_FAIL_FATAL("Could not get slave pty attributes"); CU_ASSERT(term_flags.c_lflag & ECHONL) write(masterfd, "\n", (size_t) 2); close(masterfd); close(slavefd); return; } void passphrase_read_prompts_to_stderr_when_no_tty() { static const int read_nbyte = 11; int stdin_pipe[2], stderr_pipe[2]; char read_buf[read_nbyte]; struct sigaction ignore, orig; ignore.sa_handler = SIG_IGN; sigemptyset(&ignore.sa_mask); if (pipe(stdin_pipe) != 0 || pipe(stderr_pipe) != 0) CU_FAIL_FATAL("Could not create pipe"); switch (fork()) { case -1: CU_FAIL_FATAL("Could not fork"); case 0: { static const int password_size = 512; char buffer[password_size]; close(stderr_pipe[0]); close(stdin_pipe[1]); if (setsid() == (pid_t) -1) CU_FAIL_FATAL("Could not create new session"); dup2(stdin_pipe[0], STDIN_FILENO); dup2(stderr_pipe[1], STDERR_FILENO); freerdp_passphrase_read("Password: ", buffer, password_size); exit(EXIT_SUCCESS); } } close(stderr_pipe[1]); close(stdin_pipe[0]); read_buf[read_nbyte - 1] = '\0'; if (read(stderr_pipe[0], read_buf, read_nbyte) == (ssize_t) -1) CU_FAIL_FATAL("Nothing written to pipe"); CU_ASSERT_STRING_EQUAL(read_buf, "Password: "); sigaction(SIGPIPE, &ignore, &orig); write(stdin_pipe[1], "\n", (size_t) 2); sigaction(SIGPIPE, &orig, NULL); close(stderr_pipe[0]); close(stdin_pipe[1]); return; } void passphrase_read_reads_from_stdin_when_no_tty() { static const int read_nbyte = 11; int stdin_pipe[2], stderr_pipe[2], result_pipe[2]; char read_buf[read_nbyte]; struct sigaction ignore, orig; ignore.sa_handler = SIG_IGN; sigemptyset(&ignore.sa_mask); if (pipe(stdin_pipe) != 0 || pipe(stderr_pipe) != 0 || pipe(result_pipe) !=0) CU_FAIL_FATAL("Could not create pipe"); switch (fork()) { case -1: CU_FAIL_FATAL("Could not fork"); case 0: { static const int password_size = 512; char buffer[password_size]; close(stderr_pipe[0]); close(result_pipe[0]); close(stdin_pipe[1]); if (setsid() == (pid_t) -1) CU_FAIL_FATAL("Could not create new session"); dup2(stdin_pipe[0], STDIN_FILENO); dup2(stderr_pipe[1], STDERR_FILENO); freerdp_passphrase_read("Password: ", buffer, password_size); write(result_pipe[1], buffer, strlen(buffer) + (size_t) 1); exit(EXIT_SUCCESS); } } close(stderr_pipe[1]); close(result_pipe[1]); close(stdin_pipe[0]); read_buf[read_nbyte - 1] = '\0'; if (read(stderr_pipe[0], read_buf, read_nbyte) == (ssize_t) -1) CU_FAIL_FATAL("Nothing written to pipe"); sigaction(SIGPIPE, &ignore, &orig); write(stdin_pipe[1], "passw0rd\n", sizeof "passw0rd\n"); sigaction(SIGPIPE, &orig, NULL); if (read(result_pipe[0], read_buf, read_nbyte) == (ssize_t) -1) CU_FAIL_FATAL("Nothing written to pipe"); CU_ASSERT_STRING_EQUAL(read_buf, "passw0rd"); close(stderr_pipe[0]); close(stdin_pipe[1]); return; } void test_passphrase_read(void) { passphrase_read_prompts_to_tty(); passphrase_read_reads_from_tty(); passphrase_read_turns_off_echo_during_read(); passphrase_read_resets_terminal_after_read(); passphrase_read_turns_on_newline_echo_during_read(); passphrase_read_prompts_to_stderr_when_no_tty(); passphrase_read_reads_from_stdin_when_no_tty(); } void handle_signals_resets_terminal(void) { int status, masterfd; char* slavedevice; struct termios test_flags; pid_t child_pid; masterfd = posix_openpt(O_RDWR|O_NOCTTY); if (masterfd == -1 || grantpt (masterfd) == -1 || unlockpt (masterfd) == -1 || (slavedevice = ptsname (masterfd)) == NULL) CU_FAIL_FATAL("Could not create pty"); terminal_fildes = open(slavedevice, O_RDWR|O_NOCTTY); tcgetattr(terminal_fildes, &orig_flags); new_flags = orig_flags; new_flags.c_lflag &= ~ECHO; tcsetattr(terminal_fildes, TCSANOW, &new_flags); terminal_needs_reset = 1; if((child_pid = fork()) == 0) { freerdp_handle_signals(); raise(SIGINT); } while(wait(&status) != -1); tcgetattr(terminal_fildes, &test_flags); CU_ASSERT_EQUAL(orig_flags.c_lflag, test_flags.c_lflag); close(masterfd); close(terminal_fildes); } void test_handle_signals(void) { handle_signals_resets_terminal(); } FreeRDP-1.0.2/cunit/test_utils.h000066400000000000000000000017051207112532300164320ustar00rootroot00000000000000/** * FreeRDP: A Remote Desktop Protocol Client * Utils Unit Tests * * Copyright 2011 Vic Lee * * 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. */ #include "test_freerdp.h" int init_utils_suite(void); int clean_utils_suite(void); int add_utils_suite(void); void test_mutex(void); void test_semaphore(void); void test_load_plugin(void); void test_wait_obj(void); void test_args(void); void test_passphrase_read(void); void test_handle_signals(void); FreeRDP-1.0.2/docs/000077500000000000000000000000001207112532300136655ustar00rootroot00000000000000FreeRDP-1.0.2/docs/Doxyfile000066400000000000000000001737171207112532300154130ustar00rootroot00000000000000# Doxyfile 1.6.1 # This file describes the settings to be used by the documentation system # doxygen (www.doxygen.org) for a project # # All text after a hash (#) is considered a comment and will be ignored # The format is: # TAG = value [value, ...] # For lists items can also be appended using: # TAG += value [value, ...] # Values that contain spaces should be placed between quotes (" ") #--------------------------------------------------------------------------- # Project related configuration options #--------------------------------------------------------------------------- # This tag specifies the encoding used for all characters in the config file # that follow. The default is UTF-8 which is also the encoding used for all # text before the first occurrence of this tag. Doxygen uses libiconv (or the # iconv built into libc) for the transcoding. See # http://www.gnu.org/software/libiconv for the list of possible encodings. DOXYFILE_ENCODING = UTF-8 # The PROJECT_NAME tag is a single word (or a sequence of words surrounded # by quotes) that should identify the project. PROJECT_NAME = FreeRDP # The PROJECT_NUMBER tag can be used to enter a project or revision number. # This could be handy for archiving the generated documentation or # if some version control system is used. PROJECT_NUMBER = # The OUTPUT_DIRECTORY tag is used to specify the (relative or absolute) # base path where the generated documentation will be put. # If a relative path is entered, it will be relative to the location # where doxygen was started. If left blank the current directory will be used. OUTPUT_DIRECTORY = # If the CREATE_SUBDIRS tag is set to YES, then doxygen will create # 4096 sub-directories (in 2 levels) under the output directory of each output # format and will distribute the generated files over these directories. # Enabling this option can be useful when feeding doxygen a huge amount of # source files, where putting all generated files in the same directory would # otherwise cause performance problems for the file system. CREATE_SUBDIRS = NO # The OUTPUT_LANGUAGE tag is used to specify the language in which all # documentation generated by doxygen is written. Doxygen will use this # information to generate all constant output in the proper language. # The default language is English, other supported languages are: # Afrikaans, Arabic, Brazilian, Catalan, Chinese, Chinese-Traditional, # Croatian, Czech, Danish, Dutch, Esperanto, Farsi, Finnish, French, German, # Greek, Hungarian, Italian, Japanese, Japanese-en (Japanese with English # messages), Korean, Korean-en, Lithuanian, Norwegian, Macedonian, Persian, # Polish, Portuguese, Romanian, Russian, Serbian, Serbian-Cyrilic, Slovak, # Slovene, Spanish, Swedish, Ukrainian, and Vietnamese. OUTPUT_LANGUAGE = English # If the BRIEF_MEMBER_DESC tag is set to YES (the default) Doxygen will # include brief member descriptions after the members that are listed in # the file and class documentation (similar to JavaDoc). # Set to NO to disable this. BRIEF_MEMBER_DESC = YES # If the REPEAT_BRIEF tag is set to YES (the default) Doxygen will prepend # the brief description of a member or function before the detailed description. # Note: if both HIDE_UNDOC_MEMBERS and BRIEF_MEMBER_DESC are set to NO, the # brief descriptions will be completely suppressed. REPEAT_BRIEF = YES # This tag implements a quasi-intelligent brief description abbreviator # that is used to form the text in various listings. Each string # in this list, if found as the leading text of the brief description, will be # stripped from the text and the result after processing the whole list, is # used as the annotated text. Otherwise, the brief description is used as-is. # If left blank, the following values are used ("$name" is automatically # replaced with the name of the entity): "The $name class" "The $name widget" # "The $name file" "is" "provides" "specifies" "contains" # "represents" "a" "an" "the" ABBREVIATE_BRIEF = # If the ALWAYS_DETAILED_SEC and REPEAT_BRIEF tags are both set to YES then # Doxygen will generate a detailed section even if there is only a brief # description. ALWAYS_DETAILED_SEC = NO # If the INLINE_INHERITED_MEMB tag is set to YES, doxygen will show all # inherited members of a class in the documentation of that class as if those # members were ordinary class members. Constructors, destructors and assignment # operators of the base classes will not be shown. INLINE_INHERITED_MEMB = NO # If the FULL_PATH_NAMES tag is set to YES then Doxygen will prepend the full # path before files name in the file list and in the header files. If set # to NO the shortest path that makes the file name unique will be used. FULL_PATH_NAMES = NO # If the FULL_PATH_NAMES tag is set to YES then the STRIP_FROM_PATH tag # can be used to strip a user-defined part of the path. Stripping is # only done if one of the specified strings matches the left-hand part of # the path. The tag can be used to show relative paths in the file list. # If left blank the directory from which doxygen is run is used as the # path to strip. STRIP_FROM_PATH = # The STRIP_FROM_INC_PATH tag can be used to strip a user-defined part of # the path mentioned in the documentation of a class, which tells # the reader which header file to include in order to use a class. # If left blank only the name of the header file containing the class # definition is used. Otherwise one should specify the include paths that # are normally passed to the compiler using the -I flag. STRIP_FROM_INC_PATH = # If the SHORT_NAMES tag is set to YES, doxygen will generate much shorter # (but less readable) file names. This can be useful is your file systems # doesn't support long names like on DOS, Mac, or CD-ROM. SHORT_NAMES = NO # If the JAVADOC_AUTOBRIEF tag is set to YES then Doxygen # will interpret the first line (until the first dot) of a JavaDoc-style # comment as the brief description. If set to NO, the JavaDoc # comments will behave just like regular Qt-style comments # (thus requiring an explicit @brief command for a brief description.) JAVADOC_AUTOBRIEF = NO # If the QT_AUTOBRIEF tag is set to YES then Doxygen will # interpret the first line (until the first dot) of a Qt-style # comment as the brief description. If set to NO, the comments # will behave just like regular Qt-style comments (thus requiring # an explicit \brief command for a brief description.) QT_AUTOBRIEF = NO # The MULTILINE_CPP_IS_BRIEF tag can be set to YES to make Doxygen # treat a multi-line C++ special comment block (i.e. a block of //! or /// # comments) as a brief description. This used to be the default behaviour. # The new default is to treat a multi-line C++ comment block as a detailed # description. Set this tag to YES if you prefer the old behaviour instead. MULTILINE_CPP_IS_BRIEF = NO # If the INHERIT_DOCS tag is set to YES (the default) then an undocumented # member inherits the documentation from any documented member that it # re-implements. INHERIT_DOCS = YES # If the SEPARATE_MEMBER_PAGES tag is set to YES, then doxygen will produce # a new page for each member. If set to NO, the documentation of a member will # be part of the file/class/namespace that contains it. SEPARATE_MEMBER_PAGES = NO # The TAB_SIZE tag can be used to set the number of spaces in a tab. # Doxygen uses this value to replace tabs by spaces in code fragments. TAB_SIZE = 8 # This tag can be used to specify a number of aliases that acts # as commands in the documentation. An alias has the form "name=value". # For example adding "sideeffect=\par Side Effects:\n" will allow you to # put the command \sideeffect (or @sideeffect) in the documentation, which # will result in a user-defined paragraph with heading "Side Effects:". # You can put \n's in the value part of an alias to insert newlines. ALIASES = \ msdn{1}="http://msdn.microsoft.com/en-us/library/\1/" # Set the OPTIMIZE_OUTPUT_FOR_C tag to YES if your project consists of C # sources only. Doxygen will then generate output that is more tailored for C. # For instance, some of the names that are used will be different. The list # of all members will be omitted, etc. OPTIMIZE_OUTPUT_FOR_C = YES # Set the OPTIMIZE_OUTPUT_JAVA tag to YES if your project consists of Java # sources only. Doxygen will then generate output that is more tailored for # Java. For instance, namespaces will be presented as packages, qualified # scopes will look different, etc. OPTIMIZE_OUTPUT_JAVA = NO # Set the OPTIMIZE_FOR_FORTRAN tag to YES if your project consists of Fortran # sources only. Doxygen will then generate output that is more tailored for # Fortran. OPTIMIZE_FOR_FORTRAN = NO # Set the OPTIMIZE_OUTPUT_VHDL tag to YES if your project consists of VHDL # sources. Doxygen will then generate output that is tailored for # VHDL. OPTIMIZE_OUTPUT_VHDL = NO # Doxygen selects the parser to use depending on the extension of the files it parses. # With this tag you can assign which parser to use for a given extension. # Doxygen has a built-in mapping, but you can override or extend it using this tag. # The format is ext=language, where ext is a file extension, and language is one of # the parsers supported by doxygen: IDL, Java, Javascript, C#, C, C++, D, PHP, # Objective-C, Python, Fortran, VHDL, C, C++. For instance to make doxygen treat # .inc files as Fortran files (default is PHP), and .f files as C (default is Fortran), # use: inc=Fortran f=C. Note that for custom extensions you also need to set FILE_PATTERNS otherwise the files are not read by doxygen. EXTENSION_MAPPING = # If you use STL classes (i.e. std::string, std::vector, etc.) but do not want # to include (a tag file for) the STL sources as input, then you should # set this tag to YES in order to let doxygen match functions declarations and # definitions whose arguments contain STL classes (e.g. func(std::string); v.s. # func(std::string) {}). This also make the inheritance and collaboration # diagrams that involve STL classes more complete and accurate. BUILTIN_STL_SUPPORT = NO # If you use Microsoft's C++/CLI language, you should set this option to YES to # enable parsing support. CPP_CLI_SUPPORT = NO # Set the SIP_SUPPORT tag to YES if your project consists of sip sources only. # Doxygen will parse them like normal C++ but will assume all classes use public # instead of private inheritance when no explicit protection keyword is present. SIP_SUPPORT = NO # For Microsoft's IDL there are propget and propput attributes to indicate getter # and setter methods for a property. Setting this option to YES (the default) # will make doxygen to replace the get and set methods by a property in the # documentation. This will only work if the methods are indeed getting or # setting a simple type. If this is not the case, or you want to show the # methods anyway, you should set this option to NO. IDL_PROPERTY_SUPPORT = YES # If member grouping is used in the documentation and the DISTRIBUTE_GROUP_DOC # tag is set to YES, then doxygen will reuse the documentation of the first # member in the group (if any) for the other members of the group. By default # all members of a group must be documented explicitly. DISTRIBUTE_GROUP_DOC = NO # Set the SUBGROUPING tag to YES (the default) to allow class member groups of # the same type (for instance a group of public functions) to be put as a # subgroup of that type (e.g. under the Public Functions section). Set it to # NO to prevent subgrouping. Alternatively, this can be done per class using # the \nosubgrouping command. SUBGROUPING = YES # When TYPEDEF_HIDES_STRUCT is enabled, a typedef of a struct, union, or enum # is documented as struct, union, or enum with the name of the typedef. So # typedef struct TypeS {} TypeT, will appear in the documentation as a struct # with name TypeT. When disabled the typedef will appear as a member of a file, # namespace, or class. And the struct will be named TypeS. This can typically # be useful for C code in case the coding convention dictates that all compound # types are typedef'ed and only the typedef is referenced, never the tag name. TYPEDEF_HIDES_STRUCT = YES # The SYMBOL_CACHE_SIZE determines the size of the internal cache use to # determine which symbols to keep in memory and which to flush to disk. # When the cache is full, less often used symbols will be written to disk. # For small to medium size projects (<1000 input files) the default value is # probably good enough. For larger projects a too small cache size can cause # doxygen to be busy swapping symbols to and from disk most of the time # causing a significant performance penality. # If the system has enough physical memory increasing the cache will improve the # performance by keeping more symbols in memory. Note that the value works on # a logarithmic scale so increasing the size by one will rougly double the # memory usage. The cache size is given by this formula: # 2^(16+SYMBOL_CACHE_SIZE). The valid range is 0..9, the default is 0, # corresponding to a cache size of 2^16 = 65536 symbols SYMBOL_CACHE_SIZE = 0 #--------------------------------------------------------------------------- # Build related configuration options #--------------------------------------------------------------------------- # If the EXTRACT_ALL tag is set to YES doxygen will assume all entities in # documentation are documented, even if no documentation was available. # Private class members and static file members will be hidden unless # the EXTRACT_PRIVATE and EXTRACT_STATIC tags are set to YES EXTRACT_ALL = YES # If the EXTRACT_PRIVATE tag is set to YES all private members of a class # will be included in the documentation. EXTRACT_PRIVATE = NO # If the EXTRACT_STATIC tag is set to YES all static members of a file # will be included in the documentation. EXTRACT_STATIC = YES # If the EXTRACT_LOCAL_CLASSES tag is set to YES classes (and structs) # defined locally in source files will be included in the documentation. # If set to NO only classes defined in header files are included. EXTRACT_LOCAL_CLASSES = NO # This flag is only useful for Objective-C code. When set to YES local # methods, which are defined in the implementation section but not in # the interface are included in the documentation. # If set to NO (the default) only methods in the interface are included. EXTRACT_LOCAL_METHODS = NO # If this flag is set to YES, the members of anonymous namespaces will be # extracted and appear in the documentation as a namespace called # 'anonymous_namespace{file}', where file will be replaced with the base # name of the file that contains the anonymous namespace. By default # anonymous namespace are hidden. EXTRACT_ANON_NSPACES = NO # If the HIDE_UNDOC_MEMBERS tag is set to YES, Doxygen will hide all # undocumented members of documented classes, files or namespaces. # If set to NO (the default) these members will be included in the # various overviews, but no documentation section is generated. # This option has no effect if EXTRACT_ALL is enabled. HIDE_UNDOC_MEMBERS = NO # If the HIDE_UNDOC_CLASSES tag is set to YES, Doxygen will hide all # undocumented classes that are normally visible in the class hierarchy. # If set to NO (the default) these classes will be included in the various # overviews. This option has no effect if EXTRACT_ALL is enabled. HIDE_UNDOC_CLASSES = NO # If the HIDE_FRIEND_COMPOUNDS tag is set to YES, Doxygen will hide all # friend (class|struct|union) declarations. # If set to NO (the default) these declarations will be included in the # documentation. HIDE_FRIEND_COMPOUNDS = NO # If the HIDE_IN_BODY_DOCS tag is set to YES, Doxygen will hide any # documentation blocks found inside the body of a function. # If set to NO (the default) these blocks will be appended to the # function's detailed documentation block. HIDE_IN_BODY_DOCS = NO # The INTERNAL_DOCS tag determines if documentation # that is typed after a \internal command is included. If the tag is set # to NO (the default) then the documentation will be excluded. # Set it to YES to include the internal documentation. INTERNAL_DOCS = NO # If the CASE_SENSE_NAMES tag is set to NO then Doxygen will only generate # file names in lower-case letters. If set to YES upper-case letters are also # allowed. This is useful if you have classes or files whose names only differ # in case and if your file system supports case sensitive file names. Windows # and Mac users are advised to set this option to NO. CASE_SENSE_NAMES = YES # If the HIDE_SCOPE_NAMES tag is set to NO (the default) then Doxygen # will show members with their full class and namespace scopes in the # documentation. If set to YES the scope will be hidden. HIDE_SCOPE_NAMES = NO # If the SHOW_INCLUDE_FILES tag is set to YES (the default) then Doxygen # will put a list of the files that are included by a file in the documentation # of that file. SHOW_INCLUDE_FILES = YES # If the INLINE_INFO tag is set to YES (the default) then a tag [inline] # is inserted in the documentation for inline members. INLINE_INFO = YES # If the SORT_MEMBER_DOCS tag is set to YES (the default) then doxygen # will sort the (detailed) documentation of file and class members # alphabetically by member name. If set to NO the members will appear in # declaration order. SORT_MEMBER_DOCS = YES # If the SORT_BRIEF_DOCS tag is set to YES then doxygen will sort the # brief documentation of file, namespace and class members alphabetically # by member name. If set to NO (the default) the members will appear in # declaration order. SORT_BRIEF_DOCS = NO # If the SORT_MEMBERS_CTORS_1ST tag is set to YES then doxygen will sort the (brief and detailed) documentation of class members so that constructors and destructors are listed first. If set to NO (the default) the constructors will appear in the respective orders defined by SORT_MEMBER_DOCS and SORT_BRIEF_DOCS. This tag will be ignored for brief docs if SORT_BRIEF_DOCS is set to NO and ignored for detailed docs if SORT_MEMBER_DOCS is set to NO. SORT_MEMBERS_CTORS_1ST = NO # If the SORT_GROUP_NAMES tag is set to YES then doxygen will sort the # hierarchy of group names into alphabetical order. If set to NO (the default) # the group names will appear in their defined order. SORT_GROUP_NAMES = NO # If the SORT_BY_SCOPE_NAME tag is set to YES, the class list will be # sorted by fully-qualified names, including namespaces. If set to # NO (the default), the class list will be sorted only by class name, # not including the namespace part. # Note: This option is not very useful if HIDE_SCOPE_NAMES is set to YES. # Note: This option applies only to the class list, not to the # alphabetical list. SORT_BY_SCOPE_NAME = NO # The GENERATE_TODOLIST tag can be used to enable (YES) or # disable (NO) the todo list. This list is created by putting \todo # commands in the documentation. GENERATE_TODOLIST = NO # The GENERATE_TESTLIST tag can be used to enable (YES) or # disable (NO) the test list. This list is created by putting \test # commands in the documentation. GENERATE_TESTLIST = NO # The GENERATE_BUGLIST tag can be used to enable (YES) or # disable (NO) the bug list. This list is created by putting \bug # commands in the documentation. GENERATE_BUGLIST = NO # The GENERATE_DEPRECATEDLIST tag can be used to enable (YES) or # disable (NO) the deprecated list. This list is created by putting # \deprecated commands in the documentation. GENERATE_DEPRECATEDLIST= NO # The ENABLED_SECTIONS tag can be used to enable conditional # documentation sections, marked by \if sectionname ... \endif. ENABLED_SECTIONS = YES # The MAX_INITIALIZER_LINES tag determines the maximum number of lines # the initial value of a variable or define consists of for it to appear in # the documentation. If the initializer consists of more lines than specified # here it will be hidden. Use a value of 0 to hide initializers completely. # The appearance of the initializer of individual variables and defines in the # documentation can be controlled using \showinitializer or \hideinitializer # command in the documentation regardless of this setting. MAX_INITIALIZER_LINES = 30 # Set the SHOW_USED_FILES tag to NO to disable the list of files generated # at the bottom of the documentation of classes and structs. If set to YES the # list will mention the files that were used to generate the documentation. SHOW_USED_FILES = YES # If the sources in your project are distributed over multiple directories # then setting the SHOW_DIRECTORIES tag to YES will show the directory hierarchy # in the documentation. The default is NO. SHOW_DIRECTORIES = YES # Set the SHOW_FILES tag to NO to disable the generation of the Files page. # This will remove the Files entry from the Quick Index and from the # Folder Tree View (if specified). The default is YES. SHOW_FILES = YES # Set the SHOW_NAMESPACES tag to NO to disable the generation of the # Namespaces page. # This will remove the Namespaces entry from the Quick Index # and from the Folder Tree View (if specified). The default is YES. SHOW_NAMESPACES = YES # The FILE_VERSION_FILTER tag can be used to specify a program or script that # doxygen should invoke to get the current version for each file (typically from # the version control system). Doxygen will invoke the program by executing (via # popen()) the command , where is the value of # the FILE_VERSION_FILTER tag, and is the name of an input file # provided by doxygen. Whatever the program writes to standard output # is used as the file version. See the manual for examples. FILE_VERSION_FILTER = # The LAYOUT_FILE tag can be used to specify a layout file which will be parsed by # doxygen. The layout file controls the global structure of the generated output files # in an output format independent way. The create the layout file that represents # doxygen's defaults, run doxygen with the -l option. You can optionally specify a # file name after the option, if omitted DoxygenLayout.xml will be used as the name # of the layout file. LAYOUT_FILE = #--------------------------------------------------------------------------- # configuration options related to warning and progress messages #--------------------------------------------------------------------------- # The QUIET tag can be used to turn on/off the messages that are generated # by doxygen. Possible values are YES and NO. If left blank NO is used. QUIET = NO # The WARNINGS tag can be used to turn on/off the warning messages that are # generated by doxygen. Possible values are YES and NO. If left blank # NO is used. WARNINGS = YES # If WARN_IF_UNDOCUMENTED is set to YES, then doxygen will generate warnings # for undocumented members. If EXTRACT_ALL is set to YES then this flag will # automatically be disabled. WARN_IF_UNDOCUMENTED = YES # If WARN_IF_DOC_ERROR is set to YES, doxygen will generate warnings for # potential errors in the documentation, such as not documenting some # parameters in a documented function, or documenting parameters that # don't exist or using markup commands wrongly. WARN_IF_DOC_ERROR = YES # This WARN_NO_PARAMDOC option can be abled to get warnings for # functions that are documented, but have no documentation for their parameters # or return value. If set to NO (the default) doxygen will only warn about # wrong or incomplete parameter documentation, but not about the absence of # documentation. WARN_NO_PARAMDOC = NO # The WARN_FORMAT tag determines the format of the warning messages that # doxygen can produce. The string should contain the $file, $line, and $text # tags, which will be replaced by the file and line number from which the # warning originated and the warning text. Optionally the format may contain # $version, which will be replaced by the version of the file (if it could # be obtained via FILE_VERSION_FILTER) WARN_FORMAT = "$file:$line: $text" # The WARN_LOGFILE tag can be used to specify a file to which warning # and error messages should be written. If left blank the output is written # to stderr. WARN_LOGFILE = #--------------------------------------------------------------------------- # configuration options related to the input files #--------------------------------------------------------------------------- # The INPUT tag can be used to specify the files and/or directories that contain # documented source files. You may enter file names like "myfile.cpp" or # directories like "/usr/src/myproject". Separate the files or directories # with spaces. INPUT = .. # This tag can be used to specify the character encoding of the source files # that doxygen parses. Internally doxygen uses the UTF-8 encoding, which is # also the default input encoding. Doxygen uses libiconv (or the iconv built # into libc) for the transcoding. See http://www.gnu.org/software/libiconv for # the list of possible encodings. INPUT_ENCODING = UTF-8 # If the value of the INPUT tag contains directories, you can use the # FILE_PATTERNS tag to specify one or more wildcard pattern (like *.cpp # and *.h) to filter out the source-files in the directories. If left # blank the following patterns are tested: # *.c *.cc *.cxx *.cpp *.c++ *.java *.ii *.ixx *.ipp *.i++ *.inl *.h *.hh *.hxx # *.hpp *.h++ *.idl *.odl *.cs *.php *.php3 *.inc *.m *.mm *.py *.f90 FILE_PATTERNS = # The RECURSIVE tag can be used to turn specify whether or not subdirectories # should be searched for input files as well. Possible values are YES and NO. # If left blank NO is used. RECURSIVE = YES # The EXCLUDE tag can be used to specify files and/or directories that should # excluded from the INPUT source files. This way you can easily exclude a # subdirectory from a directory tree whose root is specified with the INPUT tag. EXCLUDE = ../build ../cmake ../CMakeFiles ../cunit ../docs ../keymaps ../resources # The EXCLUDE_SYMLINKS tag can be used select whether or not files or # directories that are symbolic links (a Unix filesystem feature) are excluded # from the input. EXCLUDE_SYMLINKS = NO # If the value of the INPUT tag contains directories, you can use the # EXCLUDE_PATTERNS tag to specify one or more wildcard patterns to exclude # certain files from those directories. Note that the wildcards are matched # against the file with absolute path, so to exclude all test directories # for example use the pattern */test/* EXCLUDE_PATTERNS = # The EXCLUDE_SYMBOLS tag can be used to specify one or more symbol names # (namespaces, classes, functions, etc.) that should be excluded from the # output. The symbol name can be a fully qualified name, a word, or if the # wildcard * is used, a substring. Examples: ANamespace, AClass, # AClass::ANamespace, ANamespace::*Test EXCLUDE_SYMBOLS = # The EXAMPLE_PATH tag can be used to specify one or more files or # directories that contain example code fragments that are included (see # the \include command). EXAMPLE_PATH = # If the value of the EXAMPLE_PATH tag contains directories, you can use the # EXAMPLE_PATTERNS tag to specify one or more wildcard pattern (like *.cpp # and *.h) to filter out the source-files in the directories. If left # blank all files are included. EXAMPLE_PATTERNS = # If the EXAMPLE_RECURSIVE tag is set to YES then subdirectories will be # searched for input files to be used with the \include or \dontinclude # commands irrespective of the value of the RECURSIVE tag. # Possible values are YES and NO. If left blank NO is used. EXAMPLE_RECURSIVE = NO # The IMAGE_PATH tag can be used to specify one or more files or # directories that contain image that are included in the documentation (see # the \image command). IMAGE_PATH = # The INPUT_FILTER tag can be used to specify a program that doxygen should # invoke to filter for each input file. Doxygen will invoke the filter program # by executing (via popen()) the command , where # is the value of the INPUT_FILTER tag, and is the name of an # input file. Doxygen will then use the output that the filter program writes # to standard output. # If FILTER_PATTERNS is specified, this tag will be # ignored. INPUT_FILTER = # The FILTER_PATTERNS tag can be used to specify filters on a per file pattern # basis. # Doxygen will compare the file name with each pattern and apply the # filter if there is a match. # The filters are a list of the form: # pattern=filter (like *.cpp=my_cpp_filter). See INPUT_FILTER for further # info on how filters are used. If FILTER_PATTERNS is empty, INPUT_FILTER # is applied to all files. FILTER_PATTERNS = # If the FILTER_SOURCE_FILES tag is set to YES, the input filter (if set using # INPUT_FILTER) will be used to filter the input files when producing source # files to browse (i.e. when SOURCE_BROWSER is set to YES). FILTER_SOURCE_FILES = NO #--------------------------------------------------------------------------- # configuration options related to source browsing #--------------------------------------------------------------------------- # If the SOURCE_BROWSER tag is set to YES then a list of source files will # be generated. Documented entities will be cross-referenced with these sources. # Note: To get rid of all source code in the generated output, make sure also # VERBATIM_HEADERS is set to NO. SOURCE_BROWSER = NO # Setting the INLINE_SOURCES tag to YES will include the body # of functions and classes directly in the documentation. INLINE_SOURCES = NO # Setting the STRIP_CODE_COMMENTS tag to YES (the default) will instruct # doxygen to hide any special comment blocks from generated source code # fragments. Normal C and C++ comments will always remain visible. STRIP_CODE_COMMENTS = YES # If the REFERENCED_BY_RELATION tag is set to YES # then for each documented function all documented # functions referencing it will be listed. REFERENCED_BY_RELATION = NO # If the REFERENCES_RELATION tag is set to YES # then for each documented function all documented entities # called/used by that function will be listed. REFERENCES_RELATION = NO # If the REFERENCES_LINK_SOURCE tag is set to YES (the default) # and SOURCE_BROWSER tag is set to YES, then the hyperlinks from # functions in REFERENCES_RELATION and REFERENCED_BY_RELATION lists will # link to the source code. # Otherwise they will link to the documentation. REFERENCES_LINK_SOURCE = YES # If the USE_HTAGS tag is set to YES then the references to source code # will point to the HTML generated by the htags(1) tool instead of doxygen # built-in source browser. The htags tool is part of GNU's global source # tagging system (see http://www.gnu.org/software/global/global.html). You # will need version 4.8.6 or higher. USE_HTAGS = NO # If the VERBATIM_HEADERS tag is set to YES (the default) then Doxygen # will generate a verbatim copy of the header file for each class for # which an include is specified. Set to NO to disable this. VERBATIM_HEADERS = NO #--------------------------------------------------------------------------- # configuration options related to the alphabetical class index #--------------------------------------------------------------------------- # If the ALPHABETICAL_INDEX tag is set to YES, an alphabetical index # of all compounds will be generated. Enable this if the project # contains a lot of classes, structs, unions or interfaces. ALPHABETICAL_INDEX = NO # If the alphabetical index is enabled (see ALPHABETICAL_INDEX) then # the COLS_IN_ALPHA_INDEX tag can be used to specify the number of columns # in which this list will be split (can be a number in the range [1..20]) COLS_IN_ALPHA_INDEX = 5 # In case all classes in a project start with a common prefix, all # classes will be put under the same header in the alphabetical index. # The IGNORE_PREFIX tag can be used to specify one or more prefixes that # should be ignored while generating the index headers. IGNORE_PREFIX = #--------------------------------------------------------------------------- # configuration options related to the HTML output #--------------------------------------------------------------------------- # If the GENERATE_HTML tag is set to YES (the default) Doxygen will # generate HTML output. GENERATE_HTML = YES # The HTML_OUTPUT tag is used to specify where the HTML docs will be put. # If a relative path is entered the value of OUTPUT_DIRECTORY will be # put in front of it. If left blank `html' will be used as the default path. HTML_OUTPUT = api # The HTML_FILE_EXTENSION tag can be used to specify the file extension for # each generated HTML page (for example: .htm,.php,.asp). If it is left blank # doxygen will generate files with .html extension. HTML_FILE_EXTENSION = .html # The HTML_HEADER tag can be used to specify a personal HTML header for # each generated HTML page. If it is left blank doxygen will generate a # standard header. HTML_HEADER = # The HTML_FOOTER tag can be used to specify a personal HTML footer for # each generated HTML page. If it is left blank doxygen will generate a # standard footer. HTML_FOOTER = # The HTML_STYLESHEET tag can be used to specify a user-defined cascading # style sheet that is used by each HTML page. It can be used to # fine-tune the look of the HTML output. If the tag is left blank doxygen # will generate a default style sheet. Note that doxygen will try to copy # the style sheet file to the HTML output directory, so don't put your own # stylesheet in the HTML output directory as well, or it will be erased! HTML_STYLESHEET = # If the HTML_ALIGN_MEMBERS tag is set to YES, the members of classes, # files or namespaces will be aligned in HTML using tables. If set to # NO a bullet list will be used. HTML_ALIGN_MEMBERS = YES # If the HTML_DYNAMIC_SECTIONS tag is set to YES then the generated HTML # documentation will contain sections that can be hidden and shown after the # page has loaded. For this to work a browser that supports # JavaScript and DHTML is required (for instance Mozilla 1.0+, Firefox # Netscape 6.0+, Internet explorer 5.0+, Konqueror, or Safari). HTML_DYNAMIC_SECTIONS = NO # If the GENERATE_DOCSET tag is set to YES, additional index files # will be generated that can be used as input for Apple's Xcode 3 # integrated development environment, introduced with OSX 10.5 (Leopard). # To create a documentation set, doxygen will generate a Makefile in the # HTML output directory. Running make will produce the docset in that # directory and running "make install" will install the docset in # ~/Library/Developer/Shared/Documentation/DocSets so that Xcode will find # it at startup. # See http://developer.apple.com/tools/creatingdocsetswithdoxygen.html for more information. GENERATE_DOCSET = NO # When GENERATE_DOCSET tag is set to YES, this tag determines the name of the # feed. A documentation feed provides an umbrella under which multiple # documentation sets from a single provider (such as a company or product suite) # can be grouped. DOCSET_FEEDNAME = "Doxygen generated docs" # When GENERATE_DOCSET tag is set to YES, this tag specifies a string that # should uniquely identify the documentation set bundle. This should be a # reverse domain-name style string, e.g. com.mycompany.MyDocSet. Doxygen # will append .docset to the name. DOCSET_BUNDLE_ID = org.doxygen.freerdp # If the GENERATE_HTMLHELP tag is set to YES, additional index files # will be generated that can be used as input for tools like the # Microsoft HTML help workshop to generate a compiled HTML help file (.chm) # of the generated HTML documentation. GENERATE_HTMLHELP = NO # If the GENERATE_HTMLHELP tag is set to YES, the CHM_FILE tag can # be used to specify the file name of the resulting .chm file. You # can add a path in front of the file if the result should not be # written to the html output directory. CHM_FILE = # If the GENERATE_HTMLHELP tag is set to YES, the HHC_LOCATION tag can # be used to specify the location (absolute path including file name) of # the HTML help compiler (hhc.exe). If non-empty doxygen will try to run # the HTML help compiler on the generated index.hhp. HHC_LOCATION = # If the GENERATE_HTMLHELP tag is set to YES, the GENERATE_CHI flag # controls if a separate .chi index file is generated (YES) or that # it should be included in the master .chm file (NO). GENERATE_CHI = NO # If the GENERATE_HTMLHELP tag is set to YES, the CHM_INDEX_ENCODING # is used to encode HtmlHelp index (hhk), content (hhc) and project file # content. CHM_INDEX_ENCODING = # If the GENERATE_HTMLHELP tag is set to YES, the BINARY_TOC flag # controls whether a binary table of contents is generated (YES) or a # normal table of contents (NO) in the .chm file. BINARY_TOC = NO # The TOC_EXPAND flag can be set to YES to add extra items for group members # to the contents of the HTML help documentation and to the tree view. TOC_EXPAND = NO # If the GENERATE_QHP tag is set to YES and both QHP_NAMESPACE and QHP_VIRTUAL_FOLDER # are set, an additional index file will be generated that can be used as input for # Qt's qhelpgenerator to generate a Qt Compressed Help (.qch) of the generated # HTML documentation. GENERATE_QHP = NO # If the QHG_LOCATION tag is specified, the QCH_FILE tag can # be used to specify the file name of the resulting .qch file. # The path specified is relative to the HTML output folder. QCH_FILE = # The QHP_NAMESPACE tag specifies the namespace to use when generating # Qt Help Project output. For more information please see # http://doc.trolltech.com/qthelpproject.html#namespace QHP_NAMESPACE = # The QHP_VIRTUAL_FOLDER tag specifies the namespace to use when generating # Qt Help Project output. For more information please see # http://doc.trolltech.com/qthelpproject.html#virtual-folders QHP_VIRTUAL_FOLDER = doc # If QHP_CUST_FILTER_NAME is set, it specifies the name of a custom filter to add. # For more information please see # http://doc.trolltech.com/qthelpproject.html#custom-filters QHP_CUST_FILTER_NAME = # The QHP_CUST_FILT_ATTRS tag specifies the list of the attributes of the custom filter to add.For more information please see # Qt Help Project / Custom Filters. QHP_CUST_FILTER_ATTRS = # The QHP_SECT_FILTER_ATTRS tag specifies the list of the attributes this project's # filter section matches. # Qt Help Project / Filter Attributes. QHP_SECT_FILTER_ATTRS = # If the GENERATE_QHP tag is set to YES, the QHG_LOCATION tag can # be used to specify the location of Qt's qhelpgenerator. # If non-empty doxygen will try to run qhelpgenerator on the generated # .qhp file. QHG_LOCATION = # The DISABLE_INDEX tag can be used to turn on/off the condensed index at # top of each HTML page. The value NO (the default) enables the index and # the value YES disables it. DISABLE_INDEX = NO # This tag can be used to set the number of enum values (range [1..20]) # that doxygen will group on one line in the generated HTML documentation. ENUM_VALUES_PER_LINE = 4 # The GENERATE_TREEVIEW tag is used to specify whether a tree-like index # structure should be generated to display hierarchical information. # If the tag value is set to YES, a side panel will be generated # containing a tree-like index structure (just like the one that # is generated for HTML Help). For this to work a browser that supports # JavaScript, DHTML, CSS and frames is required (i.e. any modern browser). # Windows users are probably better off using the HTML help feature. GENERATE_TREEVIEW = YES # By enabling USE_INLINE_TREES, doxygen will generate the Groups, Directories, # and Class Hierarchy pages using a tree view instead of an ordered list. USE_INLINE_TREES = YES # If the treeview is enabled (see GENERATE_TREEVIEW) then this tag can be # used to set the initial width (in pixels) of the frame in which the tree # is shown. TREEVIEW_WIDTH = 250 # Use this tag to change the font size of Latex formulas included # as images in the HTML documentation. The default is 10. Note that # when you change the font size after a successful doxygen run you need # to manually remove any form_*.png images from the HTML output directory # to force them to be regenerated. FORMULA_FONTSIZE = 10 # When the SEARCHENGINE tag is enable doxygen will generate a search box for the HTML output. The underlying search engine uses javascript # and DHTML and should work on any modern browser. Note that when using HTML help (GENERATE_HTMLHELP) or Qt help (GENERATE_QHP) # there is already a search function so this one should typically # be disabled. SEARCHENGINE = YES #--------------------------------------------------------------------------- # configuration options related to the LaTeX output #--------------------------------------------------------------------------- # If the GENERATE_LATEX tag is set to YES (the default) Doxygen will # generate Latex output. GENERATE_LATEX = NO # The LATEX_OUTPUT tag is used to specify where the LaTeX docs will be put. # If a relative path is entered the value of OUTPUT_DIRECTORY will be # put in front of it. If left blank `latex' will be used as the default path. LATEX_OUTPUT = latex # The LATEX_CMD_NAME tag can be used to specify the LaTeX command name to be # invoked. If left blank `latex' will be used as the default command name. LATEX_CMD_NAME = latex # The MAKEINDEX_CMD_NAME tag can be used to specify the command name to # generate index for LaTeX. If left blank `makeindex' will be used as the # default command name. MAKEINDEX_CMD_NAME = makeindex # If the COMPACT_LATEX tag is set to YES Doxygen generates more compact # LaTeX documents. This may be useful for small projects and may help to # save some trees in general. COMPACT_LATEX = NO # The PAPER_TYPE tag can be used to set the paper type that is used # by the printer. Possible values are: a4, a4wide, letter, legal and # executive. If left blank a4wide will be used. PAPER_TYPE = a4wide # The EXTRA_PACKAGES tag can be to specify one or more names of LaTeX # packages that should be included in the LaTeX output. EXTRA_PACKAGES = # The LATEX_HEADER tag can be used to specify a personal LaTeX header for # the generated latex document. The header should contain everything until # the first chapter. If it is left blank doxygen will generate a # standard header. Notice: only use this tag if you know what you are doing! LATEX_HEADER = # If the PDF_HYPERLINKS tag is set to YES, the LaTeX that is generated # is prepared for conversion to pdf (using ps2pdf). The pdf file will # contain links (just like the HTML output) instead of page references # This makes the output suitable for online browsing using a pdf viewer. PDF_HYPERLINKS = YES # If the USE_PDFLATEX tag is set to YES, pdflatex will be used instead of # plain latex in the generated Makefile. Set this option to YES to get a # higher quality PDF documentation. USE_PDFLATEX = YES # If the LATEX_BATCHMODE tag is set to YES, doxygen will add the \\batchmode. # command to the generated LaTeX files. This will instruct LaTeX to keep # running if errors occur, instead of asking the user for help. # This option is also used when generating formulas in HTML. LATEX_BATCHMODE = NO # If LATEX_HIDE_INDICES is set to YES then doxygen will not # include the index chapters (such as File Index, Compound Index, etc.) # in the output. LATEX_HIDE_INDICES = NO # If LATEX_SOURCE_CODE is set to YES then doxygen will include source code with syntax highlighting in the LaTeX output. Note that which sources are shown also depends on other settings such as SOURCE_BROWSER. LATEX_SOURCE_CODE = NO #--------------------------------------------------------------------------- # configuration options related to the RTF output #--------------------------------------------------------------------------- # If the GENERATE_RTF tag is set to YES Doxygen will generate RTF output # The RTF output is optimized for Word 97 and may not look very pretty with # other RTF readers or editors. GENERATE_RTF = NO # The RTF_OUTPUT tag is used to specify where the RTF docs will be put. # If a relative path is entered the value of OUTPUT_DIRECTORY will be # put in front of it. If left blank `rtf' will be used as the default path. RTF_OUTPUT = rtf # If the COMPACT_RTF tag is set to YES Doxygen generates more compact # RTF documents. This may be useful for small projects and may help to # save some trees in general. COMPACT_RTF = NO # If the RTF_HYPERLINKS tag is set to YES, the RTF that is generated # will contain hyperlink fields. The RTF file will # contain links (just like the HTML output) instead of page references. # This makes the output suitable for online browsing using WORD or other # programs which support those fields. # Note: wordpad (write) and others do not support links. RTF_HYPERLINKS = NO # Load stylesheet definitions from file. Syntax is similar to doxygen's # config file, i.e. a series of assignments. You only have to provide # replacements, missing definitions are set to their default value. RTF_STYLESHEET_FILE = # Set optional variables used in the generation of an rtf document. # Syntax is similar to doxygen's config file. RTF_EXTENSIONS_FILE = #--------------------------------------------------------------------------- # configuration options related to the man page output #--------------------------------------------------------------------------- # If the GENERATE_MAN tag is set to YES (the default) Doxygen will # generate man pages GENERATE_MAN = NO # The MAN_OUTPUT tag is used to specify where the man pages will be put. # If a relative path is entered the value of OUTPUT_DIRECTORY will be # put in front of it. If left blank `man' will be used as the default path. MAN_OUTPUT = man # The MAN_EXTENSION tag determines the extension that is added to # the generated man pages (default is the subroutine's section .3) MAN_EXTENSION = .3 # If the MAN_LINKS tag is set to YES and Doxygen generates man output, # then it will generate one additional man file for each entity # documented in the real man page(s). These additional files # only source the real man page, but without them the man command # would be unable to find the correct page. The default is NO. MAN_LINKS = NO #--------------------------------------------------------------------------- # configuration options related to the XML output #--------------------------------------------------------------------------- # If the GENERATE_XML tag is set to YES Doxygen will # generate an XML file that captures the structure of # the code including all documentation. GENERATE_XML = NO # The XML_OUTPUT tag is used to specify where the XML pages will be put. # If a relative path is entered the value of OUTPUT_DIRECTORY will be # put in front of it. If left blank `xml' will be used as the default path. XML_OUTPUT = xml # The XML_SCHEMA tag can be used to specify an XML schema, # which can be used by a validating XML parser to check the # syntax of the XML files. XML_SCHEMA = # The XML_DTD tag can be used to specify an XML DTD, # which can be used by a validating XML parser to check the # syntax of the XML files. XML_DTD = # If the XML_PROGRAMLISTING tag is set to YES Doxygen will # dump the program listings (including syntax highlighting # and cross-referencing information) to the XML output. Note that # enabling this will significantly increase the size of the XML output. XML_PROGRAMLISTING = YES #--------------------------------------------------------------------------- # configuration options for the AutoGen Definitions output #--------------------------------------------------------------------------- # If the GENERATE_AUTOGEN_DEF tag is set to YES Doxygen will # generate an AutoGen Definitions (see autogen.sf.net) file # that captures the structure of the code including all # documentation. Note that this feature is still experimental # and incomplete at the moment. GENERATE_AUTOGEN_DEF = NO #--------------------------------------------------------------------------- # configuration options related to the Perl module output #--------------------------------------------------------------------------- # If the GENERATE_PERLMOD tag is set to YES Doxygen will # generate a Perl module file that captures the structure of # the code including all documentation. Note that this # feature is still experimental and incomplete at the # moment. GENERATE_PERLMOD = NO # If the PERLMOD_LATEX tag is set to YES Doxygen will generate # the necessary Makefile rules, Perl scripts and LaTeX code to be able # to generate PDF and DVI output from the Perl module output. PERLMOD_LATEX = NO # If the PERLMOD_PRETTY tag is set to YES the Perl module output will be # nicely formatted so it can be parsed by a human reader. # This is useful # if you want to understand what is going on. # On the other hand, if this # tag is set to NO the size of the Perl module output will be much smaller # and Perl will parse it just the same. PERLMOD_PRETTY = YES # The names of the make variables in the generated doxyrules.make file # are prefixed with the string contained in PERLMOD_MAKEVAR_PREFIX. # This is useful so different doxyrules.make files included by the same # Makefile don't overwrite each other's variables. PERLMOD_MAKEVAR_PREFIX = #--------------------------------------------------------------------------- # Configuration options related to the preprocessor #--------------------------------------------------------------------------- # If the ENABLE_PREPROCESSING tag is set to YES (the default) Doxygen will # evaluate all C-preprocessor directives found in the sources and include # files. ENABLE_PREPROCESSING = YES # If the MACRO_EXPANSION tag is set to YES Doxygen will expand all macro # names in the source code. If set to NO (the default) only conditional # compilation will be performed. Macro expansion can be done in a controlled # way by setting EXPAND_ONLY_PREDEF to YES. MACRO_EXPANSION = NO # If the EXPAND_ONLY_PREDEF and MACRO_EXPANSION tags are both set to YES # then the macro expansion is limited to the macros specified with the # PREDEFINED and EXPAND_AS_DEFINED tags. EXPAND_ONLY_PREDEF = NO # If the SEARCH_INCLUDES tag is set to YES (the default) the includes files # in the INCLUDE_PATH (see below) will be search if a #include is found. SEARCH_INCLUDES = YES # The INCLUDE_PATH tag can be used to specify one or more directories that # contain include files that are not input files but should be processed by # the preprocessor. INCLUDE_PATH = # You can use the INCLUDE_FILE_PATTERNS tag to specify one or more wildcard # patterns (like *.h and *.hpp) to filter out the header-files in the # directories. If left blank, the patterns specified with FILE_PATTERNS will # be used. INCLUDE_FILE_PATTERNS = # The PREDEFINED tag can be used to specify one or more macro names that # are defined before the preprocessor is started (similar to the -D option of # gcc). The argument of the tag is a list of macros of the form: name # or name=definition (no spaces). If the definition and the = are # omitted =1 is assumed. To prevent a macro definition from being # undefined via #undef or recursively expanded use the := operator # instead of the = operator. PREDEFINED = # If the MACRO_EXPANSION and EXPAND_ONLY_PREDEF tags are set to YES then # this tag can be used to specify a list of macro names that should be expanded. # The macro definition that is found in the sources will be used. # Use the PREDEFINED tag if you want to use a different macro definition. EXPAND_AS_DEFINED = # If the SKIP_FUNCTION_MACROS tag is set to YES (the default) then # doxygen's preprocessor will remove all function-like macros that are alone # on a line, have an all uppercase name, and do not end with a semicolon. Such # function macros are typically used for boiler-plate code, and will confuse # the parser if not removed. SKIP_FUNCTION_MACROS = YES #--------------------------------------------------------------------------- # Configuration::additions related to external references #--------------------------------------------------------------------------- # The TAGFILES option can be used to specify one or more tagfiles. # Optionally an initial location of the external documentation # can be added for each tagfile. The format of a tag file without # this location is as follows: # # TAGFILES = file1 file2 ... # Adding location for the tag files is done as follows: # # TAGFILES = file1=loc1 "file2 = loc2" ... # where "loc1" and "loc2" can be relative or absolute paths or # URLs. If a location is present for each tag, the installdox tool # does not have to be run to correct the links. # Note that each tag file must have a unique name # (where the name does NOT include the path) # If a tag file is not located in the directory in which doxygen # is run, you must also specify the path to the tagfile here. TAGFILES = # When a file name is specified after GENERATE_TAGFILE, doxygen will create # a tag file that is based on the input files it reads. GENERATE_TAGFILE = # If the ALLEXTERNALS tag is set to YES all external classes will be listed # in the class index. If set to NO only the inherited external classes # will be listed. ALLEXTERNALS = NO # If the EXTERNAL_GROUPS tag is set to YES all external groups will be listed # in the modules index. If set to NO, only the current project's groups will # be listed. EXTERNAL_GROUPS = YES # The PERL_PATH should be the absolute path and name of the perl script # interpreter (i.e. the result of `which perl'). PERL_PATH = /usr/bin/perl #--------------------------------------------------------------------------- # Configuration options related to the dot tool #--------------------------------------------------------------------------- # If the CLASS_DIAGRAMS tag is set to YES (the default) Doxygen will # generate a inheritance diagram (in HTML, RTF and LaTeX) for classes with base # or super classes. Setting the tag to NO turns the diagrams off. Note that # this option is superseded by the HAVE_DOT option below. This is only a # fallback. It is recommended to install and use dot, since it yields more # powerful graphs. CLASS_DIAGRAMS = YES # You can define message sequence charts within doxygen comments using the \msc # command. Doxygen will then run the mscgen tool (see # http://www.mcternan.me.uk/mscgen/) to produce the chart and insert it in the # documentation. The MSCGEN_PATH tag allows you to specify the directory where # the mscgen tool resides. If left empty the tool is assumed to be found in the # default search path. MSCGEN_PATH = # If set to YES, the inheritance and collaboration graphs will hide # inheritance and usage relations if the target is undocumented # or is not a class. HIDE_UNDOC_RELATIONS = YES # If you set the HAVE_DOT tag to YES then doxygen will assume the dot tool is # available from the path. This tool is part of Graphviz, a graph visualization # toolkit from AT&T and Lucent Bell Labs. The other options in this section # have no effect if this option is set to NO (the default) HAVE_DOT = YES # By default doxygen will write a font called FreeSans.ttf to the output # directory and reference it in all dot files that doxygen generates. This # font does not include all possible unicode characters however, so when you need # these (or just want a differently looking font) you can specify the font name # using DOT_FONTNAME. You need need to make sure dot is able to find the font, # which can be done by putting it in a standard location or by setting the # DOTFONTPATH environment variable or by setting DOT_FONTPATH to the directory # containing the font. DOT_FONTNAME = FreeSans # The DOT_FONTSIZE tag can be used to set the size of the font of dot graphs. # The default size is 10pt. DOT_FONTSIZE = 10 # By default doxygen will tell dot to use the output directory to look for the # FreeSans.ttf font (which doxygen will put there itself). If you specify a # different font using DOT_FONTNAME you can set the path where dot # can find it using this tag. DOT_FONTPATH = # If the CLASS_GRAPH and HAVE_DOT tags are set to YES then doxygen # will generate a graph for each documented class showing the direct and # indirect inheritance relations. Setting this tag to YES will force the # the CLASS_DIAGRAMS tag to NO. CLASS_GRAPH = YES # If the COLLABORATION_GRAPH and HAVE_DOT tags are set to YES then doxygen # will generate a graph for each documented class showing the direct and # indirect implementation dependencies (inheritance, containment, and # class references variables) of the class with other documented classes. COLLABORATION_GRAPH = YES # If the GROUP_GRAPHS and HAVE_DOT tags are set to YES then doxygen # will generate a graph for groups, showing the direct groups dependencies GROUP_GRAPHS = YES # If the UML_LOOK tag is set to YES doxygen will generate inheritance and # collaboration diagrams in a style similar to the OMG's Unified Modeling # Language. UML_LOOK = NO # If set to YES, the inheritance and collaboration graphs will show the # relations between templates and their instances. TEMPLATE_RELATIONS = NO # If the ENABLE_PREPROCESSING, SEARCH_INCLUDES, INCLUDE_GRAPH, and HAVE_DOT # tags are set to YES then doxygen will generate a graph for each documented # file showing the direct and indirect include dependencies of the file with # other documented files. INCLUDE_GRAPH = NO # If the ENABLE_PREPROCESSING, SEARCH_INCLUDES, INCLUDED_BY_GRAPH, and # HAVE_DOT tags are set to YES then doxygen will generate a graph for each # documented header file showing the documented files that directly or # indirectly include this file. INCLUDED_BY_GRAPH = YES # If the CALL_GRAPH and HAVE_DOT options are set to YES then # doxygen will generate a call dependency graph for every global function # or class method. Note that enabling this option will significantly increase # the time of a run. So in most cases it will be better to enable call graphs # for selected functions only using the \callgraph command. CALL_GRAPH = YES # If the CALLER_GRAPH and HAVE_DOT tags are set to YES then # doxygen will generate a caller dependency graph for every global function # or class method. Note that enabling this option will significantly increase # the time of a run. So in most cases it will be better to enable caller # graphs for selected functions only using the \callergraph command. CALLER_GRAPH = YES # If the GRAPHICAL_HIERARCHY and HAVE_DOT tags are set to YES then doxygen # will graphical hierarchy of all classes instead of a textual one. GRAPHICAL_HIERARCHY = YES # If the DIRECTORY_GRAPH, SHOW_DIRECTORIES and HAVE_DOT tags are set to YES # then doxygen will show the dependencies a directory has on other directories # in a graphical way. The dependency relations are determined by the #include # relations between the files in the directories. DIRECTORY_GRAPH = YES # The DOT_IMAGE_FORMAT tag can be used to set the image format of the images # generated by dot. Possible values are png, jpg, or gif # If left blank png will be used. DOT_IMAGE_FORMAT = png # The tag DOT_PATH can be used to specify the path where the dot tool can be # found. If left blank, it is assumed the dot tool can be found in the path. DOT_PATH = # The DOTFILE_DIRS tag can be used to specify one or more directories that # contain dot files that are included in the documentation (see the # \dotfile command). DOTFILE_DIRS = # The DOT_GRAPH_MAX_NODES tag can be used to set the maximum number of # nodes that will be shown in the graph. If the number of nodes in a graph # becomes larger than this value, doxygen will truncate the graph, which is # visualized by representing a node as a red box. Note that doxygen if the # number of direct children of the root node in a graph is already larger than # DOT_GRAPH_MAX_NODES then the graph will not be shown at all. Also note # that the size of a graph can be further restricted by MAX_DOT_GRAPH_DEPTH. DOT_GRAPH_MAX_NODES = 50 # The MAX_DOT_GRAPH_DEPTH tag can be used to set the maximum depth of the # graphs generated by dot. A depth value of 3 means that only nodes reachable # from the root by following a path via at most 3 edges will be shown. Nodes # that lay further from the root node will be omitted. Note that setting this # option to 1 or 2 may greatly reduce the computation time needed for large # code bases. Also note that the size of a graph can be further restricted by # DOT_GRAPH_MAX_NODES. Using a depth of 0 means no depth restriction. MAX_DOT_GRAPH_DEPTH = 0 # Set the DOT_TRANSPARENT tag to YES to generate images with a transparent # background. This is disabled by default, because dot on Windows does not # seem to support this out of the box. Warning: Depending on the platform used, # enabling this option may lead to badly anti-aliased labels on the edges of # a graph (i.e. they become hard to read). DOT_TRANSPARENT = NO # Set the DOT_MULTI_TARGETS tag to YES allow dot to generate multiple output # files in one run (i.e. multiple -o and -T options on the command line). This # makes dot run faster, but since only newer versions of dot (>1.8.10) # support this, this feature is disabled by default. DOT_MULTI_TARGETS = YES # If the GENERATE_LEGEND tag is set to YES (the default) Doxygen will # generate a legend page explaining the meaning of the various boxes and # arrows in the dot generated graphs. GENERATE_LEGEND = YES # If the DOT_CLEANUP tag is set to YES (the default) Doxygen will # remove the intermediate dot files that are used to generate # the various graphs. DOT_CLEANUP = YES FreeRDP-1.0.2/docs/FreeRDP.vsd000066400000000000000000006430001207112532300156350ustar00rootroot00000000000000ࡱ> 123Root EntryRoot EntryF\NVisioDocument4SummaryInformation( ODocumentSummaryInformation8H  !"#$%&'()*+,-./056789:;<=>?@ABCDEFGHIJKLMNOPQRSTUVWXYZ[\]^_`abcdefghijklmnopqrstuvwxyz{|}~VisioInformation" ՜.+,D՜.+,P `ht   FreeRDP Graphics3NGeneralization ArrowreDynamic Connectorow NavigablennSharedl CompositennComposite NavigableShared Navigablele QualifierigShared QualifierleComposite Qualifier Composite Navigable QualifierffShared Navigable QualifiereNavigable QualifierProcedure CallfAsynchronous Flowr Flat Flowusrealize_subshaperWatermark TitleLeft AsynchronousrUMLPackage DependencyrClassenGeneralizationuUsageliBinary Association Composition InterfacenNotefac PagesMasters0|_PID_LINKBASE_VPID_ALTERNATENAMES _TemplateIDATC010498511033Oh+'0O `ht ,8awakeTC:\Program Files (x86)\Microsoft Office\Office14\visio content\1033\UMLMOD_M.VSTawakeMicrosoft Visio@6GNC`: @ EMFxNl@4>ܜ<VISIODrawingLMC`Da ??d(LM(DaLM㾤ȳůůȳX2Y2_bb`jEP'˸ůůìɴ˸zsewWmKM$sRwWwWƯwWwWT,R)U-U-W0J!S+ȷȷxU~IX1U-U-S+}IwWwWǞwWwWwWS+eBwW|^κfBsκǞwWwWȮsP®vvm®rk}Isκ`;sκǞwWwWκgAygv|Ys}Isκ`;sκǞwWwWY1Z3O&N%mJmJʵ}Isκ`;sκǞwWwW}I}I|^k}Isκ`;sκǞwWwWκs}Isκ`;ʵwWwW]7gDwWwW|^wWoMV/wWwWwWwWV/oMwW|^ΞwWwWgD]7wWwWʵewWwWM$wWwWewWwW]7gDwWwWewWsRQ)wWwWs{X~`:sTů\5~p[5ϻR+q~`;κgA{Xs}I}}}Is{XqMU-~q`;sr®ʹȷ`8U-kI[5ȷʹ®ȩR)oNL"Ʀıʹƴ׾iDκsNȷʹ®ps}Iּƴʹƴּ}Isp®ʹȷ_Y2׾ƴʹıʬ`;srrgujbsNκǔgBVNGujbıʬ`;`;˭rgWOIu׾iDκsNvuk®ps}Iּsf]Vƴּ}Isy_UKDe\Tti`w_Y2׾e[Sujbı˭`;k|Yo{gAκǎ^7srq`;]7qpr`;̶gAt{{Xs}I~~r~}In{Xv~qMT,wtq`;vVN$L"L"T-wW|^K"O%P(Q(sRwW©X2P&~J P'dAwWe¨L"N$N$N%wWwW}IQ'|IO&jGwWs~aN$L"Q)[4wWwW~K!P&M#}J sRwW©Ư}IN%|]̶R*}Iowe}I\6΀N$}IlpfC}IkIƯ}IN$t\6}IyZ_:sκǞwWκssκ`;sκǞwWܞwWwWfB\6wWwWsκ`;sκǞwWκgA~{Xssκ`;ǞwWwWκsNȷȷps}IsκwWwWwWwWoMK"U-U-L#K!L"L"L"J!hH|r~pdr~K L"L"L"L"~JU-U-M$gDwWwWwWwW˸ůů~~~~x[b>}|ygwc|YjG~~~~ůůůŭL"O%\6wWwWwW}I}IƯ      !"#$%&'()*+,-./0123456789:;<=>?@ABCDEFGHIJKLMNOPQRSTUVWXYZ[\]^_`abcdefghijklmnopqrstuvwxyz{|}~Visio (TM) Drawing KaR8;pw88;.u8`;-r{g"b!U&{ !oI$`) P?7H {{,Q, }& &J , 1& ?@/+?I?\.? CA  z,,,'m/%L6$U6 (} g?h)?"U   U%=3# o :S<#>:_a[RaUUaUaUaUaUaUaPONODN`[RaUUaUaUaUaUUaUaUU/b SR{%;1OI%:Qim;RRRRgg Rmh:Qjj  g+g=ZB' @!p3{|bFp#*| | | ri?9Oo<3U4t,,A,/R Q ieUBm]~U]T2d_8v_;Ab_____/υo`s#,uZ b6y C4&f(0%05$Pߒ??r  2ӥ%8Pxx AA r^b(qOOOO%=Oa>]=OTO贁Nk@GI(3wƴ&ٵf>Ddn(ksWƕsދ '?uگ'3#._ÿ7oIo[omo!3 6Bθ(BYQqσP9#8ǵH\(i -?Qcu08Ѩ縇[<XyGbt4"H$ @Y,b'@ I.A-~'O."AUb UUUUU !"#t4"H$ @Y,b'@ įA.RC-$. A$t4"H$ @Y,b'@ h = A>-T~C7"A%t4"H$ @Y,b'@ _ A-x7"A&t4"H$ @Y,b'@ P  A>-x7"A't4"H$ @Y,b'@ & A>-p,7"A(t4"H$ @Y,b'@ ă t A>-xz7"A)t4"H$ @Y,b'@  A>-$~7"A*t4"H$ @Y,b'@ ܃ A>-p7"A+t4"H$ @Y,b'@  ^A>-lxd7"A,t4"H$ @Y,b'@  A>-r7"A-t4"H$ @Y,b'@ A~-l{ A.t4"H$ @Y,b'@ h GA>-<{M7"A/t4"H$ @Y,b'@ A>-{7"A0t4"H$ @Y,b'@ A>-D}7"A1t4"H$ @Y,b'@ D 1A>-Lp77"A23t4"H$ @Y,b'@ _ A- }7AU45t4"H$ @Y,b'@ rC-T*7 A678t4"H$ @Y,b'@ <A>-J7"A9:t4"H$ @Y,b'@  A-\Oz7AUR UUU78;?@At4"H$ @Y,b'@ EC-- AU: UU78Ht4"H$ @Y,b'@ 1C-t*7 AUj UUU78?@UAIJKLMNt4"H$ @Y,b'@ TAXzC-h7 AUJ UUU78OPt4"H$ @Y,b'@ >C-DO*7 AU: UU78Qt4"H$ @Y,b'@ DU1C-$E*7 AUj UUUUU !"#78Rt4"H$ @Y,b'@ @XC-4E6 AUj UUUUU !"#78Ut4"H$ @Y,b'@ @X}C-DE7 AUB UUU78?@Vt4"H$ @Y,b'@ ?8C-Dw*7 AUF UUU78?@ASt4"H$ @Y,b'@ ;C-TE  A @8Q CR@t7 MR@8E FR@> ER@D%  FR@! . FR@l) | FR@  FR@ FR@,4fFR@ZFR@d[ER@ OFR@ FR@\ FR@ 9FR@HR@NR@RE! RE7RE"  RE$ RE &RE 4RE BRE PRET ^RE lRED\zRE REREYRE^RERE RE\REREREt RERE&RE24RE3BRE) PRUFDfP h> /T6D UIV?Au?3P? '-6 bfbK66ȅH? ?[e^gUS#u %U13 VGcGic]WRNJ Jfmb{?QU?P?j?HDB D# ?hZ >TEI U@??@ĸ?]P6 >-u`aW? Su# SbHN N*J}5 `?Copy_rigTt`(c)`2U09`McosfrԦain}.` AlU seev d `l>,>Uh9 #H@ Wa"% bJ*!K 9 8:"   6MB/>//_5&5365O? g?D&5v%27?%rAH2CdUHUz 4 )Fޝ#jB ~tuiV@eW!o+K%o8aߝ ]oP_}U$ U%&'U'4(AU )N *[U +h ,ue -.V/0U12U34U69U;HUIOUQ+R8YUEVRS_UFDfP h> /T6D } UI???J3P S'666== bb ^aȅHUд\?Ke^ %UGu ? ?????GXFFflGYUQ DhRepursnt asocito: btwu )ocl ifes.bԿ?m:mԿ8?>?>? UG HD # 3h@>TB(E=J AUa?kP6 u{` ?A_M u#u /u`!MHbwSu J fB{R.2JAaAK!a)% bJYJ"?"I/K d&T'}->U2N贁N{?<T#2r!#z!"?&&v&BUk; "; !92D?62?; .460"2]?o;񩶸#>?$@&7c#2a4#k4%EI AѸ#5 `UML BackgroundPA$Pd-Pn` /C PD=10 DP1!y#s'I4]RVCsVCV CVCV"aA%?S@bUD V VQ#78:?Ala߿@qt`?smg @X"FL /A-_!}!ab g92rS!0wA3b?!1]R  h s]Rru$y2Kx@1ظ#qAG;v`?CPpyPiPhtP(P)P2DR9PMpcJRsPfrqrp* api0R.P'QUl' xs+epUePv=dIQ`VpsU_1BP2cTm!#tEQ< e>levE q ʄ%ل䋫5ل@ 3لɨ8FaP"b !rRb" !!rrl1Uh]Q)3q.a 918T&&Krr--TsJ@A4q#gK 0Ac?(P4C?wQ9FaC# gc#sVVYcmx(sVV1L& r4#;!FBaCꡯ%[l!+w]RrWXɿۿ颫5f?$6% ףp= V׏ϡϳYS#(g1 WV #xҚWVpheWMFaTA|KX11(GTAg¾?A-<qqA6#rq Q(-DT!p0@A?t092rcB83P|* `M4^s_}r_VUDBE;!^L5j2 @m(h_XbmXȴxEjad࿘-r!3|@/ iDӀw2b]|/XEj7??/Qcu/SB_Xb_?XL/^/3Q7ReR *<2N-AeAȺ y+@MKb6PYeepEwp.BBR __-_?W5JVU׵4rAjOOOF R_A+*_V|%d_b___VV_BRBoooF=R+SpapeX`i&#bOpORodovoV]%_7]pEWiF)C%SPrqr3`&B V1g2D?O6QQ¥abaaCC|"@Һ-2BC!BAvwj!AD1qr0ѪяQȪL9A7@}@ů9!D2W MYiҐxȳ$]Z|%Y6P&w rwe@@4^hޥrrr |״܁=-/ sï˰.EMq 5mB1A$C!$BA$@0  bP-Ēo52b 3ђ9+@0|?" ρu&`uj `Dޒb@|ʥ0`uD0!/d`$h@AۏP`N$x,]ȥaaD'i?D1ɑ|%wy)&XfUx'0ǭq?`!0)_ xIHD:  ;h ,>T  9 BAUAhf?A 3~@q?@IS?@P6 Bu`p   ۢ b bA)u,]uLA-4b .J z3h6> "& !m a9$YA * /ՄJQU5 }Kx(&""&'3ah) ,"?!;nh 4;" L# b"U#BMIAM"gL#l6R"-4m0h#!!';`?CopyrigTt (c)0W20090M0]c0os0f2R1r0Aa0i0n.0 AUl"@ 8s&Be0e0v8@d@T$l(0@Uh%I 1'H6$4*:#A%A%A qJG4(\AXB@HiAb9 O9Uk$;W'01!05 ;VO6+"VV"HD # =h ,>T  9 CAUA23?Ahf~@q?@IS?@P6 B[u`p    b b_ASu#,uLRA-4b .lJ z3Q6VA "& ! a9$A * /JQU5 }Kx("E"&'3Xh)E Y"?!;h r4M" bU#)6h#MIPAM"gL#c6 c1JBh#!!';`?CopyrigTt (c)020090M0c.0os0f21r01a0i0n.0 Al@ 8sBe0eJ0v%@d@T$l0@Uh%I 1'?6;"aU:#A%A%A J9PIAXB@H(*e 0AbE9 F9Uk$EW'01!05 EVF6+"VV"HD:  ;h ,>T  9 BAUA{af?A3@q?@I?@P6 Bu`p    b bkAuJ,WuLA-4b .J- z36>j "& !]a9$A V* /JQU5 }Kx(&"H&'3Xh)2"?!;b 4M" bU#BMIAM"gL#c6R"$4d0%h#!!';`?CopyrigTt (c)02U0090M0c0os0f21r01a0i0n}.0 Al@U 8sBe0e0%v/@d@T$l0@Uh!%I 1'?6;"a*:#A%A%A qJ>4(SAXB@HiAb9 F9Uk$2W'01!05 2VF6+"zVV"HD:  ;h ,>T  9 BAUA}3?Aaf@q?@I?P6 Bu֐`p    b bA@Su,uLRA-64b .lJ 6z36 V> "&!a9$A * /JQU5 }Kx( $E"&'3Xh) Y"?!;bˀ 64M" bEU#BM IAM"gL#c6R"($4d0h#!!';`?CopyrigTt (c)020090M0c0os0f21r01a0i0n.0 Al@ 8sBe*0e0v/@d@T$Ql0@Uh %I 1'?6;"Wa:#A%A% A J>4SAX"B@HiAAb9 F9xUk$2W'0X1!05 2VF6+"zVV"_0HU[ | }O Fġ!"#CWjcTB9_dKTUaLui;$@+k?-aG!l:!/l!1!s4 !7UFDfP h> /T6D UIV?Au?3P? '-6 bfbK66ȅH? ?[e^ gUS#u\ N*  _'+<*9]b?Uxwvj33?UHLD t >jh: JTP5 QI>[U@?г?P >uA`bJ>u`em? >)5< <U{>`?CopyrigXtd(c)d209dMcosfrain.d Al seev d3 >`2lTJ$JUl 3 M w >a"a# z; @"?>Sb3")#N: #)-%A=/O/a/s///)<ڶ-4"/^' A/??*?<=_HU-򆅗 ; a)Ft0:#!Lj;AB  /T6D UIV?Au?3P? '-6 bfbK66ȅH? ?[e^gUS#u ,  ,C}C ,X Y RH?+mbĿ?wUſXw?`?TV?HDB D# ?hZ >TEI U@?Яĺ?P6 >u`a?j u#j bJHN NJ%}5 `?CopyrigTt`(c)`209`Mcosfrain.` Al seev d `l*>0>Uhh;!;!9 #@ a+"% ъJ*!" D 84y" 6MB//D*53:;&?U?/7?83N?8?}9z%2?%rTAHZB`CdHUe  )Fl2Q>#i*?`B $ui]#@eko+K]2aL37]PUFDfP h> /T6D UIV?Au?3P? '-6 bfbK66ȅH? ?[e^gUS#u ,  ,C}C ,XUY RH?+bĿ?Uw?`ׅ?3;?HD   3Ah$>T 3 A U@?г?A?P6 ku ` ?Mu M b,2 2>eJPPJAG7 ??  A,2񕣍5 `?CopyrigTt (c) 20" 9 M c. os f"!r A!a i n. Al\ (s`"e4 eJ vr dT `l>0>Uhh!! @i{w a"%50J!Z(J"PE hv2M>?[:(53;309?R?7 ??86A$O9%2&?85rTA,BCa,e HU͋e 9 )F,43B#i C[B uig]#@e kko+$Ko]9a 5W]UFDfP h> /T6D UIV?Au?3P? '-6 bfbK66ȅH? ?[e^\gUGu ,   , B-a mgX K ? +b.nĿ?< a|ҿ:5?U%?*q,ת35?UHLuD  >h: JT5 QI!MU@@ 3?K?P >tA` et"D a?怗U!!>ub>uU >c ܔXJ>U `?CopyrigXtd(c)d20& 9dM c oKs f" !r E!a i n.d Al` (sd"e8 e v"v dX lJ$JUl 3 M ! >a"a# ;@??>^ben!N::X23cC:z%A//////9T9 MEJU@??@ı.n?@?@?P6 .n>mJuM` ?"u` 5l Jb >5 J`?CopyrigTwt `c)W20 9M]cosfRr#!aiun Al> U sB"e evT d J`ԈJ8B-# ?9 e!e -MM=U'464A7l$>Uh E 9!@6 ("l7J??? Os@HD: # ;ih#$>T #3 A AU@ı.n?@ F%u?AA?UP t`  ?t#ŭA@#3Zn>uNT^u N b TJGU ?? TAB=!=!5 `?CopyrigTt(c)20 9Ml cj osd fr"c!rf !ar id n. Al j(s"e* ej v d )l> 0>Uhh@   #t[! WaM2S5S0J`A^dM ^pT/1 N6MB@y:?? 53;0 O?4GBI?eAwO2I/5)2y?5rARS_HUqb :? )*F5UB#i/GqB ui]#@etio+K]Oa8g]]6IK7UFDfP h> /T6D UIV?Au?3P? '-6 bfbK66ȅH? ?[e^\gUGu ,   𻻰,K B-La mgX K ? +b.nĿ?< a|ҿT0u?U%?Bw7m4HNё\?UGD # T h(/TYTYU@nh?@?@ı.n^?@w?P} u` ?u`e h[ b)2 2.[Q[JPZd)`?CopyrigPwt \c)W20 9M]cosfRr!ain. AUl: s>"e evP d2 ) R`(B8-# V? e@!a-E ,UZH&124d=7HD: # ;ih#$>T #3 A AU@ı.n?@w?AA]?P t`  ?t# AK@#3cuNuj +b z> JGUG ? AbJB5 `?CopyrigTt(c)20 9Ml cj oKsd fr"c!rf !ar id n. Al j(s"e ej v" d l>0>Uhh #[!t@ aM2S5S0J`AŭBNTM Nj"  6MB@y:?^: 53;0 O?4GBI? UAwO2I/52y?5rARS#$UHLuD  >h: JT5 QI!MU@@ 3?K?P >tA` et"D a?怗U!!>ub>uU >c ܔXJ >U `?CopyrigXtd(c)d20& 9dM c oKs f" !r E!a i n.d Al` (sd"e8 e v"v dX lJ$JUl 3 M ! >a"a# ;@pqʼ?>^ben3RJ2!N::X23cC4t%A//////9<=n1+??7 gAQ?c?u??=_HU# O z*F:N#iOqB tOi!P@ek%o+K+)oXaGgGՁo <*R5_TUFDfP h> /T6D UIV?Au?3P? '-6 bfbK66ȅH? ?[e^gUS#u , ;EWi{@+>Reprsnt asocito trbueo Kls8f#> wh vl1`rq6t atg6Fo/jc edch !cj .mb?wUXw?P?T?HDB D# ?hZ >TEI U@?Я?P6 >[u`a^?Mu# bJEN NJ%}5 `?CopyrigTt`(c)`209`Mcosfrain.` Al seev dE `Dl>4>Uh;!;!9 #H@ Wa"% J*!? (x y&% 6MB<3/8/ 1.53>?W?i?.5??/??OO..5~%2DO;RrAHBCdHUI]e ? *F>W#CiKGBjk7Xatio#@+t/Ko1aGYPUFDfP h> /T6D UIV?Au?3P? '-6 bfbK66ȅH? ?[e^,gUG ?,  ; w HU}O ;rj \ N A+mbҿ?憎ҿXU?`?YT ?HD: # ;ih >TEI 'AU@?ҧ?P6 t`  rqo?t#TR w>u7jtu Y )b- JU5 K`?Copy_rigTt`(c)`2U0( 9`M c os f" !r G!a i n}.` Alb U (sf"e: e vx dZ l> 0>Uhh!!9 #j!@ aJ"% Ji`tz`t"j dm6MB9?Q?`53;.6??M?7?3?*HO9R%2?35rA*BCHD: # ;ih >TEI 'AU@M?U@UP6 t`  :8?t#q0 uTSu [ b >UJ-U5 `?CopyrigTt`(wc)`20( 9`M c o%s f" !r G!ua i n.`_ Alb (Usf"e: e vx dZ l> 4 >Uh  9 #!t@ a"% J` ?TZP`p "  q6MB(738?`8U?g153???J5? OO?/OFObOtO5%2O;rTARS#UGD # T h(/TYTYU@U?гҳw?P} 8fu` ?(u2;h b &U`?CopyrigPt \c) 20 9 M coKsf"r3!a in. AlN sR"e& evRd dF  `BR-# ?3e3a-dE UH:1F4Q7_HU ! +F?[#Cki\lB tgi]#@eko+ΗK]4a! ]" _G aUFDfP h> /T6D UIV?Au?3P? '-6 bfbK66ȅH? ?[e^\gUGu ,  ; HUO ;rj \ N A+bҿGz?Q맿ҿl6i?`U%?@ t@Q3??(\?UGD # T h(/TYTYU@?@{G?ҼQ?Pn} u{` ?u` K~h b)j2 28QZT[nJPZZnn4U`?CopyrigPwt \c) W20 9 M ]cosf"Rr3!a in. AUlN sR"e& evd dF ) R`(BJ-# &?e a-E , UZH:1F4nQ7HD: # ;ih#$>T #3 A 'AU@?ҫ?P t`  rqo?t#TR u;hiu] b1ʔ $-> +JGU ??& ARBG!G!5 O`?CopyrigTt(c)20 9Mv ct osn f|"m!rp !a| in n. Al t(s"e* et v d -$)l>0>Uhh #te! WaW2]5]0JJ`Khnd "  6MB?x:d53;6?O?>GLO3 OHOTEI 'AU@M?U@UP6 t`  :8?t#q0 uTSu [ b >e J-U5 `?CopyrigTt`(wc)`20( 9`M c o%s f" !r G!ua i n.`_ Alb (Usf"e: e vx dZ l>4 >Uh9 # !t@ a"% J` ?TZP`p "!  q6MB(738?`8U?g153???J5? OO?/OFObOtO5%2O;rTARS#_HU!ϣ # V+F# q/c%kKdhB ti]#@eko+TK]UaGd$ e|% f"\& `UFDfP h> /T6D UIV?Au?3P? '-6 bfbK66ȅH? ?[e^\gUG '  =@? M EMM k \ \U< J&bXtEݷѿ?<|ڿX0u? VU&?Dw ]"ɋtG??UGD # T h(/TYTY#U@wE?@?@^tE?@|?s@X?P} u`{ ?u` lh b)2 2BvQkQdexJPZ*ddxxU`?CopyrigPt \c]) 20( 9 uM c os If" !r G!a i n. WAlb (sf"Ue: e vx dZ J) `(B8-# V? e $^  ,UZHR1^4xi;E^4di7HD: # ;ih#$>T #3 A AU@ı.n?@]ڊ?AA?UP t`  ,PQ7?t#z#A@#3u NuY br z>  JGU ?? ]ATB=!=!5 `?CopyrigTt (c)t 20 9t Ml cj osd fr"c!rf !ar id n.t Al j(s"e* ej v d #$)l>0>Uhh #t[! WaM2S5S0jJ`Aŭ-NTMvNj`" K 6MB@y:?^:v53;0 O?4GBI?UAwO2IR/52y?5rA*RS$#UHLuD  >h: JT5 QI!MU@<@3??@ v?P >tA`  n&]<t"D a? !!>ubo>ueU R>c nXJY > U `?CopyrigXtd(wc)d20& 9dM c o%s f" !r E!ua i n.d_ Al` (Usd"e8 e vv dX lJ$ JUl 3 M ! >a"aR# ;@pq?ʼ?>^Wben3J2)!N::X23cC4t%A//////9<=q1ۓ+??7 gAQ?c?u??=HD: # ;ih >TEI 'AU@^tE?@3?@?@ ?P6 t`x a?t#"D a_n&] չuTu j +b lA JU5 `?CopyrigTt`(c)`20( 9`M c os f" !r G!a i n.` Alb (sf"e*: e vx dZ l>4>Uh!!9 #" !@] a"%) J`9TZp ,k! q6MB(738?`8U?g153>??5? OO?/OFObOtOv5%2%?;rA RS#_HU[  + F<' k#Dk}lwB ti]#@eko+]ZaG( Vm4) ?%oK* pqs'UFDfP h> /T6D UIV?Au?3P? '-6 bfbK66ȅH? ?[e^\gUG ?'  =? M E MrM k \ \U< J&bXtEݷѿ?< |ڿT0u? VU&?@տw]w.7袋?UGD # T h(/TYTY#U@(袋?@?@^tE{ѳ?@X?P} u` ?u` hm b)2 2BnQ[SexJPZdxxU`?CopyrigPt \c) 20( 9 M c os f" !r G!a i n. Alb (sf"e: e vx dZ ) `(bBv8􅤍-# ? e$^ d ,UZHR1^4di;E^4xi7HD: # ;ih#$>T #3 A AU@ı.n?@w?AA]?P t`  ,PQ?t#A@#3udNuj +b z> JGUG ? ]AbJB5 `?CopyrigTt(c)20 9Ml cj oKsd fr"c!rf !ar id n. Al j(s"e ej v" d l>0>Uhh #[!t@ aM2S5S0J`AŭBNTM Nj`"  6MB@y:?^: 53;0 O?4GBI? UAwO2I/52y?5rARS#$HD: # ;ih >TEI 'AU@^tE?@ 3?@?@ ?P6 t`x a?t#"D a_n&] չuTu j +b > JU5 `?CopyrigTt`(c)`20( 9`M c os f" !r G!a i n.` Alb (sf"e*: e vx dZ Rl>4>Uh9 # !@ a"% J`9TZp "! q6MB(738?`8U?g153>??5? OO?/OFO@bOtOv5%2%?J;rARS#UHLuD  >h: JT5 QI!MU@<@ 3??@ v?P >tA`  n&]<t"D a? !!>ubo>ueU R>c fXMY > U `?CopyrigXtd(wc)d20& 9dM c o%s f" !r E!ua i n.d_ Al` (Usd"e8 e vv dX lJ$ JUl 3 M ! >a"aR# ;@pq?ʼ?>^Wben3J2)!N::X23cC4t%A//////9<=n1ۓ+??7 gAQ?c?u??=_HU算 < , F , qv#kKw{B ti]#@eko+t]WaGG%x. Oy?)|%/ N~UFDfP h> /T6D UIV?Au?3P? '-6 bfbK66ȅH? ?[e^\gUGu ,  ; ZHPW c Pd\ O A +b?<пxw?U%?v碋.dtE??UGD # T h(/TYTYU@E]t?@?@{?@|?@ݿ?P} u` ?u.` h b)2 28QQdZJPZddZU`?CopyrigPt \c) 20 9 M cosf"r3!a in. AlN sR"e& evd dF ) `(BJ-# ? e!a-E ,UdH:1F4ZQ7UHLuD  >h: JT5 QI!^MU@@Q+??P >tbA` et ?!Z5>ub>uX >cr XJ  >U4N44 `?CopyrigXtd(c)d20& 9dM c oKs f" !r E!a i n.d Al` (sd"e8 e v"v dX lJ$JUl 3 M ! >a"a# ;@#2?>^b*en3J2!eN::X23cC4%A//////9<=4J2+??7 gAQ?c?u??=HD: # ;ih >TEI 'AU@M?}@?@t?P6 t` ao?t#TMU 1cuTu  Vb n>Y JAU0J005 `?CopyrigT}t`(c)`W20( 9`M ]c os f"R !r G!a i n.` AUlb (sf"e: e vx dZ l>4>Uh9 # H!@ Wa"% J` ?TZp "!K q6MB(738?`8U?g153???5= OO?/OFO bOtOv5%2O;rARS#_HUe򧳗  P,F (#i^B tgi`]#@eՔkdo+Ch]MaGį ] pܲ h/ UFDfP h> /T6D UIV?Au?3P? '-6 bfbK66ȅH? ?[e^\gUGu ,4E XUI5?mb?@ t¿XUw?`?T? ?UGD # T h(/TYTYU@?@?@??P} u` ?u` h b)2 28MQVbZUJPZdZUW `(`?CopyrigPt \c) 20 9 M c os f"!r >!a i n. AlY (s]"e*1 e vo dQ )BRJ-# ?ea-dE ,UZH:1F4dQ7UHLuD  >h$JT 3 M 'MU@v"u}?@?@݊>P >tA`  Go?t j Gp  >uMZu>m >b J )JG>U K?& UMRNK!K!`?CopyrigXt(c)20 9Mz cx osr f"q!rt !a ir n. Al x(s"e ex v d 1$lJ ,JUl  i! >aW2]5]0` $& \bXx,91 6N K?n:n53?O$OHR5952?5>rMBC'Ae2pQA?S?e?PO OtO/O?O??;HD: # ;ih(>TA9 3?@?@tv[>P-DT! A-u `u b_u  l" EER cu` ?u#b. ܳl> J=U2N贁GN{?<Lnb&B\}.t  G|"t"|"'$I$Iu$/$'"/517-;?0U115 k`?CopyrigTt (c) 2009 M0c0oKs0f21r01a0i0n. Al@ 8s Be0e0v"@d@.l>#!Uh#3 A 1 aBKaC@J:eG# '>"BEOO_HUx M_ zFԴ !w#_ġjKTB T[O@eVSo+gWo=aGyW o̶ >R UFDfP h> /T6D UIV?Au?3P? '-6 bfbK66ȅH? ?[e^\gU Gu ,>  밻Y `;l p:b|=x|@ tUﴱ?@N{_? ^(_>3??HD:  # ;ih#$>T #3 A U@@<۾??P ku` ?Mu#  Sb,2 2n>JYPPJ32N贁N{?<CLBB5 `?CopyrigTt (c) 20 9 Mcosf"r-!a in. AlH sL"e ev^ dH@ l>(>Uh 3 a"a# Jh#<+1B%?@j}GLwA>?n44i0>C7,3%1n;3ك<|7UGD # T h(/TYTYU@?@qP?||= k=P} g nu` [W? u` o+3[ birI r ``?CopyrigPt \c)209Mc.osfr!ain. Al) s-"e eJv? d! B8 -l#[ ? e^| rlUH3_0HU=n L_  Fĸ w#jWB9V]#@9Wo+C]GaO >z "UFDfP h> /T6D UIV?Au?3P? '-6 bfbK66ȅH? ?[e^ gUS#u , _ ;C OU V\QH?+mb?Nh6i?@N{?3 ?UHLD t >h$JTB 3 M m>U@? ?P T> J>uA` ?3:DuNWm >b% J32N贁GN{?H?N!!`?CopyrigXt (wc)F 20R 9F M> c< o%s6 fD"5!r8 q!uaD i6 n.F _ Al <(Us"ed e< v Id lJaUl~M -! >a2Ka3"0<3D^JDpN>;W?To?(5!A('11-3/?!?3?;UB?S?????B3hO&OOg5_HU򙿗 t_ /F Yw#j3ZB C[]#@eko+4 ]5a_| ]֮UFDfP h> /T6D UIV?Au?3P?]2H?>P ?ze^ * 4uC 5߃ bп?łֿ߯? 4 HD" # =hj,>T]]#MAU@?;ofP-DTw!?>Bu `u bWu  -B) n6Bu` ?MRu#]"B<,O7Y]AjJBU`?CopyrigTt (c) 20 9 M c osf "r :!a in. AlU (sY"e- e vk dM B,?C$'"/% 7-H? #0Ud2C^6dhMKl>#!Uh#T5P= 92J)*/4SY[~"B"E;OfHU lݬ-sGWKFl!Xݨ#dCB |[UC]@ekGo+yK]*aL!u]#UFDfP h$T PYYBUI<+ @Ill??I?3P  V[+1F_R@k|؎VrsUE \:BIHи/й?d E"eB^ E 1!#u \ۿO߶w\߿ w $3 1wwU1X>w(w.1OwwVbqql?@? <+ ` `xV4@[˿UHDF #hz,TAYY#\3  #UI<+ @Ill?@ǝq?@ ?@P} u`bA@buL#-$R.)tStT^a}  RY# J7U 3  @#?a*g*g*g*I!"^ b}++++ + d&" Y S6"Y[3q2 %@!@!H'p`?CopyrigPt (c)02U0090M0c0os0f21r01a0i0n}.0 Al@U 8sBe0e0v+@d @> ]% D^ 0#^P X͇I'0S&!L$05 wFn3da _T'T  #%NS9 5,?tQ'`L0Wck0T+@x2E7@i0> 3B> {!S!` UUW`Gu@r7@(0)Z{~<_o"c1)gR"rQ%%_V#P_\AP WD+@%l+@t+@> 34`*Ss!;Q Uko,e85bboa"]|hah g_%%=]INS#5tTT?1 3;EHU 0OhWK_4 QF,!/w#$k,{B |uWi]@eՄko+]Bao;]PUFDfP h$T PYYBmUI?UA?| P?x *+1: bjb:$:!H? w?+B  0$k`0Left,AsyncProY ouU , MLQ sK qg eY"es"oNM"wa_ !ma ]dK liY g!Re^kUGu ,>  밻Y `;l p:hDrag onut heqp ad. l fWsycrou5.a mKbb6Y||= !Y<Ŀ`̵?@ٓz?PU-G1 u&??HD: # ;h,>T]]9 ##!Uh#3 A 1u6 aBaC@J:#l+=BP6/5BF _$?aEUGD # h,^T(YYEU@b6?@pP?@yY?@L?z|=@;C\i;P} )i.;;XNu` [%?:bu ` ek=v b 4؉U`?CopyrigPt (c) 20& 9 M c os f" !r E!a i n. Al` (sd"e*8 e vv dX 1`V sU_1 2X cPm!#543 5t8-# ? Bd&+"e,1a-%UYH14D7B(aݓM?MgdaOC T7QD!! JCC #%nA%JC,4,@BHD: # ;ih(>TA9 3 AU@C(@H13?@53?@Gj$?@?P*Fh >t`  fSrol  Vu =u#H?  by l>*JGU ??PI?AzBE,M $K!Bp!p!5 `?CopyrigTwt `c) W20 9 M ]c os f"R!r !a i n. AUl (s"e e v0d $lT>#$>Uh #3 A !'& at2a|30J6J7>DMDg>ZPB5  9J:1/!_HU Kl/1'E슋F #djcwWB _]Va?uiW@+kca!wwG r`UFDf hZVTYYU?"H$ @?Y,b'@?x  .`/HZl~ 2DVhz@/*.U U (V!"#U$%&'U()*+U,-./U0123U4567U89:;u<=?U@ABCUDEFGUHIJKULMNOUPQRSUTUVWUXYZ[U\]^_abcdefghijklmnopqrstuvwxyz{|}~32o0tE0t 01OO "Ř`&:/ 6 U!01yOOO !OobAP5"nOO_MF _S_~Jx___6___^1"_oo,o>oPobotoooooooo(:L"R1Ru!" $BM S}!-"F0e0R .1 1j!r8oLG!t0p2 !"f!]%O^fK1]"d0c0m01a0i01Gus%"cr1&!y6@1E>BS# (t;-"d0s2o2`wII?J w1+u="i0vm0r0a2 #y)_C?cn!9?"1$+v5]"p0ҁcd0`a+ŢE4Tt1+wU"pr֟P)X*HKg*761H +xA-"e0Zb16!y[ŗ$E(vz1+yɯ5"Lh0Tto!~RYB!Eɶ!%+zG-"XiOZTB Iǿ="X1\Z~1#jkHC5?AH 2{E5"s0by0lm0sk!zĉE?ey Ϣς|-"wt}O-a$"4}G"u0Ёl'R>ѤLNno{ߠ߲~="}vbHAOFUG*=Wo0dw!ykL?emN1+ٶЁ1R#'FT.1 +AE"ҁde26ǯALl!5ĜJ18e8f!I Lm D#am Tt1>!!'w]OyDlg i}0l"!uf,kNJ$:` un nJ=';ݠVcvm@CT8N!qr0in] 3U1IEJSlRqs͒nSb0le1 &iH,Y(!="mWiy01OC6Ñ(e"  f N?f͙!I[5L^C\U 7RbBcM6LB= |E anTJk]JZME8(M5/&2#gmj"/4-d&H+%'ٰ?"? R~}'A?v#R?O8>z@r2UԜT/f/i"nHr"// I i:B?g/ht?86?0?8?4-Ct=pEL-?? &g| Af9CT)O_$IzEFxUb|@^OpO+-s_@6{$OO zZB?Qnp7O_#_R҃LT_0Nنb~__ Ɖ܉@ܝLj[_8_cgJB?ak^_ o&-W`L?MF6oHo-robH  zooo88oSwoooq􏛨N?83ZtwUL3xqLTB8˖YCL"*]zMCaV-֣GB|)fC 8)7fMRԁ\6,dD\OA+NcՀDc.Ə /W +~nJg,p'NqF|QAkU#~GQ5TNF}>bί|N(WE4w@$p;q&ncv#Om憣,ȏL@]f} %ؿ8߲sYpJD`"ςGD1Ms`uN`-UdPp@WB2ϨR2ϙojckFsĞC7ðN1߁Hp;SO?sVqi}?^ߺ}~Gn޾8lߨx( atINK\>-?J?䋋*4^yF:(I*smy>i5sK0'w]Oyۤ{Fs c*<N N\?F8[|l6ZpNPMK7/=.M;fǛL zWG T@?&8J%afʅxd)BZ(DHOH`̬%F0uD:'FMH?:36WGld&/8/1MMYP d/v/L 6kKZ[a#1///$/"611t?{qLg?ֆ,?>?N us۾AV:Vbn?O[F^_>??DҘ}Er,[-??L O|+0JCGj_!,O>OPO#cO"w@h@rOm-MU@`OOF\3<%Mr{4OHo ޷NO)#/Ϋ*_<_BXB!!Dr? d_v_L sH.yK4!___"_+r_ ȍ C2&iu,o>oN y!Jj_扷noM˜xonK *zXooEe Q&O -Ukňoo~t DI>((:L!cabyo 6IςG1)qN bn[]JhE=oJe6ngK/={T$6FN|Fk<7btL sE`Aʏs8ykPoKS.@N -LHC;pƯWj MD&h%_H5&B :L %=JG0xKcR.@R)&e"s{po/Oz&LDmo M 3R#}'FC:ǺF uM.?g:J$6+u$jE*btL eR E<<.fwJZ*U,Tг vy PKkp߂N 8DK ǝSZlB\{FH?p%뵤϶?v@;N1L 0HGbE:'&8ʿ-Z_; ]?%\D/s\&8N 4m*{D.턂ǐh{hr׫I_GRzGËݰE)2S.'KoCe"4FX].XnwMwyÌmG MI&p3 M*XFjr,GA5ڏXjqYRK?H\~dџ zueϔ(cN0(;&$-h9UOqf8ODŽV/.DnȎG]myBjU{\ ,^N !/%/7/K/ %X-MRY.B#//(7uB*/O@1x=cqHmLo@??o'.H?_KP@?R?F6A [R ;???b?ײiBn$hr)JJg6?O Cb0<@O_A#&{-@3D] bxOOYິClG]uэOO)w`{C*?mDYO __(a5_ҺQngCGMuɆp__NAaJ߂_Au?n __R02g@N%,o>oz (CLe= lo~ooqTobutg`e` a/ɒt8wJǂooĦvD?5[&qƦc4DD`^p5ZcM#N)?jonuEMsxY+"%2?R QrH+Q_9]_j|7K7,"N9銯Ba\5ڎ<`*\DJVv"45YLO`*fx֡L_Zߚt");|eNݣK.=v߈hkYH: fDߔݐfζIQx R1 63;Ο ﹭ddAdNNdocumentai n@mQcmLQ+wl ,B|MAK&prsUsc$ r:ڤ'E?t~\Z+ErsXbUlUty#|p tFEP}B/:JsmQi s#ڲ,T_`ضWige U)aD|&rJ.;& ̉IطAƥ?8KD=UvJ"Zr$x|*wbRE?kxIFú$ <״|@*8K!"9PnSddRHPt;u& N kM# ?U9v AX!w ljm/*;FER?:/L/$ :1O L///ܹ/ fM2T1dN]?-_??$ "A2=0A&lNpvOM,ܻC9b:|??& x;Kx F?_߲ooK,nC*~??_0;O+Du@l2fXktGLrO _&  B~Nt b=_o~IH?Ir_r__*z CaJƫazOO$ ƌCB7e OO_ޱ_ob% _+0E*H Ƃ '_o& $;LƶQ4oҀ&jCZuY[Yulo~o*X1g#qJQ$+E2oo( (:tN_Eio,Yc 8n@*`tWf8˿oB&C#DтaTMq-qA'~D?`k)}!dˀcp|lcnu)H%xvȁ&  %/|E}cԶCI >INhs*Xp`*L{tdl[,>$ YYIs*dpr1 chÐrcIc,1-JWt& j‘BB?FFLoEoE}*7ڎ&BCNď,>$ aHoD;.+p bbvdb,f O(& 9a!DC/랹.|Ϸw_ͶTFofxo,7Is{$ 貼g;hAUgQ 1oeT6j5*Mڃz1.xCzV(N80HuTxR&8zY}Hf+u fxߊ"y2viР l9]8M*㏬D>#x[b/#]NA?,Xl(v~r MO2\n xJ\Iu߇qrespo]nib#l#tyc҉M[ \smat#c2X^4ߛJ׶'.;dcu]eaacl Wa8o`&WVBDauT/p 6,TضBo)e_ioyL^K+QݒeFGFil_nbeMBr-)r!s-hc2 }A٨/; 2 F$OA?JTRd > 'y8] @I#m?1/ /2 YmOf7cR/d- ߴDvK hK49Vh4 j,*RGx&P(d?v2 %ApV?r ?/"Ch0r7ˑ>kBH4{2]H?Z?4 3`A-L?ZO}i0M*֦KO??MpB\@//2 XKA2?>?d/?<O"-%7mNA|^,>OPO4 ĝy@ԅTQO_d%GNUǘ!OOt}vnHjM>QO _c_+J}!:_L_^_;u_%Ds`c`al7'QHW0=__4 ,[\J"f _L$X-Hf++V,o>oHBR@I8?v 5jo|o2 nYdVSL<"Iooo:oRo9pb/8U@vXpA):3,>4,zx#IK1>m)rďa'3O6BAM9gK?,WWd2 DkNћ!(:L4c%Ieg'8`H4 ~/YJP2>yG}(0:%U@KˠU\n2  K:HC'ğ9۟"Lg7DKc`.04 O ENOE`[3/LM!6ãyGN-?֯2 y,wO9!,>7UuOajrt7/{)E?<5 4 3dLg[%*F Qx )!5AC?CJ\2.BNC) ЎϠϲ@ S@o3|E!Lvٟ.Kk¯bJ #k+2 s +@P1 $??UTDQD[x 4 #cPzkA/O߻ ,8AuSp: Tq2G? .2pC2 eϺF/"eRPP (7  44O9%I/ERy B!) ESɎL''op'2!wkb*rpkO# UdT//3D?q&(/:/bPvE<$? Ayh[mF$ZAUꗔրl/~/5GB*&Ǔ9b-6E#? +OOr_S8L 7E???)q1.IH"a#O5OjVEd}B?ݹ}ۛBhO_:'{}K?'LOOOQG;@@_%k2SdIg`dBjGM*IZ_l_1mLB__mC3__\=7L@ꖐ|Vo]Kv?{[o//A@^貍L^w*5 'MRH?O F2TUcblib5aN=QkW2t8\Ay4 L ?B3z ܇B0"Eg5 HK!`0H3MƷ6t7CB`!oo՟5vzNLJ~2h?NL! wJ4FǦz6H~p;aMwZXOM8⶟o6іATGRT&d}MmGH(ûbhoޟ1F1ao=1L*a5Pub&UW6J\aB#.@^wP?Gqο3 Gg?'_( qƯ UPJ*mGpRri-Fw*b.@RJE'F}ArB{K[qGI! у(:Ϥ=G?<6֛BĿCD"2 u*J7qh~*ȬF84@,#bA{J5"(:+>@(_8 Se jBiBOxm KEI0Z1D" p\Jq[9F/X/sI;) A(#1 //L@DD"D~///:9;lZBEF>H A0g212LK?O4 I(0u^E -~?OtBA4QGD9-?1??罞 NⰺA??;q@YD?E@'R">?P?_< ;NNzMp "iQ@n@l3@F"QIf_x_2 k7-*oH?q aO_ gOJFcQ(_:_44e\xDPaAo"xOO1{ڷLJAOO_cX@eNWtu`i`g~ 2NޟYç_o6 #e˥{H{cP$HJA3oEo+S:z(A=3oo4 \:6MFov|tF? ˣjo|o>zv1Q O7@@ ^UBrqj=tE(5|$6L4 .k)LtoaF'BJztTdv>'J|WrL~\nn*OFO V:qoېw+ch&;#J?ukKVhަrOC(. ԟ‹F+F6 ~|GRKo®ɦC܏0CwA1'Ӓ*u>$hH鿙+]2{eemLX <$K= 8K"ү2 '1NIIGvDqiQCA}`N`4 w MΏ ,p$3M &=)Zlx{8uL'WWCt'oٲes!OieǃϨ .oE?ITf4 b<Hj7NlCF48luhASۂֿ =I0MJT0|o^A8;%Evj6PGAP4\b|(O>3\q@p:{uHZ8L;B麪PbHmߞ>HJDB9Oa\(UJABbk#` O<<::OQw%3ZvOX%}/l] 5( :GМ:DV HUM㥗4_az2fA_% Qsg;lsNd EE"*&v}P uQ@@q+xW68M@iW6S o.9L5m8kVM?>&6EB>맪PIDJo3`P3IR}4rRz{B\3Ekg%PU o 0䙤\\Czp6/H/QPn%DZ7 lj//mh2O|X#"r//djCG^L_//k #IRNdSL/ &.L%F_|\22uT9deKj?? Pqj{C?RŎ??vڽ!F"KΕ2?_QjH$Y@'*X2.OtxXVpMJ<ѿ{?GOwnLѰE%BPDR :hBy&OO =}ٹM?_Y b__eϼ]OFA^7Ѣf_x_CQPO MG o<&*_/_:C+KOEbqP`ofwba`My4F ?S3o.o/LOOޥoor~xL^PX^opo!/GC UDoo3S,yAszÇq,>ycc DHa?*od~Q:Je@Q7ZOR2K276ZCN&(}46nI(A_ޏ{RwrpLHlQEwB`redmG}g[a*mG&IyJ|ꀇ۳><;,%IwPc/ PW]H «8Ls)ّ4L"ytMĒ$֝2cK?VsKRd3{1HJp]Ο3mA r~LEN5 ۿ|;O wCAM?>E\¥R Nr)IDսPM=r'@R3AJ}O:ilz3^qxD ¨ƿm&hEjwթ <:m/cEQ[=¯^U5sEwi("p@oŒK3-H+jMϞbDJvòϑϽ>{LIBT3FC90BtA~E! ߜ(|eKS)B@RtT GnW.graтA =|/dB_{c;Fu6߂mfIAÐ1>:LruxgA) G#locatintp(BI%m'dumEe tX×Kx" ڪDApAdAcy104AGvò4Fh 6jCF)do}5L{fkeJe$Yr3-UX 0M?2ԧRdv՘;FnL ,9B _E1ѝ`C/}נP / 2?/dQFHPR]d/v//4I&YE?37/ $$@T/??Pa Kzn$;4?/v???LiI\N]?gQN?6?J?FDYdVO?O!Oq%i6L&?c ٳkDO bOFd9kH&U"#OOOT2W ʂNr7 RO4O2'gׄK+.A_#_g #eE?}J~/ O 2>MK(~ ___V !IE'9Ȑ_ `O]yKFEQR稿F o2oDouC\bjoB@CYT^4ުooo؋ɖEB$ro p_/* Lk?4FXEⅲ@}ZT_8[ёC?Av߫ cH/Ȥ9!|5wG/? aFXTW"P/NH"W CcmMY{Z!q t݀ap&^{B|Xs߀RistՈ6DWŷr߀sp s b lMyXg^ިG,)qrÒse@KaIEI_Ώ {;GOX,f>+'J4ÑBxRoFXWk\yMrXY tN$lHDBe zDy =2D G#DXX@OŸ ZmN$,zVTCſx$Z"Nyպqk}oHTGq̙'= I;Ф 2YM=?/*<&JhHh9`֪Ϟ,BK(Nǯ{XNS}a9Oro.Ca1߷F?-szfړ I"+TϼarE}kǒ3^p K_I?:QWIl~¥osKBㇼ͏VaNz}I)_[,Y *)WbRGݞ; RAQLX1h3@6Ov >Zl!O+'aL?ZWJ34C=Y<(:Em:K3ŏEJZNdZX.B ψ!K rFuWS! AXvU ZE {kIA?ìdY6/2#9}!Bg@5%OE ZR>P|mEaRqDoIZ3BEàX4ƃ,GfF/ /uF.YGio//7M̶ES]O yQHZ\WNJ}}.YCIOrtxC gŠl/mKwF{1_*~qCSa8i{2X' _hcE7r??w~$ZJSuU/?DK)/?}F2Mrzr7?I? n;LS'ɰE???RX MM{CRAfAQZ@ߊMXSzH>OPO6 XFxh؏:_JbiGiLqOOs)Aq L5OZoQy1ZIi_"_]\_ 8S@?[oPo5_CV_ooT;B5loo +UM-к݀o\ڲ;v{&O;0_DV՟UVeMeamMҡy @t;+:.WE+Jćbn>ΟYHGIsD Åg6J]j4fk񠺏̏WAgAk쮟I פ4O]$H}2ʟܟ,U'~CAY6T7E9rI f@8sʎGCJ_ ¯$6{Lt+I2D-Nap4H4ԗIX:!Zv wjHNOwYJٲSl,H,ԥ.FPh,$7NEHx4?up.@걶oٟAI`b%ϲϸ҇FPO]@ѐXc>zH&ӪxF!e D䢣D48j_r`r«J\&!ߪl`M7U0F{,< kْ[mHK6]hMo#t ^BM?ԕ 6s'́JUUUU*9uJY5/ ??1?C?U?g?y??????9SNoь.0 \`\D :Bj!.TZNgb^OaOAU/ Bl) _p@tFJ\*BOTOmdBRχ1] !OO >JAtVsGEI?O9'O[Ț|t}OO:(HFyRLRJQQW,Kr!__/ >$wA/8]&1O_07GmR­B!_W_L* *E(dLz__n@(yR<_N_BF6 Hv_8R DeSyprea%9AFhWdonoK=.!1C[AMڗeooF`*YK[n9xoo, 3СGt- 1o A_#K;_X&_KTPVCyGMk=H=t?3J??u7* |NMuWvRZMCP0=ȻJ1'FX@SFAznv!kMsFu. #[JgK':MVCgx!}?SߵBe&QE8MH*Bӳ2I»F~*I}7ȼ3>0dLJt)[vxZWAI#u]wb 9۳IZ_} 4Fa?DD\SU?!QUdXm{1E珬dvXrzB;1G!!F@`I?TM»碿hӕH*t¦Ĺ`v-CLV"u*<>!}J ,?J(%R d !c(:|MiMz ;Wf//!&ݪLa*#//»2@BJgDv(/:/=" O9=)#//A7A1z$?6?H?bA ZxBCvY5S0t2ngA:ɢ?[KGf+w6O<G/cJ8A+;bOtO%-V ?C!߈C??`QڥA&=$kr(O:O de?M?%{3,??O?;HB*(I&ar}V:ɿ5J5ߤYn`_r_BwB%'<)_;_AOHݏϟo,o|9QIf? 4Ѥ_<:%DӲ%h__ ɜf8UGUsf)`Chbn1pl7cBI$ @?]_N 2» _G.g$b8a9GD?D)ɽo1tB*oOԁaL ObL8єNTYXVHuQ^pԁ3KIOolN\Mhy叿D $A($k.4R9 1ҦjOAc@V(Ngߐ8 `jfdjH裛Ґ4@ndz֟(HJLO~ҏީ"eGA^ (<˧G lUYO<3B0lHOqNLS@P0B We V+O/t3},jG7a3hC E{Ma` 0nO6$Ruμ$5.aq Oj5c?H KqoO8whf/x/IC  /. 31 ?ob2ov5r;dTA^1yW2h2c*3,C2n ;|!~!e2f7o~93. oTD"?Kt/?bY}vrD,MER Y l5Iս.iBC]N)%,h? O tCڔpGؙ? ~l5vFF6_QjOkAz,>_&s BqR:ERD =:]E`9SvOO L͕I&}BfOxO4UBcNz^_p_MpIL"zQOO )QWIHZÚ1*_ 72L--Sdr`p7 lP>! 0D>,:Kkϖoo ۴gK%iǁ\op w^H?m>*VohofJ<__Y~qJƩ^d ooNOeqT&sB)\p7]1OL@v'+.WiJ$YvKzHЖ.B<*"@zW+KBEXᲕr" $)K"[qP.m􉵯)LS$)!>ANUw$lq>f 6Os"yҏ ZQZaN;PD{ Ο.m vQLJDS𢑬lة)6(0oMngFXl l16A _+X1ex_֯LnC9MO5ߴ"lF$)JKf RUg[v!{@Ae".oל>Ilj7>lZ~qfLM::E${m{I? $r&ϨC_EMq w!¯ԯ|+dA CsG 24)G*1WтZv߈uϓANM=ްʿR/a5Kh, 1Fh6q|K*"FX狼-ߙW H,+$JAoۂIߕ8*Sr0aeJ+VH_|_kzSt6)F_{HdPi11۵SDvG/$/':2QJHFUlHwtL6X//gֲ|@?,C:8J?DWʯ8DrI?te0?B?@f=-,iB T*DogpF?nvJ??l>HF]FUu_zAEVVg!OO @B丟"`Ϟ˨(@4͡,v??VO*rjEP+c. __T?*O7B8tO//_6jI,l__λx]m,v)ID=L$A0ϸ-dƚH6["R_r@h2TA?ߥ4\7PoooO~O*At" GS]`/O '/.DVfdvjs)J)c*`_3{j5@{O)__@oVNۃ,LbU#\ cBQXiR"ol5_M8H^C]EEGK="F{QKޝ RdKQ+MW2Ml,~><~(beFe-~ϐtuh~ENGmOF{-@PO!(2b4lYhuDlDX(ֱ"cqpG֑DnF{ "AFITqxpٔi l yC~$VK_3MDSd D"D% ?n#HrAS(ZMƁPzPb )ucxAP"_ Fre%" Q\{NG~4documntagi[n'LrVC&6zMMEL ?;bH&B8_J_4G̏;~#C`9NO`O_-c&IZ~"6__OŅL_,@[x4"{OOJo8~s4LLP%vooX_mmWnNR?5SP:a_;hOwVy< 0Ku'B0}D*oool$F- 3I?OoNM7 oo 8j@^\0L^0}B5Gx)\q?t :|`FW?ZQZDBFB 6K?36Erh\G I2*@K8]y'bZM8nFM99/ϒnπF ̈́͠pDgF?JPz^@}L;ߏ7[VN$12qdtEEKxtÀ,8Bݙ@?OcT"߾s CF ]6L8:7@3$x$7I08?4 heC C,N :n@N^/vt1Jq&+C1 d/Q@z {݁? 7 M}rE?IB )/LkzJcCvkS4//,?Ly B({RZ?\kϸXF03D/V/'K q3CnǪ%P?\gmj[^ H?}V~aXj~u5v@(D?%L|5?Zipe6ED'H/Z/l/rDloFFZ2ǻ_/. SvLHl} //(8C]`6^KOId][lM/ /ƄˇK7>^?p?25>cuHmU_F? "!GDIH<vM JC/pkgW[htF؉(F^ ^emLKWKǨBp07Nr] *@$e}JnF rW&O8O\gV5ZM:9䝹r?HxAh[ΤxQ!BR apL`m?E z{_?9Ol[2@__xQ SL[ 0!)__PBUBl__ې&_WC=x__o*kx|$7K[_kkrmpDmKQ\L5AF;Ǒ*<ۇk!CWIolqϓYGorǞzoo(,oMR%'oz7rJ6Kul~*kCAŬiTH gU۔B0ukhL_1IթEgCp~!*+*@VMcY0x;+POHK}ddv3܂ъGh4XVH܏*k{Az@jU%PK*>A(xQ.;_}H7HR`iEB]n"P]϶)Jdf`rP v ߖI?j%Rdv*kzK\MO0Љ 0S?Xa1I ږJJ!4.2ȿڿ';GMC. >O .yG d(7v%D0a OHRXQEG-Y+3DF$ϗ@l h qڌG@?kov0B 52ګ[>Ni/z vrHrhzQZ"AB4Ա e(S$O~ G2,?.?@7WY1BvYf%Ch"n1 l"8;|NfSW|cp3 d3 0H$@ASp??=ٰeKH= "a"K;K~J 7~O0OBO]DDt< J""d/ 39W@;dEd7"k<*->VCز)͒OOOG|DKd!r7 K6ab_DH?K*6_H_Z_M?MtY'k%mf%pPlAlrMV +:K@>u<___r̴"N+''!r; r!1K1Pw@EaQ<1ISK7/ؕ"Fh;=c @?vag3ov?@e'hACs? ayag2V@&fyBdEsKlHXuC(CЏ⏖;#?1@6&Ep1D!I3xhbEu?0(r)9}Eըb. c.GqED+S.@=8ArZ,bK $dBMq-O(\<1Lyo ur ~5K$f/x/PcEKct 9ltDN\f(/:/{N:N@?]4О// nx@KΧ/)\DC.Ɠ$g^It*j/# G`8Ɓҿ pBحdy3Rd $T~BB1l2:$ I@,юYyP)Oaû<(ߖ;Y$x¯D%H>WfUECc0ddLkA*BnIZ)|oj U)z9I5( ٣`DQYe&Tߠq"z3I/0ߞ_gGD F&DܣȔ(:;jIH?}AL瑹CrTb 6!^N2J&PvO2[Cwb>sNs<<>8F9_)+qX1phX9b\O FSSV<,>R6cC ?.AF0TD,>QcnloaHHC6y!%qɌɿSb'`hưmX!CIڤ] ʋAAB|5$ OpDϬψSxab)`a)`~a˦;fqG4S&߇9cfub>q]˅C?Ple "ʋexYu7M}wA= /RZ<CNW|(!bdaq icb"ayٸ@# 3Nvi!f F`@Luudocumentai n8o`&}thr]aSJClVh$q7u*ipl ls] ϿJ},[y|pYdޙ|Jp6&d }yYOW=ld#3'L@_zyn Gritc冩ZUMpWRh"!b/l/tyW~4F @0UYUsaid+mnsDF%"b=xNt.]W /tdIuOնR/d/2zJO/-.K2h1w"z1j] a,J kP//?!11nW=9)0OJ̞Z_O$&O8OKO%2d@G] g$K)M^Gc OOOO"QSr#Z] 3n9x@=` _$_0_C_IcQ(!N] TdzᭇB%h)l&1__' &_D&!r`|1]}&L\mYVo o2oEoBu:2CeM`CX] ~CNUooooIf+p.1AQ!` DaKrY'E^A#C&8K2fcRqwprkmFu@]#w]Dtb)V@BfgyL$6IIIs{0&#mghNS@UoLvBPcrkgkĖ!RBW*ɞ=ӏ!` PEx94H+?atGI̔B˟"i'0] * ytyDwPl#v"4GIg)2bavfk`J;pJ' ͯ '8 '0J56J$$6I4av(!ri)yIjHCQ' ÿ]Flq O`IG+&9W1dKQ>;!걇' [d J&Exc3 o 3ݔbautSn A?46qqy$JgV 3x0*DD>$c:NGT/&/JAPa Kzn$;=8ArZ,QR <<>8F9_)+q9V !IE'9ȐHmU_F6Ȑ"P/NH"RF~$)JKf':2QJHNOeNM7 8~WRKYʣݓKD9n6jCF)do}Y$x¯D%H>fUR-&맑k@qGUB5Gx)\×Kx" Y1BvLjYR~-F/7۴I08kIrC +RC1 l16A +Xt1Jq&+)4Du\D,v)ID=L$AEL WH[M?@X%ʋ@N@ /rh\G I2*@K/,iB TcQ+MW2ˡ%L|5K q3Cn%؋ɖEB$rVaNz}I)[,Z= 'MRHO FTR<5;*>C2 eXaʝ$BM })Xaҗ1ѝ`C/}àP-ZvMO]ـOEE.f?s CF ]6Og|@,ϦC:?p-ߙWHF̏;~#C`9ZoPe0Kc?b֑o{JC"^CWEEKxtou'B0}D v˨(@4͡,뚏)G*1WyDloFFZ2C]`6LiI\N]?gQN^]ZV ŅL_,@[x4"{_-vQLJDST2W ʂNr72}Rd#\ cBQXi.6q%i6L&c ٳk=Rޟ ?n#Hr9Z!JDu/~qfLM:ى)LS$rMXs A íy B-JNQɢSt6)F{Hd~O*At" GSȢuC\ZNucxAP"LrVC&6z<4s_3MSe V+O/t3},nP5LLn[>M>MhhW@;Մ]DDt< JcX@eN"BMq-(\n;O wC?AM?>\:4-Lnlx¦U5sEwi󎕸-_(M޴K^=cMr?%!c-XFO++1z SL''o2}x?CAK? WʓbRGݞ;J"t; )B]>vO2[.` X1u@GB*&bMbM=w#F>@kI)IX5I /x|$7K[k&s BqRCAŬiTH g $hH+]WI^yglIsJ. :C+KE 'MRHO FTв,T`ض`8o.*&!3"K]u"ԟ"/"GYq"ڛ"//+/"C/U/m//"////3+a/4?'?6??Q?7i?{?8??9@????;OD#O<;OMO>eODwO?OO@OOU/ Bl)VaNz}I)[, &.L%F|\2,BK(N{X0"P/NH"oI?Z3_ |NMuvR_vzNՇ~F_2FDIE(Y$x¯D%H>fUF=ev y_]DDt< JY1BvYt1Jq&+IڄEI1rdpContex`oBoog"t; )B]>vO2[5;*>C2 emMY{Zo_kI)IX5I /lo 'w]OyeO!"#$%);&Se'}()я0 1%72Oa3y 935͟ߟc3 3!33K]p8$BM })qrɯۯs@c/uGDYvqwDxſ׿yDz+{CDU|m}D~'S?Q"i{ߥWc#;Mew 7Ias1R1R1R 1R3E1R]o1R1R1R1R1R/A1RYk1R1R1R1R//1R+/=/1RU/g/1R//1R//1R//1R/?'s'?9?1RQ?c?1R{??[S?D?1R??1R?D O1R#O5O1RMO_O1R`OUMOUO*efO_SM?MtY'km\mjS@[!}Jς ,?|o^A8ȟnEieK*:?};Y$x¯D%H>fUlG{Az@jUF6aN=QknE.ZG1ďnE,,H'^@\vLkA*Bn?IZ)nE1F1aol69;lZBEF>HH6\DC.ƃ=8ArZ,QlGJE'>nE<vMן B"N?+JnE VHX=nF  44O9%I/5;*>C2 elGJMOiz{SQnE+>@(8dnEEoE?LnEox_@|`/*FL nEF6 Hv8R nE?;HB*(6nEU'~C?AY6T75mF:nEf>+'J4k"P/NH"lG->zHό&ӊnE .yG ?d(7nE3B0lHYr6 72L--STo`fGlyo`hsS\ߘߪ{8uL'W&d}G;@@%k2S*lGsg;lsN?d E@6;,%IwPc/xnEov?@e' nE#?1@6&lG:rCIpPg*ƪ(HF?nEHJDB9a\(-̴"&tT GnW燹.tnEUVeMeamMX VaNz}I)[,HmU_F5;*>C2 eVTCſx$"P/NH"8~WRKYʣe V+O/t3},rdpPointe^RX MM{ ZxBCvY{B\3Ekgb 'MRHO FTzK\MO0Љ _1O_ͺAbJI{8a?D?D\S?ɜf8UGUsf)ag2V@&fyBov?@e' ;jIH}ALY$x¯D%H>fUPn*OF @nLѰE%/qA'~D?`kҞf8o`&///?)?;?S?e?}??????? O%O7O!OOaO"yOO#OO$OO%O _&!_3_f-xA?h[j-r|HJ/2pBu/sh_2/_S?}@kI)IX5I /bY}vrD,cMo`ooooo(:L^p$6HZl~Ə؏ 2DVhzŸԟ .@RdvЯ*Pbt(:L^p$6HZl~/ /2/D/V/h/z//////// ??.?@?R?d?v????????OO*OPbtΏ(:L^pʟܟ$6HZl~Ưد 2DVhz¿Կ .@RdvϚϬϾ*NbR_@JДئUE >/BHd(/н?}]" w  0keB`-Pack ug ,xML st t"!ru t r$oKf w #m }d lin `!^| dkOU]!G  nN(.?CU^pVX|Drag onut heqp ad ru iTfmd lHeAes.m]b~׿fl??nɶؿ<>??@BP(4,c 4И߿HD # =hj0>T h]]9 ^AUF?F@ ?@?Fd2L&\?P6 &t`]tu A7@t#)uAu` ?X4 \bu)mR b R6Xti]\@LXMJU2{Gz?<@L6p| =#s,$?R,&*#U*zc! b- L$e&##?>g! RU"<[#Q >"uB .bQ1ѤB,' 24#K4u#`?CopyrigTt (c)@2`09@M0c0os0fB1r00Aai0n.@ lK@ 8sOBe*#@e0v dC@4 l>]Uhzt1p4 BWaBE@JJ`&#;&F9Rbhb6QR RVVM(;! Q_ju:_6QpU3^__WpUEUV _,_ opU2 _;N/1rAb c\4(e7 iDAbE9 MU$g'_2q?p;J!4a5 f v>v"HD:  ;hj0>T h]]9 BAUF~?Fi4FW?P6 t`  ?u`b+uL .@ F5AF]Aku VgJqg k ]{  Vb %& !k+"pJU2{Gz?<@TL6p }#sb$?b&**R! ! ! K-\#V5 '=@*#T3BX\#MM=9$ ]> 2uB to11 "b $1\-LU2j#H4 %! \#117;`?CopyrigTt (cu) 2`09 uM6@c4@os.@If]Uhz%A4V@aRUPJ`\#FIV{{hX+#] :#RM(q!S_s_oQU3^__7gU5UJV!oe_EoU2C_;b1SrA bc4iDAb59 H9U$w'_2q[p;J!4aE vH6Zv"UGD # h0TdYYU@BP(?@hY?F~?Ffl?P} -t` YA@mY!Y0;9 699 6'999 u` ?+VEQqhuq+b8%A& A!`%a"a#+! Y^ ;"b9$ && U%ĉqj$} h#`UML Background A 0d-0n` /C D=1z\0'0yT">r7)S 7 0?*$ W#j#1s1s7"`?C0py0i ht ( ) 2)29 M0cJ2s0f21r0*Aa0i2. 1Ul*@ 8s.Be@e0v@@d"@8 .1`V0sU_1'02"@cPm!#5Q4y@*1V$j#SE 8eaM%y'Y;"U HAa%TYW(B^PPR|g eat_dS2YJTqTa"Fn8Da 5p0n B Jq@o 0e,B eq@@u#Axb$>g,Ica".ab9SQQ~d*drB3S]g)bKSiag,uL-Yg1Sj_e3_ta";"SSP2+!+!2FQFQ |~1~1Y@E^(@S9v7!?+#UC D0a&"a q@8 i"/??$74/6;"A&U%%Ɵ؟t&UUC \Aew.@R$75oO6AΝt&TESP-o q&*@GsPi0s+06@R6dnt&fQX@_B7&A&3ϸSPeǟ r+;UC s0űySm8q1 EArؿ*12%ϝQrQ]c|RdψϬ϶Yߨt&aX@a0eU& O0ɷQcu'4A(ȇ@EşSe%h r0&C +:W#B+!ahg`&!YaD^Ӂ}YaU5CS/љ~XqFUFi4F?F HHWk3)`*#a%$(%FQ&f flư()( tP5Ǧ 5}>/./@/iV/h/w 2@D/cuV&NP<9Pvu5z%??:;!?E6/l6/>R?/,. +֧v O,5;W&?8=CCOFTh?Ӂvu_=_HULs =wZGF !SWi#čkXw]B ;!Y`auiyo@+D}oWal7o[P/]PG=?`PUFD# Th(/TYTYBBUF??F BP(?EP3 g/ Bb>NbR_@JДئUE >/BHd(/н?}]"ҍt  0kkB`0Dep nd"cy,xML sta e$ru t r$of w #m !lKi g!e^| kOU$q3ud V? q , :FDrag onut hep s ecifywr0i emi# 3lZsi b t-e nwmdc cRt.aSbؿ?Ͽؔݿ?H D  # =ih@>T(E=R#ZAYUa??P6 u`u buA_ u  >3.T$ A@nu` ?"x)u"-a% bJU2N_N{?O"A"b)b2r#2"?8&&)&D4 "d# "ݓ2$q ?/6?\.?e#47`BackgroundCk0lk0rz_k %2#?|"7w=xGH|H2#L?MXA"I!"k #iFQiF!#iF iF sFsF sA4{2##} "1@#>!?Eb R $% a!"!!C/ z^?AVf{Q?2r2?@IPρU   N}?#AQ?"*ELA-1{2 wԶRRu&.$R8bHS"g Ru` Wc "HG>Gh`UML `?d`Aq0dPoo0 /s0M=10 p1y"%2#2qAG;q`Vis_1 p2.c0hm!#5]4up09a)`?t1pyi0ig0ht`(c0)`2 r9`MYpcJi2sk0frt1rp*z1apib.`aUlw0 xsre[pei0vpdgp$"k,@!l8>rUh9 5qRUX@ a.aJa_<YEBcua8ϋAQqA ev=LGQKP.C?YT!IRgMiyUdv'4О!D0<> Fbgghe _T!!MN2hB@X1X138#rJ-?@:AZ#b#%=CV3uB cG502qڷSQTpePk}\O6γ`Skpap)e&Opy tGaU O6!Tp %Pj13rp&nozcj7IhF/!32КP?!kԩ//ܝkB x~0gg`&,Q~0Q/QPW0-o ,0#HUN Ls apA<F_L*FeKhm# bnb= ab5?eнsU/:/RȉH гRQ/Ы+"B  0a`+Cl s ,ML st te$ruc u\0#of w 3m0d liOng!eB^ ?5oUG*8(^PI41/???OO&Fu E?)7PV ?WQcu Drag onut hep s ecifyaefbKj!ta5Rv s%m%lrtuGu.e,b ZUiradTltnh%p.b~׿j4F??inɶؿ`0 ?? WGҿvnᅲ1e뿀D"H$?9h3?UG D  # h0TdYYU@vn?@.c2?F~?Fi4F?P} r>qt` rb @ bj   2AQu`P?wu)  4Y >DS'>X#h&X#|&TZX#č"""""""""""�"&#D""N"&I7VY30!3 3^2'"""66j664] aD @V 0aU>B`UML BE@ckgroundk@A@d-y@n` /Cg@D=1z\0@ytZFK@>D>B>C304  ,Bb*DF 2A,B A񤤍7GI   0?QJ T R4CGCzQ@Q@WA`Vis_1@2.q@hm!#54PCB`?Cy@pyw@iu@htk@(q@)k@2B9k@MPcJwBsy@fRQrP* aaPiB.k@AUl(` Xs,bePew@v>`dP3D0!8e0!~aa@0!ki|: YH;HdkEd0!kUd kkUdkd>k|dZkhg)ɳHcPLtEM>@N Zu@4daF(ybTZ$>BJBRIkRB|<Ʉrd KE=%Q`%Q+~a~a;HQktf8QrCT&XAg'h+h Bg5B'E/4FB*(h#U@Cbr#kU4@@Qɜ>#tzQBD>P|W@~aMGQ#I2Ѧ CvC?C$>GCZC? .!?k#EuF^2& vvjf FW %wt$Cbtp%a-Q&VF>OƐDiF4ǁ@rfMN9(t*bOUҁgC˙S`R>`pbQiPt b `ӁAaQabUj>`c6dwPtPiPi(`asRPr{@u`hE@vb~CH=aesPsLg'"D, >Bp<c~aw>B&#DT4D4kR;HR% g`zQ`x~8QߋzQ,u`Gu`MaSrNVb#>$B` ExPwъCrwBwח67X2ABa+C2EE @Q,HZl~66W"4FXj|66iW(:L^p66/-A@2QdNWclt5鷡^ 4ǂKQKQr@4;Ht~YiU]UF"IDPa&uBaP'VABW`U@L BG@Ic2LAo%dJ`Y-b} / `MP)=PQ4hy9YR!V25u?OT!OPVS QeI@AwSOeOwOOG5OOOOO3F1f=CS kс&$-_?_Q_c_6w__'d___Vѣ`_"kfjo2^ogTo,M;=CDAs*y SRmac E$ro!o3oEorQ2\fr 0ci5oo(ooo4MԠ(@@QaRe Ly&WrO'_oT_oM?2O%)PƁr&Rz&sPQ?Iq4!HG70Vo1 = 5¿Կ{ &%N&EHOd/v/ 1姥6&0Q~+^0v(ϕ+ߙp?|>d$6a$@%>wb}/d6/Pbtτ) \n^H43,^qJ0qQBb81J0eD!;eHD: # =h ,>T  9 #:AUF~?Fi4Fw?F<@P-DT! ABu `u bu  -B 6@Bu` ?Ru#]"B<,O>ڧ Ba bJAnBU0U"?DM bB Bt` @"t (hp  ('B$$'"/%)7-H3? 6MK@bJ6 1115 `?CopyrigTt (c)@20@9@M0c0oKs0fB1r02Aa@i0n.@ lM@ 8sQBe%@e0vc@dE@l>#!Uh#3 A 15@&K0^@sOa)J:OGSY[ B[/_gfG_HD: # =h ,>T  9 #:AUF~?Fi4Fw?F<@P-DT! ABu `u bu  -B 6@Bu` ?Ru#]"B<,O>ڧ Ba bJAnBU0U"?DM bB Bt` @"t8 (hp W ('$!$'"/%)7-3? 6pMK@b6 1 115 `?CopyrigTt (wc)@20@9@M0c0o%s0fB1r02Aua@i0n.@U lM@ 8sQBUe%@e0vc@dE@l>#!Uh#3 A 1M5@&K0^@OaJ:OĪGSY[B[/_3fG_HD: # =h ,>T  9 #:AUF~?Fi4Fw?F<@P-DT! ABu `u bu  -B 6@Bu` ?Ru#]"B<,O>ڧ Ba bJAnBU0U"?DM bB Bt` @"t8 (hp W ('$!$'"/%)7-3? 6pMK@b6 1 115 `?CopyrigTt (wc)@20@9@M0c0o%s0fB1r02Aua@i0n.@U lM@ 8sQBUe%@e0vc@dE@l>#!Uh#3 A 1M5@&K0^@OaJ:OĪGSY[B[/_3fG_HD: # =h ,>T  9 #:AUF~?Fh4F?FYaD+Oج<@P3žm>Bu `u bwu  -B 6@Buv` ?RSu#]"B<,O V>a bJABU0U"?#DM bBigBtj` @"t (hp\  ('$$'"/%)7-3? 6MK@b6 1*115 `?CopyrigTt (c)@2U0@9@M0c0os0fB1r02Aa@i0nU.@ lM@ 8UsQBe%@e0vc@dE@l>#!Uh#3 A 415@&]K0^@OaRJ:YFSYL[B8U/_fG_HD # =h4>T]]9 P#AUF~?Ffl?P6 t` ?A@u#`ҍSpb@3} b&uLb . u-%8A   !a$$,  sJU27qZ ?Y/k&?\.+?4"k&*",,'8">%MS${Gz|#e@@#tL$tA5++S#.I>[IS#MAM32 rU<[7#b6$U6>%BNt?)B|$P0r %#,%, S#0A0A0G; `?CopyrigTt(c)20@9M@c@os@fBAr@Aa@i@n. Al@ HsRe@e@vPd@?$l>0>UhhCAjEDU@'XK*gDJ`S#FV C$$a" "34bM8%1_'nJe3ZnsoogJe5ZeVoooJeE2_;IBSrAIBs0idTAle59 6Uw4wK'%;K!4D8Q+ v6"vA"j`3y2;F!3Ă# 1C;J, o/b>%@06 T HD # =h4>T]]9 P#|AUF~?F4F??Ffl?P6 t` ?t#` u!bA@3S֍pb@3 b&uL+ .5 j53u)A V a$! %U rJU2qO ?N/`&?\.?44 "`& ",,'-"3%MH${Gzq#@@#t1$t65++H#.$>ZIH#MAM(2ʍ T0>UhhCA1l1:T6MK*\DJ`H#FVCHa "3$bM(|T_ n:e3Jncouog:e5JeVo_o:eE2_;>BSrA%>Bps0iYTAle59 6Ul4wK'%0K!)D-Q+ v6 "v6"j`#n20F!3  &C0J,_tq 3%506%e HDD # hj4>T]]9 M#WAUF~?F6f??Fl?P6 JtM`  ?)6Jt#`  u!bA@RJ=UJ{uL5 .?M ?p ~bFd2L&?<Ju)3$ AW kya$,# . # .>JUo2qq ?p/&a#?\.W?>V4 "&8"';D}#b&22'?= "'J+j#.=#* >j${Gz?<@@62Jp C)3955*:].c_2V"M%HC_3F#F2C5!*BFj#a$a%5 " tB.#b-$FMEș"H?wDB3"#%)# j#AAG;`?CopyrigTt(c)20^P9MJPc.HPosBPfPRAQrDP}QaPPiBPn. AlP HXsRepPeJHPvPdPNDi@ieE9 pIXUK4W'%KZ!D0. VpF "%f62lJ^Uh[a9QK1" T^(`j#aA\F<"/qI' "=#Sra"@J18~iu3z}sW3~23g13tAu`~u7 DfE|uR3~1",(2a;a#t:DriuEazw#Eut"v2;RJrA.ag@~8.e HD  # =h0>Th]]9 P#E`AUF~?Fi4F?A?P6 t` 6t#,uLA-@ J@JVu  >  Ra  b, JU2{Gz?@L6p|v#s.$?.&*W*e!b I5 E@@""<(# #2r. "6!MAM@ i! W"1` b1B(#*1*1*7;`?CopyrigTt (c) 2`09 M0c0os0f21r0!Aa0i0n.  Al<@ 8s@Be@e0vR@dH4@l>]Uhz1(#W8A "*@Q"W"]#b @iW"J]#J)#"J`(#gF9u 6Q $"RM(=!cWp__QU3^_o UZ5[mP>o_boUE2`_;C2rAC2c4iDA bZ59 t6U$/w'2ǥqxp5;!a5 /vt6 wv"jD 2!$56$!3@wv+3v5:vKkP._H4U NLs 0V-A~FkKs#iVuOB $j]aui>v@+BcaGlKfLVLL LdL L L7 / LN=UFDfP h(TYYCU?? F BP(?| EP0] g@/5> bnb a#V5?нsU/.:/ȉ%H гQ/Ы"B  0s`4Gen raliz t o ,MKL s !e4_ruc u . 3of w 3m d !ng$!e^ Q5oUG8(^PO41/??OO&O8Fu| n%  1:{<B:72/Drag onut heqp ad cls/if3ct3 e+>si b tKw eC&mJH n l)n!vs e)4 Ieult.Dzd3mbϿ?,؂-؂ݿ?_3OP?  UG HD h# 3h TB,]]9 J  AU@U?]ϿP6 u`u`bA@u]`u B72Xu` ?pu#$JLAVA-&-a)% bJ /"9(!:'Y#>2N贁N{?<@w"<`Gen ra_liz t ]o A r Uw{A(2}r#۠2"?u/!&&-T&H8"+ 4?+ 24B:0+ &2C?DU;;?3#9y?A%"b2J3@=N?8G9#BHvGY#WBH35 ^(WBKCBC=CV`UML B ckg"u d"dPAR9lUhE&Jq41c18T&&)r|)rcs L~ 1iXvw7'0e!40u 7qeFmW9DQ?@iq?𙸂XWB 4-T(Ra3 w%s!qi0@|:wPBN(BpheaTA$:t(OTAdϞAc#)q @?0rZ+ h !:024-[WXbֻ\ukZc2rb3q0]`\.%"bTѯR%U+!g W,ɜ3T!!w"d23)q)qBhhRvv5bY!Y!Fb7 YaYat(0p$6sբ85bTD3W,Ya3#BjB2BTh]]9 M AUAA޹@q?o@I?P6 .Jp   o@z3AE&9JuM`0b7 bk oRubnB]AvJuL`UA-!Jb #m Ja+$Y3  >OJU5 ?"E!\{"3JG"Z#5 #?& ?Aq'rBIZ)" &&-"u3%<% bG#'66$Q%Q%P>?">#6 1JZ#818187;+`?CopyrigTt (c)@2`09@M@c.0os0fB1r03Aa@i0n @AlN@ 8sRBe&@e0vd@dH"i&Abu59 8xU]$G'2J!$a% F6"FH"lTJM >Uh:U]1'~6Q4*,#3%3%3 N(@Z#QSJ^BQrRT?H"HU. Ls K-;~'+_AhF i}#;!LNeB CiNauiU@{+CY.aG!i͇= P %iĨUFDfP h(TPYYBUF??F BP(?P3 g/ bNbH_)@ДئUE W>/BHм(/н?}J]"t G 0ka`+Us ge,xML. st t"!_ruc u .#of w #m d liIn `e^| kOU$g3u q? q _׿k / =߂M=NDrag onut heqp ad* e e*_ncyr ]ltisi w@\ Bem/t=quI@snro-t flCy.H Jbؿ?Ͽؔݿ?H D  # =ih@>T(E=R#ZAYUa??P6 u`u buA_ u  >3.Tu` ?lu|"a be$Ap@MJU2N贁N{?hO"Abb2rm#2"?8&&)&D4d#H"2$7q ?/6?\._?}#47`BackgroundCjk0lk0rz_.k %2#?"7H"=G,$H|2#LR?MXARk iFiFT!iF iF sF%sF sAM{2## "1l@#>!}#?Eb R } a!!/  z^?AVf{Q?2r2?@IjPρU  y N?}?##AQ?"*ELA-1{2Y @RR[u.fb,}$Su}`=dB7 "IRngHG>`UMLW `?d`Aq0edPoo0 /s0}M=10`1y$Gdh2#2qAG;a`Vis_1`2.c0hm!#54up23[a)`]?t1pyi0ig0Wht`(c0)`U2b9`MYpci2%sk0frt1rpz1apib.`alw0 xsre[pei0vpdgp񿀩"k,@!l8>Uh9 5qRUX@ a.aJa_<YEcKa8ϋAQqA ev=LGQKP.C?YT!IRwMiyUdv'4О!DE0<> vLFIRwghe_T!!MN2hBrrX1X138#rJ-}@Q@AZ#bEC%=D uB 5!02qڷSQTp?>? UG HD # 3h @>T(]]9 TJ ]AU@BP(?@vn?aԿP6 u` ^?A_ u#u /u]`!MHbSu`u DfB{R.JAA!a)%] bJYJ"?"I/Kd&T'}->U2N?贁N{?<#2r!o#!"?𓎾&&v&Bk]; C"; !92?6"2?; .4602]?o;񶮸#@?@ ?@?$@&7c#2<S#2-G}#27L'J~# 3' #>a4#k4%E A" tN/zs#" DL(5 `UML Background:P]ANPd-HPn` /C6PD_=10nP1!y#s'I4RjCVCV CVCV> VQ@]QQ%?"%a5"bD J6f 6f6a 91 bc bcbc#)784Aa߿@q`?mg @X"FL /A-_!}!qb "w92rS!0wA3gr?!1R  husRruy2[@1ظ#AG;v`?CHPpyFPiDPht:P(@P):P2nR9:PMEcJFRsHPfKlev U q 6%EP5E P3EPɨ8aCPb!ޔb" !!l1Uhb@)34'a918ag_<rr-sJqAq#gK A=8gr?@@k RP A?Q!ͦaC# (ӳc#VVŲϲٲx(VVf1&ur24#;!BaV%l{ wRrX5GϰYU5bgfG?EՐϢϑ ףp= ́ ߀ŷS#ӳ1 WV#WVphe^gaT"2PK11 R(GTAhGҾ?A#xbtٳÔԷ!_XٲX bGA 4gr࿙_v"1!3|@+ u מb]-m/XZlP U?/3?s Ӆ*P/_X?X// ]QTfe{RQQC)DbmȺ@  Łepwk.=Rq_`UaLBckhu*dd-+ /uM̀=ЀZ5yrq!DABNjOO_!V _ח_X⠼_W0_[;DƂpaA US5Rmnc EghrkD_V_h_hz_W_"Brl3%@V%d=o_ao_ffoBs6HZ!V=SIa?ei&bO?<_ooo@Vɑ_]ܒ]!V.P %)Pbqr&3Ro:L^P1tgDANOfAqO ǢC!pqr\qq" ! !C&&mB!A!*Q1*XQ7` űm᥀7@k'-}N1\љ"2y>WͥDŷϑ  4äݨ%YP$󿙣*0r@@ʷ Էp}s^mgrr@ ׽/#☨KmEM"0Ap!îA>{]}0 !*0b`*ԈȘC"b3y71Ьѥ@8?"j̒u5u`p7u `a#QyDW@j@`uLѰ0hQW cuQ`v-4 #y^P`c4>Hk1~"0o+SK2R5Pp`ebQs'as`o`ip b5Pt9Pe o'cbif3Ra( yx1;ӏ,,q|qiDA/|%yX̒U0ѳ'0qu?̍!.0˅ BOT|_JKHD:  ;h ,>T  9 BAUAhf?A 3~@q?@IS?@P6 Bu`p   ۢ b bA)u,]uLA-4b .J z3h6> "& !m a9$YA * /ՄJQU5 }Kx(&""&'3ah) ,"?!;nh 4;" L# b"U#BM? MAM"gL#l6R"X-4m0+" t` JV"h#!!';`?CopyrigTt (c)020090M0c.0os0f21r0Aa0i0n.0 Al2@ 8s6Be @eJ0vH@d*@T$l0@Uh%HI 1'H6$4:#A%A%A pJ(lAXR@XiAb9 O7Uk$KW'01!05 KVO6+"VV"HD # =h ,>T  9 CAUA23?Ahf~@q?@IS?@P6 B[u`p    b b_ASu#,uLRA-4b .lJ z3Q6VA "& ! a9$A * /JQU5 }Kx("E"&'3Xh)E Y"?!;h r4M" bU#)Fh#M?MAM"gL#c6 ,c1+" t` V"%Bh#!!';`?CopyrigTt (c)02U0090M0c0os0f21r0Aa0i0n}.0 Al@U 8s#Be0e0%v5@d@T$l0 @Uh%I 1'?6;"a*:#A%A%A AJ9(YAXB@HB(*e 0AbE9 F7Uk$UW'a01!0E5 UVF6+"VV"HD:  ;h ,>T  9 BAUAbf?A43~@q?@IS?@P6 B[u`p    b bAu,uLA-4b .J[ z36> "& !a9$A * /jJQU5 }SKx(&"&'3Xdh)"?!;b r4M" bU#BM?MAM"gL#c6R"$4,d0+" t` V"%h#!!';`?CopyrigTt (c)02U0090M0c0os0f21r0Aa0i0n}.0 Al)@U 8s-Be@e0%v?@d!@T$l0@Uh!%I 1'?6;"a*:#A%A%A JPcAXB@$XiAb9 F7Uk$BW'01!+05 BVF6+"VV"HD:  ;h ,>T  9 BAUA43?Abf~@q?@Iϩ?P6 Bu`p   ۢ b bA@ut,uLA-64>b .؏J 6z3¦6 > "&!ea9$A * /UJQU5  }Kx( $"&'3$Xh) "?!;b 64M" bU#BM?MAM"gL#`c6R"$4d0+" t)` V"h#!!';`?CopyrigTt (c)020090M0c0os0f21r0Aa0i0n.0 Al)@ 8s-Be*@e0v?@d!@T$Ql0@Uh %I 1'?6;"Wa:#A%A% A JcAXEB@XiAb9 F7Uk$BW'01!0"5 BVF6+"VV"_0HU XLs Led'HnN\! Fix#jB9j]aui@+-aGiJ>? UG HD # 3h @>T(]]9 TJ ]AU@DP( ?@vn?aԿP6 u` ^?A_ u#u /u]`!MHbSu`u DfB{R.JAA!a)%] bJYJ"?"I/Kd&T'}->U2N?贁N{?<#2r!o#!"?𓎾&&v&Bk]; C"; !92?6"2?; .4602]?o;^#@ B?@?@?$@&7c#2 a"4#k4%E A"g tN/zs#" L(5 `UML Backgrounud:PANPd-HP}n` /C6PD=10nP1!y#s'I4RCjCVDCV CV(CV> VQ]QQ%?"%a5"b*D 6f 6f6a 91 bc bcbc#784A~aĿ@q`K?mg @X"*FL/A-_!x}!qb l"w92rS!0A3gr?a!1R  usRruy2[@1؂#AG;v`?CHPpyFPiDPht:P(@P):P2nR9:PM*EcFRsHPfKlev U q 6%EP5E@ P3EPɨ8aPb !ޔb" !!rl1Uhb)34'a 918ag_<rr-sJq Aq#@gK Axb@tٳÔԷ_XٲXX ?ft_v"1!?3|@+ u מb]-m/XZl U5?A\P/3?sӅ*P/_X?X// ]Q Tfe{R@QQCD bmȺP  Łepwk.=RqW`UaLBckhudʏd- /JuM̀=ЀZ5yrq!DANjOO_!V _ ח_X_Wh0_[;DƂupaA S5RUmncEghrkD_V_h_z_WZ_"Brl3 @V%d=o_ao_BffoBs6hHZ!V=SIa?ei&bO?<_oooVɑ_]ܒ]x!V.P %Pb qr&3Ro:L$^P1tgDApNOfAqOǢC!pqr\qq" ! !CH&&mB!A!*Q1*Q7`űmC"T @@kp}N1\љC.P1y>Wŷϑ4'y%YP$󿿣*0-r@@ʷ ԷsNNW rry hמ/☣K2;ϦmEM"0A p!îA@.{]}0wȰ= !*0b`b*x=ĉb3y7]ԥ@IL="v5u`pu `a#QyDG@0=]`@`uLoՁxѰ0ߑQGSuQ`f-4 #y^߱P`c4.k!"0+SjR5PpT`ebs'a'fbm'ogea 9PiJh'sanRw3spiT$c`i3cUd `ie!mrppTlwpo`e'Xyx,, q|qiDA@/|%yX̒U 'o0q\?̍]!0˅- B?D|)CB-M pHD:  ;h ,>T  9 BAUAhf?A23@q~?@I?@P6 B6u`p    b b_ASu,uLRA-4b .lJ z36V> "& ! a9$A * /JQU5 M }Kx(&E"&'3ah) Y"?!;h 4;" L# bEU#BM@?MAM"gL#l6R"-4m0+" t` V"h#!!';`?CopyrigTt (c)0W20090M0]c0os0f2R1r0Aa0i0n.0 AUl2@ 8s6Be @e0vH@d*@T$l(0@Uh%I 1'H6$4*:#A%A%A JPlAXR@$XiAb9 O7Uk$KW'01!+05 KVO6+"VV"HD # =h ,>T  9 CAUA,}3?Ahf@q?@I?@P6 Bu`p   ۢ b bA)u#,]uLA-4b .J z3(6A "& !m a9$YA * /ՄJQU5 }Kx("""&'3Xh)E ,"?!;nh 4M" bU#Fh#M?MPAM"gL#c6 c1+" t` V"Bh#!!';`?CopyrigTt (c)020090M0c0oKs0f21r0Aa0i0n.0 Al@ 8s#Be0e0v5@d@T$l0@Uh%I 1r'?6;"a:#A%A%A J9YAXB@H!(*e 0AbE9 F7Uk$UW'01!0"5 UVF6+"VV"HD:  ;h ,>T  9 BAUA{if?A3@q?@I?@P6 Bu`p    b bkAuJ,WuLA-4b .J- z36>j "& !]a9$A V* /JQU5 }Kx(&"H&'3Xh)2"?!;b 4M" bU#BM?MAM"gL#c6R"$4d0+" t` V"h#!!';`?CopyrigTt (c)020090M0c0oKs0f21r0Aa0i0n.0 Al)@ 8s-Be@e0v?@d!@T$l0@Uh!%I 1r'?6;"a:#A%A%A pJ(cAXB@XiAb9 F7Uk$BW'01!05 BVF6+"VV"HD:  ;h ,>T  9 BAUA53?A\f~@q?@Iϩ?P6 Bu`p   ۢ b bA@ut,uLA-64>b .؏J 6z3¦6 > "&!ea9$A * /UJQU5  }Kx( $"&'3$Xh) "?!;b 64M" bU#BM?MAM"gL#`c6R"$4d0+" t)` V"h#!!';`?CopyrigTt (c)020090M0c0os0f21r0Aa0i0n.0 Al)@ 8s-Be*@e0v?@d!@T$Ql0@Uh %I 1'?6;"Wa:#A%A% A JcAXEB@XiAb9 F7Uk$BW'01!0"5 BVF6+"VV"_0HU~ :Ls X!`N&- Fj#jKB90׸]auit@+Tx/aGgj PDj̝jZ»Tj@kUFDfP h,TPYYBUF??F BP(Q?P| BD@{Ќ,sUM\:/ȍH /\ ?:%UU"D G 0 ;i`/Interfac ,HML\s a"#rUu t r$o tw #m d: l ng! e^ 5 Y!g3uS E 3?É3τ3ύDrag onut heqp adexenl;yviKsEb; o 4aisf c;aGs;,qom qe~ckB~oeMm.mmb`f¿?^ ` ?8 t@ {WE `]߿0<UH LED D# >h4JTaa#M>U@x?@ `?@`f?@zP>uA` ?u#B2M]h6HI ^k6A>Jq`UM BackgroundAd-n` /CD=10 1yrgQNl {2N贁N{?HA2>r#%!!"?rj&&>&%! b !b񜔙ϹA'[۰0?$?=?J u`M-AW1?s.`$ %!uBA0`(r` [!f2# 5r@%ع14 !0Vis_1 2.hm!#5d4 3݉"`?CpuyihtU()2"9UM @csfHBR9Ar<@uAaH@i.l@ @HsBe @ev@d@.@Q03 7r#@KUl 7 Q`I1A 8"z1rF )nTv^?nV52  B3W5A SEA#l0UE 3 ,M A_UUS R N9hZƇXz1 b}of(!i USk_+_BFX2>go"DqQNo*y(}t:2mcbP,u?"dM@pi%<&QvivyNxg e[*W @dH@ Y~,aA 1$iSTQ3rr"qq@mr!r! %9vD?d0C Ae&w @..@'5 &QȟږESXo URl~HsXi<@s 206G3asږECaBCs @-@ik@ ItBfeͯ߯YAH%6HZޒ2`_-A! O;H5r;CUD BpyðSQmǰaA prϲr˯¿Կ!!# %A0N@(ϡL^ϖmߨߑږ=Ca(<@&O<@ %$8Guږ!@ Q%j!rH@&@]o*g (a!!HH!!3$l@7HⴡcT=@}qE#Q( 1yuPBEP[%,A PQvpgq@% + @Ucb NdթCUCipFAuB jBJy t. 84AcAibkNexn$Ay>v BlᨦuAZc,o@yAnAZBieF ,+,@HpHK/Fwif(%ExXG''2q FxU!uߑ{RJ5 &:1xUBR$slp3DRB HU Ls "!9ҕ8s_L \F/BHм(/н?}J]"t G 0k_`*Note,xMLʼ s a$!ruc u #oKf w #m d linIg!e^| kO UGu ?\?JϊQcu~~w|̄ޤ̆nDra_g ot] hep adny aex.imIb~[׿??2|&8i6?4?6BP(p8 4࿈=UGDF P# h=0TdPYY#]U@BP(?@p8?F~?F?Pn} t`A@Mt#u ?!u- b[*d d.   XT|5 N*?@+"" """ "" "("'&""" """""L79U42!^ b ĉa!9I8`UML Bm0ckground0A0d-0n` /}C0D=1\I00y 6U451N ^ ^ b\FFA؂!3TA;1;7*B`?C0py0i0ht0(0)02290M*@c2s0fBzAr}@Aa@i2.T01l@ HsBUe@e0v@d}1`V@Ws_102cPm!#54 P2 P[񕾕!4E 9e-aE]f5K6CUYH@Q5TWp@da_+5lT2f2d#4NNEB ! ! !!|!!('"(!E8%c_TA^dda!(+A>31 u`!su `]#i` JzAn0e0AN0It_RMX qr2af5aj@ooa"r(x4s"4FXjx v| v3'9kw v| vEEwяkw v| vWi{ß՟kwv|v|7I[mǯٯkwv|vb&8J\nhzv|vE -π?Qcuχϙkwv|21# _m8%c/e3oEoWi8%cXI-^\E`MK6;CDRp@a@ S@&RPa0Ac0E0"1r@[2???726 9r>5-f5d:L[Yx; C_Zd)B33EWK6=C+SPa}@e%&O}@Es!b)EE}6dҏ` %0Dr@&@A'9K]8\3g_`z(`Q2 a2EBsQsQ/ 1 1xbwR8 h ,T  J ɨUF~?F?FP Jt`aA@tJtM`0 t=t#HJuEM?pu_}Jb2 ]kVNT]M   U KG& G&U G& G&G&G&5G&#JU0U"?H@MDJ#" ?L%N}% bR;1#`1`1+*`?Copyrigpt(c)2009M0c0os0f21r01ai0n. Al0 8s2e*0e0v0d0*lJ$~U!#3 ~1|6iadBalCs@"(4#&&5 K$&G(| Jyp U uBGu0F2EO)O;OMO_OqOI!O~rxnTO_Ha_)e^U3_E_W_i_{___o____oli0oUu^ _oqoooooo4o% l\^]`-?Q8lS^aɏۏ#@GYk}dlSܢ^A+=Osl!^i!3EWi{俟ÿտl! 1ZUH LuD" # R>h-4JTaaM# MUF~[?F?Q 6>u`M-@FL&d2W?A [A+>> b .+U>tA`  7?dt#o>uluTt>Wb R Maa J && &J &O"U&MJ>U2N贁WNk?H@9 v#*p  b*#!2{Gz?&N:Un"eHD"3#Ib1g4 ;`?CopyrigX}ts(c)sW2009sM0]c0os0f2R1r01a0i0n.s AUl0 8s2e0e0v0d0 >`吀#+OP OtaF!lC$""O"0"L" <#pm#'7I tB.bUQդ7?o2 "n7# lJ ,JUl U1@r2/@ab`Ut(}4%JD@fSb?]#tDUPH3ybC?4D"# D"hc# f O#TfNc%JEGCmbuC5eChb$fbf `  Ac32mSgrM krrA2aEP{Pjztrrk|UA8Wt_@ oo$o6iT%Dv[k zca ^$n"iezee@}3UogcUxuPbU%jz| }eڅwgaowy @Ȁ2HiWiMpiE(WY4'_2q[Z!T0q5 (V2Q Qi]j-ҭ{tWV!yc'(o3Z1Cϒ(_HU^ pLs {\AD'F|ei#NS|? ]NatyD{+y0!R?GlsPdԷD_h(4T ?Td\PD'^,5,!S~UOBEK9SF4ҝ=wAwӝEw(NwmVwdԝZwbwD՝j uw$w#uwם<tGwGĚ2wT؝w,;t)oy}n{4ZVw\=hw sڝ{ϫضӾ۝$)1 I_dd?~S/ T U+=F]H ?|>@8Ïa@<g "*^p?4 #5GYk}D C:\Progam Files(x86U)McsWftOfe14vsocneF\003V\ULAT_.VSp}"4FXj| D C:\Progam Files(x86)McsftOfre14UvsocneF\00]3V\ULO`_.V Sp"4FXj|D C:\Progam Files(x86)McsftOfre14UvsocneF\00]3V\ULO_.V Sp"4FXj|D C:\Progam Files(x86)McsftOfre14UvsocneF\003V\ULDE_.7VSp"4FXj|D C:\Progam Files(x86)McsftOfre14UvsocneF\003V\ULSEQ_.VbS"4FXj|D C:\Progam Files(x86)McsftOfre14UvsocneF\003V\ULSTA_.VbS"4FX j| C:\Progam Files(x8W6)Mc]sftOfe14vsocneF\003V\ULSTR_..VbS}"4FXj|؎D C:\Progam Files(x86U)McsWftOfe14vsocneF\003V\UL\SE_.VdS_(O@ *IW ZC!Du+/wo ~/x. > D|aRzP qjt )wJE/#U0`8a[@}i_ڗ@ LTFD'yB uhz$T!  UF"H$ @FY,b'@FxD=2`1R)yqVrbbׁ\rցyT1AE uu Ec,UkU@x<@@t:N@F~?Fflk??yZ1X(oFFF[d[s) FFUlNClrzJPbbbzw@JP6Ws K_bcbn!v Saow(T >\q!;"A !Y!S \!]w\!qBo <*q0~L0aGO Q*Sҽx0=bU? I}gVPc1LFn4x3P4S˓ L1˕B Q$p!Uю4U0W}c$A>-OmsxA((r<$oAAb11 rs[媒% %ѤCC=B4 //.y~mB?bA4y{?*{)5fs {3W&&{$8459`7CBB-@4F99@29@-3@8c@EB96 q@59@}qsH,yK<˕lOZ~0]&)R4p6Ue2n8s:a:Ъp^g:o@ PoeN 0RePU.6앏K,D< 9C03ЍTsQPr/Q7.KC{3%bE1[ux` `R @V7~//E%2&1⏁bqq rs&&&2AA˕T*qeiCouq sQQQiMsQP7g5 >-zY_r'2&TGlkv>& UT4x8e)}?mWKLqp7$!Ii v%P&1앙TFi4Fo?F&?ŦÍHԏdӇlwwA}㦁5Xˆ$7}>ɀ̟ޟ@Q.r@ÅkYͯEz .l6,w;<ˏ6TWj!v%zv 1d/(7DVhzF?F@ ?@?Fd2GL&%0ӳ6s);M_qߕ! q6s}H7rv&v'v&v&%'2{Gz:L^psP{~!/YouBr[=?pUTq`rx2q~`[mϒ: 1SO{{C8Q`89{CP1E1<(QLp)5Ko?JGAiA/~ReTiA5IiBGTű Qt&_÷؆Ϧ@h@@t:N @P%tj53 //noC/U/g/y/////+N_ 9coiB(QQ>Jhp3Kua auͶaDz -?P?b7bpp4Q5ƟR5Q? 0U…???j|(efb|eHA̔NeV tđ9׋eKQVa@u̐U:@QQA 8.M-{C걁#iBac^H JkkRdϕR7~·K=겣RnI8fKcbhnA @uzK?GnAzOH5+fW&{DCFE3-Ơ3K94Р318ǐFР-ǐE658B} jEwiFUI+li])RprrsnGPsbpabpgΠojppgbpog +m̠dlbp e[. A,+겔`TGtiArC@qUK㙲R,|IruL`-g#, qR(Q(Q2aaRlQlQ璚R5aLpiARAOB'~q&(6:_o3Uz9LH ?9O:qPYiXȑ;aUFi4 ? F?6 U1e51=?8@u>:7!O8;^O6qOwǸ5}>0OO7>WFO_dB8dD5FYR_`15zEs__7\b^Ol6:J SͿSao 1 ;K?o52g<_ەVđezߜ񷸟ʟܟF?F@ ?@s?Fd2L&upSgyӯ寇 S??uB!O` ǯ/%u$vqaïuo2{GzϢϴ 1.р5ޯGH"' dZ!uf/x///(2%qW/.e//2S1-?|qXd uqPrZဟy>uG!UpV?O.@RdvЏ`$V&"F ec&"" `1S&`1#`c"4SaW6`ÓW6`aדe0U2 *1aa \QM ET2k5Mlf?c94SW&{5B3AP2-B6BD`42FbE`8`C9b88:Ab5}-1<@>lc;{>kMl҉5loP])RpeZe0tZ Z rutp1gM0o` UmdV VepB}u.-BfR~,MlDR9?c`q'cS*21 r#*0g 2K?cS"`Q1ĖuL`"!-2gn*1\ St1#Ĵq)2*1jR.x1126Ht01kak҈B1Rfn G4ć ?A{B41Y#LP; Cq^DQDQ2 DQufUDZauǞ?1.5*"DLd+>KO:35qпC*}>DV5ϰ/ dH;ϳ/y*{*zM_5<ދl6>/ ;`qOCw*6xAi `~ Ϡ79F?F@ ?@?Fd2L&Wsk}a //W/C/y)/s?)`0?B7rQ3 *13ͅ?42{Gz????9,c A_oȗ؟ 2%q103EC_q /uDmAf2>+^rp|QyyJ?x^O,>Pbt?(:_^pǑ#fƒ#fǑu/%P/b/t////////??B-???Q? bi3qcw?oX1}QdpcGq< ??ˋ^pDOVE@BP(@@t:N@HJSOOOOO__%_I_[___bY_^b>*0ЁpևQ *V hԯ毀 _[q_g-pc5gQg55Yo0U~ooo/() m5n3geh-qʻ_#cU kn5} (h1qE 5aӁpoo's5UԢ!)%%qO4 ?(e.Ơ 7S?(%1;ǐ?6?%}>@??'ۅ1>P6K?2Od4%xIЂBO8!5%zEOO'IŔNOڋl60JCAC_:s!:##?:Y.Ђovb$oMov!U WnOoo(o:ootӁ=&Vہot#࢏Ə؏F?F@ ?@s?Fd2GL&ups+?Qcuq+ݏF/Mt]!9@RauvT2{Gz¿Կ < Ѳ%L1zY=)%Nux2qA .?U/1/ĥq)|vqBNnuqrщyquu93F?8?n*%~%F&" #V&!" +V&!#S&#i(S F="W6W6,ic0U2&8}2~PNSe=NU;la]6 q[G~mD(xG(5  v6( e$7,qET2k5Mlf?c94SW&{5`614-`F`9`4`CP-A`1`-fAD`B`A`8`C}-1&>lc%Zq6DʱDQ ʵafUZ9Auk?1.5i*DLdD+ K%/2-5 qпC*?}>ADVϰ@/!*0;ϕ/ yF%u*zM_p9E<ދl6 ﳳ/;!ǖq1Cw*xA>cI` O7 F?F@ ?@?Fd2GL&9sM_qa/9/%/[)k/s?)0?B7rQ3S?82{Gz????9,cҒA_oȗ؟ 2q103EC_q /uDf2>+^rp|Qy0yJ?x^O,>Pbt?(:_^pb #fa#f)e/YP/b/t////////??Fr-???Q? Uecw?oU(}G0I&<\ \??oZl~2O@RT*@@t:N@HJSOOOOO__%_I_[___Yc_^bAb1>#p~փ1 )V桦`_[q_g-pS T `11Yo0U]~ooo/()m5Dn3geh-q@l_K( n5'(h1;qEd &G1aρ ok}o'sD<b uǢG Ge2AAׂ8Ի7Rҋ!=lԾww }*~%rbaAqe&{?6w@qǥ&e55ܚׅf뤥Wv&{130uB~E-F3-4]CU5kB7-}UA5C~A~|1}ߡuܐKvHl=])Rppespnpsagou&go; mdpl[eT/.߲jҶ,ܾ9ӵЄ*uDrwtܠҶKpFAc1o DpFuLE`-nm kyiӁXGHbܡܡǢUa5M1ׂ&&nnHkkaׅ1rG?rHZl~!<\ŧ~{e?cKcPKMɭ%eqaĸ AӅHܡ[AyGn?&९!%qO$A/y(e.ƭ'P/y(ǥ+2?&E?C%}>@r??z'ׅ.+6/?dXDKdK̂mBAsO4!%z5GOYOz'6N?l6:mCC5_:s!+ /O~%W@O*&ρ9RׁpŧԏF?F@ ?@c?Fd2L&e`c';M_q[ݟ'I'[UV&5&?2{Gzdv4UT%.e:L^p/2q+=e'%ol`a,o8oXea$jb.siaeooe #DF?/Xo&8J\n"4Xj|)ȏڏJ\nȟڟ`@'9K cq weKbGkQCeAίگiWTofoxo,od@x<@@t:/N@={Uáſ׿ ύCUύycX!*>x'wC8}| 'PVH"UkS'y&&Wi0UW"xߊߜ߀"g>"haPCe'Ef+ϲQE7h4!:(Ȫk ^ 1A1 e1I!4>"<4 1 1B7LDBR=fDqq !?bA% ?0 HI_K5LfCCW&{B1AURAh-34FR-iRhQ-x9gPu9eP1iP25iPU9sR2kP9}P}LESBML%l7_@])uRpesUnsagou `!go5P mdl$UaeN`)e."FDdB^,LP9C4@~aC*o"fՁBrqn!~G~BBjCgiAjuL`b-fGn>g}eT!RuAB~~_hhBe!e!"BaaA19@BTfxV$šu_/UfeO7I@q$[41eEB!~zeUsh?zŅksņƧs͛,?=}>zl~t@͞%ίdR%~Ꮞ} gm.zUzASt%0.l6̪g/4z~ֿ͛xg $1 13'FL?jJ)F?F@ ?@?Fd2L&ջӳ! |c5GYk}U! CS|c0}by y 1/# 19/K(2{Gz^/p///)C.O1N?.}%FŅOe(4FXj|2q%7ջ͏!4A1 Z&2 Rՙsdb=Յߛ߭Փ>?ԟR/ 2DVhz~ .?Rdv#}FF##8DVhz :R!3fE q]}CkO8q R0!GeգcN`r&/^I@BP(@@q8@u(ň*3//////??=?O??s?_9?RB>P؂aAqyx1 #DIIII(񁒑)*--?Me?GlC}ґѥMO_H0U钅rOOO  aВb[eH!Qd?pfApAbE`Ǖie% uZoAӡѳAa O_]@OS PВ<BUSY @bbe>b7޴wqq=lhmJY_RbA)QE[?*WQS_hY|5ef}w1Ws&}{p7F9`}Cp5-4.`C82AREpFB`B6b@34}k Ue| V>czwl4]ւs)RPppeUsPnPskakgpougko mpdPlkeл.kEB,BQ9}Ae- CaBzazaS a aY11blbdqdq>bwAe1`awza 噢h`aO!em'dc?le We/2@:Eps9E }ǃB/S_Ǿ1}>///elyӏ%_^٤<NW___ߏ o2oDoVohozoooo_/oToo{;5p0GpU1 p49r1-pC%rBCp!9:0BU-*/ A pEU4!p2qF pAS/w+=Oa0?͏'9KTFhcқy&ưHanA"Q_9KP#< R&h ex @F ơ@FdX,?FX0 砗c՞e /ASewQaQkvRijkvQسQ*@F @F`―J`x2L&`#`&#oooo$6wUsJx@s-\|os&0bs&s#5GYk+ϏOŅc'"@Fu:N b<@F_@tDN~L2nG>*FOO![ )VO_şן +OCU2G_ƣI_t!{q˯ݯ層fg8Afe)ovC&BT"xuϿ);M_qσϕϹP$Τ&%/A$ew߉ߛ߭߿߀ߤ+={7b305l-0ADjE02"j8P88l3t1nB˟);M_qv7I[mK]?$D"weBX5wCfB93XAq=OqZ.~eB @F&X,Fp'&>/P/b/t////-[/,q #r 3q3t*?5GYk}ůׯ鯀 \CU .vx˿%7I[m.ϵE0Ep5J4`B7U-`2`35AA!SEWi{ߍߟ߱ /$Sew___Oa_x6t2};:otMi`Mw%,Pb\t dnvj,>PWi >օ> ////A/S/e/w///J//)m/ 9[,9B4v5 ? ???e??OO%O7OIO[Kg|+pOOOOOOOOWS,_>_b_t_pP_o__ oo.o@oRodovooooooooUqk/H~&bt(@:L^pZ0ɀ0قBɀF8ɂ46ŀ-ՂFR-ɀkABAF4ŀ0O -?QcuϟO);M_c?˯ݯ%@ 3EWiKyD;BɈ"԰]8b኿b᧿{˿ݿO?%7I_jZV?r-4ϝϯ A/ !bt߆ߘߪ߼(:r^ c&2Fh@%鮧uϦsίXk% % \#̠ ?A6Hvl~%Ə%73c2%oo//'/9/K/]/o///////a- >6-???Q?4ou????????O)O;OMOW{9C@E1`qAF#1zBBTAA96p@0`I7$2aADh@OOOO__'_9_K_]_o________o#o'GoYoko}ooo[moc aм$~BѤ*LJuQq'J\w 1j>?u"p8_5{]|>@F BP@FXT*JFP0 <35N`ṙ^փ5A 1F 2F 1- 17I[mǟٟ5!_EWx,>Pbt F7CU5O5iP3G4#24COP-OPEY-D#2EAEŲl] 2DVhzϞ //./@/R/d/ݏ/l6fb/.vܻfG\1?"4-?Q?c?u?????8_(` 5jZV05nu OO1OCOUOgOyOM!OL CBzCBHO__,_>_P_b_t_______NoiFh@F,o>m!{eoob{e!,_iA'ooh/!3EWi{|X#̠ A)O*<_6Kg6vtO6Iʏ $6HZl~Ɵ؟' ZP@\n\xү,>PbtDK11ֱٰ2%19װ3812ֱB*D`A5o$6HZl~Ϣϴϊ 2DVh+oߞ_OqOS0RbWWi HѦFkB -?Qg(@F fF U M!3 @FĶZĶʵx,>vbT MRw/Q /"%)Z"E)[///ߣ//////?!R .@arCMrkzCvuQO _(:L^p $S ,@d)k{ev}O//*/\.?4qgª?lb;uP`u g ҁlooot `"8yHsu&\su&psz .@xd?ךf0raɆP!VF"YO FA-XC=euFOtO~Ɵ؟?\a/J?A_1e4*dvп*PbtP( ?% //0/B/T.Gi)y###/////??)?;?M?_?q????95BP(:E4O*C8BOXInDG0EIOOOOO _-_0ERK_]_o______VS oX[=oz_o]ooooooo%7I[m*-|DS_/ӃGP-47e#s2z2,?W*a!d]*aE5a!Ūl@@@u:N @F~?Ffl? tC-%(:L^pF/5RBq>PA2cw9Aba /fA2cQ2cіQh!2ch!!2c I!%/f++2EoJ:3c[)#PBqӓArBqBql+0U碅3R:)E eȧQdɧ9%->Q-%/A5`ť0iuXQѱBq1! _>oSH5RMM8B]5$"w5Bj5B5"5u5=Hkks"9OOV?vOP߮]OB5OO*OlB3UC-\@0EVB)6x@_A8RBBApyCUB@@F9B01KE?Y_eh_M9])R? pvuL`]Bp@nGQ2e__fQ9.o@oRodoCbb"uE`pa??ѱooN .ow$/6/opJ (5C*z|auB 0)y@*a!u1 oUU Fi4F7?Fcs?&e iU%v'-8/(L.7'/(E ]+Ǽ//&/%?}>- /?'E].&w/^?F% '%?w%Az;5??'ud=C?l6\: B%xunc%//2I =/@ __._G E{G?Gwœџ@U___G-|ArBy3d'yF?F@ ?@s?Fd2GL&)up4s /ASewя%r=`M Ml~GWe݆Vf݆ɯۨ2{Gz$6hӾ6bBx yiUz{ex 2q 1eK]dѱ_lonoo_ooooo z 36?d/N`rL8Jn CV؂ ֲ *PM `Q#Bk4b/t/V?@UABCDEHWt4"H$ @Y,b'@ seC-Dt AUU UU45U78<=U>?@AUBDEGUIJKLMNSt4"H$ @Y,b'@ L^tr}C-7 AUvU UU457U8;<=U>?@AUBDEHINt4"H$ @Y,b'@ 'ubC-*7 AU4U5BKRt4"H$ @Y,b'@ uC-t*7 AU4U5BMUt4"H$ @Y,b'@ ,SvC-d.m*7 AU4U5BOTt4"H$ @Y,b'@ , vC-tM*7 AUvU UU457U8;<=U>?@AUBDEHJQt4"H$ @Y,b'@ 7wbC-K*7 AU4U5BLSt4"H$ @Y,b'@ _wC-I x AU4U5BFVt4"H$ @Y,b'@ ,exC-$M*7 AU45B\t4"H$ @Y,b'@ xC-*7 AU45B^t4"H$ @Y,b'@ FyC-I]*7 AU45B_t4"H$ @Y,b'@ $yC-4J*7 AU45B]t4"H$ @Y,b'@ $zC-$J;*7 AU45Bkt4"H$ @Y,b'@ DzC-J*7 AU45Bct4"H$ @Y,b'@ {C-#*7 AU45Bjt4"H$ @Y,b'@ q{zC-#7 AU45Bmt4"H$ @Y,b'@ {C-DM*7 AU45Blt4"H$ @Y,b'@ dN|C-Ne*7 AU45Bit4"H$ @Y,b'@ |C-L*7 AU*U45BCDEnt4 "H$ @Y,b'@ DA,}$C-tLP7A@7tPR@T tMR@uNR@vNR@wvNR@t`vNR@`wNR@TaxPR@axNR@bxNR@cgyNR@cyNR@,dEzNR@dzNR@ e#{NR@g{MR@dk|NR@no|NR@o|NR@oZ}MRH<(H<(H<(H<(H<(H<(H<(H<(H<(H<(H<(H<(H<(H<(H<(H<(H<(H<(H<(H<(E8eRET8sRERERElRERELRERERERE\RERE RERE)RE7RETXERE4YSREYaREd[oRU/`8?|>@8?a@L LFuDTyB uh(T UF"H$ @FY,b'@Fx<11j4s_3MSqeiEPme u UiE)UH^qjt GvziEjta{Ujt<1wQlds4tI Sa_1CnOx_iIYPa^caυVdυ7$r`& nsert @MLDiaPr+mY06`hbbN$q` B+ck-ou`dAvdm0o``/C!D=201yDabEEbuq$!y SL!*?EΓ $$wDt% ЗEc)2@mo({ @@M?"GJ8 UKH3ܠ]a bADa#q<$s}qW?l_#?I`H1TpSaihU rrcueiU$w FXק7'_!0: .va0Um^c  $!$!9^cGaVQu@r־ϢB5iԀCq y a  u='t1uB} UnU@=@@BcC@@*>a@F$go?P?Y?JʯܯHC(F7FF__wbbbz^p@bbb <1Y uSavowopozۢ%/A [PcM_P2hBVJiECz0YBU? I}2SC"c L)ncU*qBC!!Q'tۉxR{ $!Bu^Uufx>q |L! }jtBq ӵjt$! |! Bujt jt#s\$siO~?i4Ff80BqpѩQ}*CY^cўђCJ$$}$ӲRBr <<ՒK$ >4=4B UQ]aV.r+i o`B1QooukdkbH%i]k4FlUf3i3W &{`U961`01E-p7A8JBkB`;AApUFz3`BFP6k}+aBu?Ii;?Gk[kFlՈOIi3P3$rFtLb-`rb@O)1bѓERpNVBWVa_sYW>q@&j71x7Bİ'\'?NR TQt3QwF)2 O3P `RRpnsUadgbcic`tB @cva9o @abjJraw)t*ai3Uipabs, bYv)euHas*as9U62N, ̿qDa1빹4@wa1۹.6Ϥ@"jWo?@!d>ơ'9K߃oߎ2ũ߻ ߇Qa1&a1S2{/Gz*<EJ \O$Ǎq ?/&3\.?ѰAsԻhz($ (㹊5#d4H$Se鍚 24γ18#5D .%O7OIL1\OnODOOOQDONA+Nw(" crn :P%rp"W,PS]b tmpZ]BX) PFe_____W P!too'o9o$KoXDzam`QUs`(TSt`ufcbiRbtn?0l~D* mn`i{bg*qg sbrd..P͙Dv8t0CBq5zzAjŕt40&V!3lm7V&ZSB.06A`BuGk=O"̈; lmU,S5wHɊ5*͉>~)Uzd,~QŞN2r2 A0ǡ~‰ Rr:Ffl&8J\n ./@/R/d/v/Ϛ//~|@?R?d?v????^uuY 8rzŸԟrPbtϬV/˄o!B&$!"L""8DVhzߌ /ANQ$&A4;.AXU$ _-_LRXaQT5Tdd?O7JDUD_nOO1OOOO-JD!O__ڄP3_E_W_i\{(QaI:`o 4UXV);M;g'[o3,60X,qktk +t{R0j,>UaV!3GF@QYZBޮNߡ`!hRG!k]Llle>^ ή yȵI7{iot$g?6U?ץ஥3//$/6/H//l//ƀ5//^^$?.>@63O?a?߲{???????BTnߓmW|oNoкWoU6mYz4p-G@UUBN2DVhz=@@z^@FA^@F7?ɫsݯDϰc#x5Gu` FqlB` b2ϕ/g3/ W"V"66WE 3,=0U9=lϠ~ϐϢϴG.e:т+eUUhQב:'+L$W'pQAYT+webQAQArQQ"4ҤQQb@1|q(/4ӽx72eD>?o?v???45"???45O(O:O45\OnOO45bOOO45%OO _/An7// 84%//)ϑQϑ_*+ҵ s UUr\d"J7vdҫQQ0 '9ԀFBؠaef4W[&{P98|La2-6L0P-41}5p8A3pU-4p2x`5uFE/C}j@aW3c""48`3Yf a3߾ido`^%Us t lcra cmeJt odarmq>v%{,l%E(႐hR~? WbѯffLvo+Sz"K' !JAџ,ƬTxp,%!iINCW!S!r ďU3,RzjMG_DȯDk*<N`rÿ!3VSSS! bS!l~U_.o (%fo{A$6HZl~W!t!^L b,8(!74}Vb)n@`FUQ#5GYk}׿* @1&t!:t!bϜ2N贁NkRќH*!3EWi{ߍx߱2q )= Qt$q2DxQw1rrG-pCia+ _Obj-cps=3asbrov-r/iG1yrhrc+i,nG ")sps3(t-1!f/9;3.P-adUk}u%4!Af-(Ia*f{BֱWjJ!GGujCQG{OjO|J-a&QQ DVv0MDOVOGۮOJ_OOOOKnOJeۦDo_rG js8cP-p`&wqA_@=@@'Ե@@*>@Fz|?Vt?tݽL V0%btZs(_"bbbz~.bbb<@L8h\ L[y ~0OXkXX R/%0"0#Y֓eW$Wd"!_3_F}J>j'90%(Z)*3b=@ą7MQQ8!&",)a<(ƂK!b63"@,!Z8,(%9/7"2A>,!gxujS|:?,8Cc`w/#/5/G//k/o/`///,EvAA??,?>?P?b?t?O??????OO(O:OLO^O pOOO+p(cD]Q N OO@AqYA4wo UA Y]UIQ>i_W@xihlr5rA>pVo o2oDoVohozoookBuoo osE&>qIUI2{/GzYsktyCqf@ֵ};\~Ǎq?!b\.?AY[(a$| aPeUVdS /]Pw!ļ鍢T !a8R?Թ2TfxQߝX?}ahlp+Nw( cn΀˃ :Jrp,p䠱rP) Fʠe!St6HZl~ URgs((*Q]Q]Q5Q5]M VqX5QQqVbt Ut epj^T#5VXc_U!%3`󛇜'fU_+F)`kFTD VjlCIQU{ UIQIYY] R~UVQƗ/ (Е'%& ?Bu/Z*QBq NF*_WU;#F/x//Q@/ML?%=.G?-쏆?1??<=[w?w~%O7H!'[IHl6TA[H"xmO ϻē9K`;ap?a K#Na`ʖA2@?KcAuOOIOOOO __1_i_U_y[@o`_\!BRSSa BrbQloo%o7oIeooooooo`u3ًU J\x߀|T!P~qG+=^p߂uԁH@&8y*E{$1:r*Su3!4`wN)UeGn ovAcJ~uUs5qHpbZjPWȒ',a!3@AoaJonm9@1`q%kRdUgb숀+rcq > ӏW"H%E5A::JC1KQ@z|?V?\4d5m5Qzeϯ=)NOMVpTRRBF_ٿ Jh~u]ooo8J\nπϒϤo-oPt[;X,r`w!|Ue7oe?7k`/lov=Na, sB?ĸ}PD}P, ;Q)U1( O-D&UA%U f -h"/T))+U- g&+ P`- zvT ?!-a *Q`H&Q- -H*)AU/["i-EQ./ ??feArial UncodeMiS6?/?`4 R$fSymbol$67fWingds*7 fECalibr@  ?$fSwimunt(S$fPMingLU(w$fMS PGothicj@ $fDotum"|i0@ S$fESylaen  $fEstrangeloU dsaC 9$fEVrind1a8 Q$fEShrutqi| Q$fEM_angl$fETunga<"@ Q$fGSendya*/ (   R$fERavi"o Q$fGDhenu"*/ (  R$fELath#/ R$fEGautmqi | Q$fECordia NewE R$fEArial"*Cx /@~4 R$fMalgun Gothic |w L$fETimes NwRoan*Ax /@4$DEEBGS.BtG%B@=BT?3B>5B4IKGBH:B$F̮7BAB3D0B6t1Bt70B7կ0B8;B49@.B:n9B=-BC԰2BD;BMA8BDyIBT1±JBGuideTheDoc"msvTheeCol r"Gestur Fom a Row_1"UMLDiagrmType&msvNoAWutCn 7ec Row_2BmsvNoAplyDwat Gr phicf eLnk Row_3$msvNoSubprcesCo}nectrHairlneUML Shadow.GenralWiztoW Ar w(Dynamic CoWnetr Row_4 Row_5 Row_6 UMLShapeTy UMLObjectGID UM_LEroBeginA7glEndAgle" UMLPresOption1(UMLSup_resOtionNa_vigblty UMLVersionDX1DY1DX3DY3end1_a mend1_mpend2_a mend2_mpNavigbleSharedCompsite,Compsite Navg b l&Shared NvigblQualifer&Shared Qulif e,Compsite Q_ualfer@Compsite Navg b]lQu lfer:Shared Nvigbl WQul f e,Navigble Qulfer"Procedue C7al (Asynchwroou_ FlwFlat ow&realiz_sub5hp real_sWubhp$Watermrk T5il msvNoAutSize(Left Asynchroo u" visDecrpton visVerionUML,Viso ExtenuddDaaPawckge,UMLAutoockTexE7di EnsureWidthOKDefaultWidhRow_7Row_8NameUMLPagweGID*St}aic rut re-1$msvTheeEfe7ct msvTheeOrdrGraphicsDepndcyClassUMLTemplat"UMLPresOption2OperationsuAtribuesPa}rmetrs"GenralWizto Di_scrmnatoUsage*Binary Aso]catoNoteCompsitonInterf7acFr}eRDPF3lE3'G3%G3,*%G3OE3T_&G3(G3E3tCG3E3'G3<7G3XQG3*jG3ܹ-G34*G3ߵE3E3E3!G30$G3TG3+mG3G3'G3dʶ*G3,G3$+G3̳1 E3̳= E3̳I E3̳U E3aG3'|G3اG3'G3ǷG3(G3 G3/G3ĦA)G3<jG3)G3$/G3dtݸ>G3=;G3TV.G3T&G3*G3XԹG3(G3#G38'G3_$G3-G3$G3D+ԺG3̳ E3.G3(+G3DA0G3,q%G3T"G3E3ȻE3,ػE3d+G3t)G3.'G3U#G3,{xE3<|G3+G3DE3+!G3'G3+G3+&G3,BG3^$G3,#G3XE3-G3E3h?E3$,G3G34(.G3h?DE3h?HE3h?LE3|h?PE3th?TE3lh?XE3dh?\E3\h?`E3Th?dE3Lh?hE3Dh?lE3?@ABCDEFGHIJKLMNOPQRSTUVWXYZ[\]^_`abcdefghijklmnopqrstuvwxyz{|}~U t4"H$ @Y,b'@ p" }C-dE/7 AU %t4 PC>-~7"AJ@39MR@ e7RH<(H<(JEd4RE6R{@4s  g"4FX8P[zD(&՘@(߫#!8h?Bl/  դ64`.tP{` v̭6 wR$  !| 3):R'_~1d  O26T?A*ODAH%a!FreeRDP-1.0.2/freerdp.pc.in000066400000000000000000000007021207112532300153140ustar00rootroot00000000000000prefix=@CMAKE_INSTALL_PREFIX@ exec_prefix=@CMAKE_INSTALL_PREFIX@ libdir=@CMAKE_INSTALL_PREFIX@/@CMAKE_INSTALL_LIBDIR@ includedir=@CMAKE_INSTALL_PREFIX@/include Name: FreeRDP Description: A free remote desktop protocol client URL: http://www.freerdp.com/ Version: @FREERDP_VERSION_FULL@ Requires: Libs: -L${libdir} -lfreerdp-core -lfreerdp-codec -lfreerdp-gdi -lfreerdp-kbd -lfreerdp-rail -lfreerdp-channels -lfreerdp-utils Cflags: -I${includedir} FreeRDP-1.0.2/freerdp.spec000066400000000000000000000061421207112532300152430ustar00rootroot00000000000000# cmake # make package_source # rpmbuild -ta freerdp-<...>.tar.gz Summary: Remote Desktop Protocol functionality Name: freerdp Version: 1.0.0 Release: 1%{?dist} License: Apache License 2.0 Group: Applications/Communications URL: http://www.freerdp.com/ Source: http://downloads.sourceforge.net/%{name}/%{name}-%{version}.tar.gz BuildRoot: %{_tmppath}/%{name}-%{version}-%{release}-root-%(%{__id_u} -n) BuildRequires: openssl-devel BuildRequires: libX11-devel, libXcursor-devel, libXext-devel, libXinerama-devel, libXdamage-devel, libXv-devel, libxkbfile-devel BuildRequires: cups-devel BuildRequires: alsa-lib-devel BuildRequires: pcsc-lite-devel %description FreeRDP is a free implementation of the Remote Desktop Protocol (RDP) according to the Microsoft Open Specifications. %package -n xfreerdp Summary: Remote Desktop Protocol client Group: Applications/Communications Requires: %{name}-libs = %{version}-%{release}, %{name}-plugins-standard = %{version}-%{release} %description -n xfreerdp FreeRDP is a free implementation of the Remote Desktop Protocol (RDP) according to the Microsoft Open Specifications. %package libs Summary: Core libraries implementing the RDP protocol Group: Applications/Communications %description libs libfreerdp-core can be embedded in applications. libfreerdp-channels and libfreerdp-kbd might be convenient to use in X applications together with libfreerdp-core. libfreerdp-core can be extended with plugins handling RDP channels. %package plugins-standard Summary: Plugins for handling the standard RDP channels Group: Applications/Communications Requires: %{name}-libs = %{version}-%{release} %description plugins-standard A set of plugins to the channel manager implementing the standard virtual channels extending RDP core functionality. For instance, sounds, clipboard sync, disk/printer redirection, etc. %package devel Summary: Libraries and header files for embedding and extending freerdp Group: Applications/Communications Requires: %{name}-libs = %{version}-%{release} Requires: pkgconfig %description devel Header files and unversioned libraries for libfreerdp-core, libfreerdp-channels, libfreerdp-kbd, libfreerdp-cache, libfreerdp-codec, libfreerdp-rail, libfreerdp-gdi and libfreerdp-utils. %prep %setup -q %build cmake -DCMAKE_BUILD_TYPE=Release -DCMAKE_INSTALL_PREFIX=/usr -DWITH_PCSC=ON . make %{?_smp_mflags} %install rm -rf $RPM_BUILD_ROOT make install DESTDIR=$RPM_BUILD_ROOT rm -f $RPM_BUILD_ROOT%{_libdir}/{freerdp/,lib}*.{a,la} # FIXME: They shouldn't be installed in the first place %post libs -p /sbin/ldconfig %postun libs -p /sbin/ldconfig %clean rm -rf $RPM_BUILD_ROOT %files -n xfreerdp %defattr(-,root,root) %{_bindir}/xfreerdp %{_mandir}/*/* %files libs %defattr(-,root,root) %doc LICENSE README %{_libdir}/lib*.so.* %dir %{_libdir}/freerdp %{_datadir}/freerdp/ %files plugins-standard %defattr(-,root,root) %{_libdir}/freerdp/*.so %files devel %defattr(-,root,root) %{_includedir}/freerdp/ %{_libdir}/lib*.so %{_libdir}/pkgconfig/* %changelog * Tue Mar 16 2010 Mads Kiilerich - 0.0.1-1 - Initial "upstream" freerdp spec - made and tested for Fedora 12 FreeRDP-1.0.2/include/000077500000000000000000000000001207112532300143605ustar00rootroot00000000000000FreeRDP-1.0.2/include/CMakeLists.txt000066400000000000000000000031011207112532300171130ustar00rootroot00000000000000# FreeRDP: A Remote Desktop Protocol Client # include headers cmake build script # # Copyright 2011 O.S. Systems Software Ltda. # Copyright 2011 Otavio Salvador # Copyright 2011 Marc-Andre Moreau # # 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. file(GLOB HEADERS "freerdp/*.h") install_files(/include/freerdp FILES ${HEADERS}) install(DIRECTORY freerdp/utils DESTINATION include/freerdp FILES_MATCHING PATTERN "*.h") install(DIRECTORY freerdp/channels DESTINATION include/freerdp FILES_MATCHING PATTERN "*.h") install(DIRECTORY freerdp/cache DESTINATION include/freerdp FILES_MATCHING PATTERN "*.h") install(DIRECTORY freerdp/gdi DESTINATION include/freerdp FILES_MATCHING PATTERN "*.h") install(DIRECTORY freerdp/kbd DESTINATION include/freerdp FILES_MATCHING PATTERN "*.h") install(DIRECTORY freerdp/rail DESTINATION include/freerdp FILES_MATCHING PATTERN "*.h") install(DIRECTORY freerdp/codec DESTINATION include/freerdp FILES_MATCHING PATTERN "*.h") install(DIRECTORY freerdp/plugins DESTINATION include/freerdp FILES_MATCHING PATTERN "*.h") FreeRDP-1.0.2/include/freerdp/000077500000000000000000000000001207112532300160075ustar00rootroot00000000000000FreeRDP-1.0.2/include/freerdp/altsec.h000066400000000000000000000145531207112532300174430ustar00rootroot00000000000000/** * FreeRDP: A Remote Desktop Protocol Client * Alternate Secondary Drawing Orders Interface API * * Copyright 2011 Marc-Andre Moreau * * 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. */ #ifndef __UPDATE_ALTSEC_H #define __UPDATE_ALTSEC_H #include #define DSDNG_STRETCH 0x00000001 #define DSDNG_TILE 0x00000002 #define DSDNG_PERPIXELALPHA 0x00000004 #define DSDNG_TRANSPARENT 0x00000008 #define DSDNG_MUSTFLIP 0x00000010 #define DSDNG_TRUESIZE 0x00000020 #define FRAME_START 0x00000000 #define FRAME_END 0x00000001 #define STREAM_BITMAP_END 0x01 #define STREAM_BITMAP_COMPRESSED 0x02 #define STREAM_BITMAP_V2 0x04 struct _OFFSCREEN_DELETE_LIST { uint32 sIndices; uint32 cIndices; uint16* indices; }; typedef struct _OFFSCREEN_DELETE_LIST OFFSCREEN_DELETE_LIST; struct _CREATE_OFFSCREEN_BITMAP_ORDER { uint32 id; uint32 cx; uint32 cy; OFFSCREEN_DELETE_LIST deleteList; }; typedef struct _CREATE_OFFSCREEN_BITMAP_ORDER CREATE_OFFSCREEN_BITMAP_ORDER; struct _SWITCH_SURFACE_ORDER { uint32 bitmapId; }; typedef struct _SWITCH_SURFACE_ORDER SWITCH_SURFACE_ORDER; struct _NINE_GRID_BITMAP_INFO { uint32 flFlags; uint32 ulLeftWidth; uint32 ulRightWidth; uint32 ulTopHeight; uint32 ulBottomHeight; uint32 crTransparent; }; typedef struct _NINE_GRID_BITMAP_INFO NINE_GRID_BITMAP_INFO; struct _CREATE_NINE_GRID_BITMAP_ORDER { uint32 bitmapBpp; uint32 bitmapId; uint32 cx; uint32 cy; NINE_GRID_BITMAP_INFO nineGridInfo; }; typedef struct _CREATE_NINE_GRID_BITMAP_ORDER CREATE_NINE_GRID_BITMAP_ORDER; struct _FRAME_MARKER_ORDER { uint32 action; }; typedef struct _FRAME_MARKER_ORDER FRAME_MARKER_ORDER; struct _STREAM_BITMAP_FIRST_ORDER { uint32 bitmapFlags; uint32 bitmapBpp; uint32 bitmapType; uint32 bitmapWidth; uint32 bitmapHeight; uint32 bitmapSize; uint32 bitmapBlockSize; uint8* bitmapBlock; }; typedef struct _STREAM_BITMAP_FIRST_ORDER STREAM_BITMAP_FIRST_ORDER; struct _STREAM_BITMAP_NEXT_ORDER { uint32 bitmapFlags; uint32 bitmapType; uint32 bitmapBlockSize; uint8* bitmapBlock; }; typedef struct _STREAM_BITMAP_NEXT_ORDER STREAM_BITMAP_NEXT_ORDER; struct _DRAW_GDIPLUS_FIRST_ORDER { uint32 cbSize; uint32 cbTotalSize; uint32 cbTotalEmfSize; uint8* emfRecords; }; typedef struct _DRAW_GDIPLUS_FIRST_ORDER DRAW_GDIPLUS_FIRST_ORDER; struct _DRAW_GDIPLUS_NEXT_ORDER { uint32 cbSize; uint8* emfRecords; }; typedef struct _DRAW_GDIPLUS_NEXT_ORDER DRAW_GDIPLUS_NEXT_ORDER; struct _DRAW_GDIPLUS_END_ORDER { uint32 cbSize; uint32 cbTotalSize; uint32 cbTotalEmfSize; uint8* emfRecords; }; typedef struct _DRAW_GDIPLUS_END_ORDER DRAW_GDIPLUS_END_ORDER; struct _DRAW_GDIPLUS_CACHE_FIRST_ORDER { uint32 flags; uint32 cacheType; uint32 cacheIndex; uint32 cbSize; uint32 cbTotalSize; uint8* emfRecords; }; typedef struct _DRAW_GDIPLUS_CACHE_FIRST_ORDER DRAW_GDIPLUS_CACHE_FIRST_ORDER; struct _DRAW_GDIPLUS_CACHE_NEXT_ORDER { uint32 flags; uint32 cacheType; uint32 cacheIndex; uint32 cbSize; uint8* emfRecords; }; typedef struct _DRAW_GDIPLUS_CACHE_NEXT_ORDER DRAW_GDIPLUS_CACHE_NEXT_ORDER; struct _DRAW_GDIPLUS_CACHE_END_ORDER { uint32 flags; uint32 cacheType; uint32 cacheIndex; uint32 cbSize; uint32 cbTotalSize; uint8* emfRecords; }; typedef struct _DRAW_GDIPLUS_CACHE_END_ORDER DRAW_GDIPLUS_CACHE_END_ORDER; typedef void (*pCreateOffscreenBitmap)(rdpContext* context, CREATE_OFFSCREEN_BITMAP_ORDER* create_offscreen_bitmap); typedef void (*pSwitchSurface)(rdpContext* context, SWITCH_SURFACE_ORDER* switch_surface); typedef void (*pCreateNineGridBitmap)(rdpContext* context, CREATE_NINE_GRID_BITMAP_ORDER* create_nine_grid_bitmap); typedef void (*pFrameMarker)(rdpContext* context, FRAME_MARKER_ORDER* frame_marker); typedef void (*pStreamBitmapFirst)(rdpContext* context, STREAM_BITMAP_FIRST_ORDER* stream_bitmap_first); typedef void (*pStreamBitmapNext)(rdpContext* context, STREAM_BITMAP_FIRST_ORDER* stream_bitmap_next); typedef void (*pDrawGdiPlusFirst)(rdpContext* context, DRAW_GDIPLUS_FIRST_ORDER* draw_gdiplus_first); typedef void (*pDrawGdiPlusNext)(rdpContext* context, DRAW_GDIPLUS_NEXT_ORDER* draw_gdiplus_next); typedef void (*pDrawGdiPlusEnd)(rdpContext* context, DRAW_GDIPLUS_END_ORDER* draw_gdiplus_end); typedef void (*pDrawGdiPlusCacheFirst)(rdpContext* context, DRAW_GDIPLUS_CACHE_FIRST_ORDER* draw_gdiplus_cache_first); typedef void (*pDrawGdiPlusCacheNext)(rdpContext* context, DRAW_GDIPLUS_CACHE_NEXT_ORDER* draw_gdiplus_cache_next); typedef void (*pDrawGdiPlusCacheEnd)(rdpContext* context, DRAW_GDIPLUS_CACHE_END_ORDER* draw_gdiplus_cache_end); struct rdp_altsec_update { rdpContext* context; /* 0 */ uint32 paddingA[16 - 1]; /* 1 */ pCreateOffscreenBitmap CreateOffscreenBitmap; /* 16 */ pSwitchSurface SwitchSurface; /* 17 */ pCreateNineGridBitmap CreateNineGridBitmap; /* 18 */ pFrameMarker FrameMarker; /* 19 */ pStreamBitmapFirst StreamBitmapFirst; /* 20 */ pStreamBitmapNext StreamBitmapNext; /* 21 */ pDrawGdiPlusFirst DrawGdiPlusFirst; /* 22 */ pDrawGdiPlusNext DrawGdiPlusNext; /* 23 */ pDrawGdiPlusEnd DrawGdiPlusEnd; /* 24 */ pDrawGdiPlusCacheFirst DrawGdiPlusCacheFirst; /* 25 */ pDrawGdiPlusCacheNext DrawGdiPlusCacheNext; /* 26 */ pDrawGdiPlusCacheEnd DrawGdiPlusCacheEnd; /* 27 */ uint32 paddingB[32 - 28]; /* 28 */ /* internal */ CREATE_OFFSCREEN_BITMAP_ORDER create_offscreen_bitmap; SWITCH_SURFACE_ORDER switch_surface; CREATE_NINE_GRID_BITMAP_ORDER create_nine_grid_bitmap; FRAME_MARKER_ORDER frame_marker; STREAM_BITMAP_FIRST_ORDER stream_bitmap_first; STREAM_BITMAP_FIRST_ORDER stream_bitmap_next; DRAW_GDIPLUS_CACHE_FIRST_ORDER draw_gdiplus_cache_first; DRAW_GDIPLUS_CACHE_NEXT_ORDER draw_gdiplus_cache_next; DRAW_GDIPLUS_CACHE_END_ORDER draw_gdiplus_cache_end; DRAW_GDIPLUS_FIRST_ORDER draw_gdiplus_first; DRAW_GDIPLUS_NEXT_ORDER draw_gdiplus_next; DRAW_GDIPLUS_END_ORDER draw_gdiplus_end; }; typedef struct rdp_altsec_update rdpAltSecUpdate; #endif /* __UPDATE_ALTSEC_H */ FreeRDP-1.0.2/include/freerdp/api.h000066400000000000000000000031001207112532300167230ustar00rootroot00000000000000/** * FreeRDP: A Remote Desktop Protocol Client * FreeRDP Interface * * Copyright 2009-2011 Jay Sorg * * 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. */ #ifndef __FREERDP_API_H #define __FREERDP_API_H #define FREERDP_INTERFACE_VERSION 4 #if defined _WIN32 || defined __CYGWIN__ #ifdef FREERDP_EXPORTS #ifdef __GNUC__ #define FREERDP_API __attribute__((dllexport)) #else #define FREERDP_API __declspec(dllexport) #endif #else #ifdef __GNUC__ #define FREERDP_API __attribute__((dllimport)) #else #define FREERDP_API __declspec(dllimport) #endif #endif #else #if __GNUC__ >= 4 #define FREERDP_API __attribute__ ((visibility("default"))) #else #define FREERDP_API #endif #endif #ifdef _WIN32 #define FREERDP_CC __cdecl #else #define FREERDP_CC #endif #ifdef _WIN32 #define INLINE __inline #else #define INLINE inline #endif #define IFCALL(_cb, ...) do { if (_cb != NULL) { _cb( __VA_ARGS__ ); } } while (0) #define IFCALLRET(_cb, _ret, ...) do { if (_cb != NULL) { _ret = _cb( __VA_ARGS__ ); } } while (0) #endif FreeRDP-1.0.2/include/freerdp/cache/000077500000000000000000000000001207112532300170525ustar00rootroot00000000000000FreeRDP-1.0.2/include/freerdp/cache/bitmap.h000066400000000000000000000037311207112532300205030ustar00rootroot00000000000000/** * FreeRDP: A Remote Desktop Protocol Client * Bitmap Cache V2 * * Copyright 2011 Marc-Andre Moreau * * 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. */ #ifndef __BITMAP_V2_CACHE_H #define __BITMAP_V2_CACHE_H #include #include #include #include #include typedef struct _BITMAP_V2_CELL BITMAP_V2_CELL; typedef struct rdp_bitmap_cache rdpBitmapCache; #include struct _BITMAP_V2_CELL { uint32 number; rdpBitmap** entries; }; struct rdp_bitmap_cache { pMemBlt MemBlt; /* 0 */ pMem3Blt Mem3Blt; /* 1 */ pCacheBitmap CacheBitmap; /* 2 */ pCacheBitmapV2 CacheBitmapV2; /* 3 */ pCacheBitmapV3 CacheBitmapV3; /* 4 */ pBitmapUpdate BitmapUpdate; /* 5 */ uint32 paddingA[16 - 6]; /* 6 */ uint32 maxCells; /* 16 */ BITMAP_V2_CELL* cells; /* 17 */ uint32 paddingB[32 - 18]; /* 18 */ /* internal */ rdpBitmap* bitmap; rdpUpdate* update; rdpContext* context; rdpSettings* settings; }; FREERDP_API rdpBitmap* bitmap_cache_get(rdpBitmapCache* bitmap_cache, uint32 id, uint32 index); FREERDP_API void bitmap_cache_put(rdpBitmapCache* bitmap_cache, uint32 id, uint32 index, rdpBitmap* bitmap); FREERDP_API void bitmap_cache_register_callbacks(rdpUpdate* update); FREERDP_API rdpBitmapCache* bitmap_cache_new(rdpSettings* settings); FREERDP_API void bitmap_cache_free(rdpBitmapCache* bitmap_cache); #endif /* __BITMAP_V2_CACHE_H */ FreeRDP-1.0.2/include/freerdp/cache/brush.h000066400000000000000000000034041207112532300203470ustar00rootroot00000000000000/** * FreeRDP: A Remote Desktop Protocol Client * Brush Cache * * Copyright 2011 Marc-Andre Moreau * * 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. */ #ifndef __BRUSH_CACHE_H #define __BRUSH_CACHE_H #include #include #include #include #include typedef struct _BRUSH_ENTRY BRUSH_ENTRY; typedef struct rdp_brush_cache rdpBrushCache; #include struct _BRUSH_ENTRY { uint32 bpp; void* entry; }; struct rdp_brush_cache { pPatBlt PatBlt; /* 0 */ pCacheBrush CacheBrush; /* 1 */ uint32 paddingA[16 - 2]; /* 2 */ uint32 maxEntries; /* 16 */ uint32 maxMonoEntries; /* 17 */ BRUSH_ENTRY* entries; /* 18 */ BRUSH_ENTRY* monoEntries; /* 19 */ uint32 paddingB[32 - 20]; /* 20 */ /* internal */ rdpSettings* settings; }; FREERDP_API void* brush_cache_get(rdpBrushCache* brush, uint32 index, uint32* bpp); FREERDP_API void brush_cache_put(rdpBrushCache* brush, uint32 index, void* entry, uint32 bpp); FREERDP_API void brush_cache_register_callbacks(rdpUpdate* update); FREERDP_API rdpBrushCache* brush_cache_new(rdpSettings* settings); FREERDP_API void brush_cache_free(rdpBrushCache* brush); #endif /* __BRUSH_CACHE_H */ FreeRDP-1.0.2/include/freerdp/cache/cache.h000066400000000000000000000026511207112532300202720ustar00rootroot00000000000000/** * FreeRDP: A Remote Desktop Protocol Client * RDP Caches * * Copyright 2011 Marc-Andre Moreau * * 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. */ #ifndef __CACHE_H #define __CACHE_H #include #include #include #include #include #include #include #include #include #include struct rdp_cache { rdpGlyphCache* glyph; /* 0 */ rdpBrushCache* brush; /* 1 */ rdpPointerCache* pointer; /* 2 */ rdpBitmapCache* bitmap; /* 3 */ rdpOffscreenCache* offscreen; /* 4 */ rdpPaletteCache* palette; /* 5 */ /* internal */ rdpSettings* settings; }; FREERDP_API rdpCache* cache_new(rdpSettings* settings); FREERDP_API void cache_free(rdpCache* cache); #endif /* __CACHE_H */ FreeRDP-1.0.2/include/freerdp/cache/glyph.h000066400000000000000000000040041207112532300203440ustar00rootroot00000000000000/** * FreeRDP: A Remote Desktop Protocol Client * Glyph Cache * * Copyright 2011 Marc-Andre Moreau * * 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. */ #ifndef __GLYPH_CACHE_H #define __GLYPH_CACHE_H #include #include #include #include typedef struct _GLYPH_CACHE GLYPH_CACHE; typedef struct _FRAGMENT_CACHE_ENTRY FRAGMENT_CACHE_ENTRY; typedef struct _FRAGMENT_CACHE FRAGMENT_CACHE; typedef struct rdp_glyph_cache rdpGlyphCache; #include struct _GLYPH_CACHE { uint32 number; uint32 maxCellSize; rdpGlyph** entries; }; struct _FRAGMENT_CACHE_ENTRY { void* fragment; uint32 size; }; struct _FRAGMENT_CACHE { FRAGMENT_CACHE_ENTRY* entries; }; struct rdp_glyph_cache { FRAGMENT_CACHE fragCache; GLYPH_CACHE glyphCache[10]; rdpContext* context; rdpSettings* settings; }; FREERDP_API rdpGlyph* glyph_cache_get(rdpGlyphCache* glyph_cache, uint32 id, uint32 index); FREERDP_API void glyph_cache_put(rdpGlyphCache* glyph_cache, uint32 id, uint32 index, rdpGlyph* entry); FREERDP_API void* glyph_cache_fragment_get(rdpGlyphCache* glyph, uint32 index, uint32* count); FREERDP_API void glyph_cache_fragment_put(rdpGlyphCache* glyph, uint32 index, uint32 count, void* entry); FREERDP_API void glyph_cache_register_callbacks(rdpUpdate* update); FREERDP_API rdpGlyphCache* glyph_cache_new(rdpSettings* settings); FREERDP_API void glyph_cache_free(rdpGlyphCache* glyph); #endif /* __GLYPH_CACHE_H */ FreeRDP-1.0.2/include/freerdp/cache/offscreen.h000066400000000000000000000033201207112532300211730ustar00rootroot00000000000000/** * FreeRDP: A Remote Desktop Protocol Client * Offscreen Bitmap Cache * * Copyright 2011 Marc-Andre Moreau * * 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. */ #ifndef __OFFSCREEN_CACHE_H #define __OFFSCREEN_CACHE_H #include #include #include #include #include typedef struct rdp_offscreen_cache rdpOffscreenCache; #include struct rdp_offscreen_cache { uint32 maxSize; /* 0 */ uint32 maxEntries; /* 1 */ rdpBitmap** entries; /* 2 */ uint32 currentSurface; /* 3 */ /* internal */ rdpUpdate* update; rdpSettings* settings; }; FREERDP_API rdpBitmap* offscreen_cache_get(rdpOffscreenCache* offscreen_cache, uint32 index); FREERDP_API void offscreen_cache_put(rdpOffscreenCache* offscreen_cache, uint32 index, rdpBitmap* bitmap); FREERDP_API void offscreen_cache_delete(rdpOffscreenCache* offscreen, uint32 index); FREERDP_API void offscreen_cache_register_callbacks(rdpUpdate* update); FREERDP_API rdpOffscreenCache* offscreen_cache_new(rdpSettings* settings); FREERDP_API void offscreen_cache_free(rdpOffscreenCache* offscreen); #endif /* __OFFSCREEN_CACHE_H */ FreeRDP-1.0.2/include/freerdp/cache/palette.h000066400000000000000000000031601207112532300206610ustar00rootroot00000000000000/** * FreeRDP: A Remote Desktop Protocol Client * Palette (Color Table) Cache * * Copyright 2011 Marc-Andre Moreau * * 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. */ #ifndef __PALETTE_CACHE_H #define __PALETTE_CACHE_H #include #include #include #include #include typedef struct _PALETTE_TABLE_ENTRY PALETTE_TABLE_ENTRY; typedef struct rdp_palette_cache rdpPaletteCache; #include struct _PALETTE_TABLE_ENTRY { void* entry; }; struct rdp_palette_cache { uint32 maxEntries; /* 0 */ PALETTE_TABLE_ENTRY* entries; /* 1 */ /* internal */ rdpSettings* settings; }; FREERDP_API void* palette_cache_get(rdpPaletteCache* palette, uint32 index); FREERDP_API void palette_cache_put(rdpPaletteCache* palette, uint32 index, void* entry); FREERDP_API void palette_cache_register_callbacks(rdpUpdate* update); FREERDP_API rdpPaletteCache* palette_cache_new(rdpSettings* settings); FREERDP_API void palette_cache_free(rdpPaletteCache* palette_cache); #endif /* __PALETTE_CACHE_H */ FreeRDP-1.0.2/include/freerdp/cache/pointer.h000066400000000000000000000030741207112532300207070ustar00rootroot00000000000000/** * FreeRDP: A Remote Desktop Protocol Client * Pointer Cache * * Copyright 2011 Marc-Andre Moreau * * 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. */ #ifndef __POINTER_CACHE_H #define __POINTER_CACHE_H #include #include #include #include #include #include typedef struct rdp_pointer_cache rdpPointerCache; #include struct rdp_pointer_cache { uint32 cacheSize; /* 0 */ rdpPointer** entries; /* 1 */ /* internal */ rdpUpdate* update; rdpSettings* settings; }; FREERDP_API rdpPointer* pointer_cache_get(rdpPointerCache* pointer_cache, uint32 index); FREERDP_API void pointer_cache_put(rdpPointerCache* pointer_cache, uint32 index, rdpPointer* pointer); FREERDP_API void pointer_cache_register_callbacks(rdpUpdate* update); FREERDP_API rdpPointerCache* pointer_cache_new(rdpSettings* settings); FREERDP_API void pointer_cache_free(rdpPointerCache* pointer_cache); #endif /* __POINTER_CACHE_H */ FreeRDP-1.0.2/include/freerdp/channels/000077500000000000000000000000001207112532300176025ustar00rootroot00000000000000FreeRDP-1.0.2/include/freerdp/channels/channels.h000066400000000000000000000040561207112532300215530ustar00rootroot00000000000000/** * FreeRDP: A Remote Desktop Protocol client. * Virtual Channel Manager * * Copyright 2009-2011 Jay Sorg * Copyright 2010-2011 Vic Lee * * 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. */ #ifndef __FREERDP_CHANNELS_H #define __FREERDP_CHANNELS_H #include #include #include #ifdef __cplusplus extern "C" { #endif FREERDP_API int freerdp_channels_global_init(void); FREERDP_API int freerdp_channels_global_uninit(void); FREERDP_API rdpChannels* freerdp_channels_new(void); FREERDP_API void freerdp_channels_free(rdpChannels* channels); FREERDP_API int freerdp_channels_load_plugin(rdpChannels* channels, rdpSettings* settings, const char* name, void* data); FREERDP_API int freerdp_channels_pre_connect(rdpChannels* channels, freerdp* instance); FREERDP_API int freerdp_channels_post_connect(rdpChannels* channels, freerdp* instance); FREERDP_API int freerdp_channels_data(freerdp* instance, int channel_id, void* data, int data_size, int flags, int total_size); FREERDP_API int freerdp_channels_send_event(rdpChannels* channels, RDP_EVENT* event); FREERDP_API boolean freerdp_channels_get_fds(rdpChannels* channels, freerdp* instance, void** read_fds, int* read_count, void** write_fds, int* write_count); FREERDP_API boolean freerdp_channels_check_fds(rdpChannels* channels, freerdp* instance); FREERDP_API RDP_EVENT* freerdp_channels_pop_event(rdpChannels* channels); FREERDP_API void freerdp_channels_close(rdpChannels* channels, freerdp* instance); #ifdef __cplusplus } #endif #endif /* __FREERDP_CHANNELS_H */ FreeRDP-1.0.2/include/freerdp/channels/wtsvc.h000066400000000000000000000103131207112532300211170ustar00rootroot00000000000000/** * FreeRDP: A Remote Desktop Protocol client. * Server Virtual Channel Interface * * Copyright 2011-2012 Vic Lee * * 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. */ /** * The server-side virtual channel API follows the Microsoft Remote Desktop * Services API functions WTSVirtualChannel* defined in: * http://msdn.microsoft.com/en-us/library/windows/desktop/aa383464.aspx * * Difference between the MS API are documented in this header. All functions * are implemented in and integrated with libfreerdp-channels. * * Unlike MS API, all functions except WTSVirtualChannelOpenEx in this * implementation are thread-safe. */ #ifndef __FREERDP_WTSVC_H #define __FREERDP_WTSVC_H #include #include typedef struct WTSVirtualChannelManager WTSVirtualChannelManager; #define WTS_CHANNEL_OPTION_DYNAMIC 0x00000001 typedef enum _WTS_VIRTUAL_CLASS { WTSVirtualClientData, WTSVirtualFileHandle } WTS_VIRTUAL_CLASS; /** * WTSVirtualChannelManager functions are FreeRDP extensions to the API. */ FREERDP_API WTSVirtualChannelManager* WTSCreateVirtualChannelManager(freerdp_peer* client); FREERDP_API void WTSDestroyVirtualChannelManager(WTSVirtualChannelManager* vcm); FREERDP_API void WTSVirtualChannelManagerGetFileDescriptor(WTSVirtualChannelManager* vcm, void** fds, int* fds_count); FREERDP_API boolean WTSVirtualChannelManagerCheckFileDescriptor(WTSVirtualChannelManager* vcm); /** * Opens a static or dynamic virtual channel and return the handle. If the * operation fails, a NULL handle is returned. * * The original MS API has 'DWORD SessionId' as the first argument, while we * use our WTSVirtualChannelManager object instead. * * This functions should be called only from the main thread. */ FREERDP_API void* WTSVirtualChannelOpenEx( /* __in */ WTSVirtualChannelManager* vcm, /* __in */ const char* pVirtualName, /* __in */ uint32 flags); /** * Returns information about a specified virtual channel. * * Servers use this function to gain access to a virtual channel file handle * that can be used for asynchronous I/O. */ FREERDP_API boolean WTSVirtualChannelQuery( /* __in */ void* hChannelHandle, /* __in */ WTS_VIRTUAL_CLASS WtsVirtualClass, /* __out */ void** ppBuffer, /* __out */ uint32* pBytesReturned); /** * Frees memory allocated by WTSVirtualChannelQuery */ FREERDP_API void WTSFreeMemory( /* __in */ void* pMemory); /** * Reads data from the server end of a virtual channel. * * FreeRDP behavior: * * This function will always return a complete channel data packet, i.e. chunks * are already assembled. If BufferSize argument is smaller than the packet * size, it will set the desired size in pBytesRead and return false. The * caller should allocate a large enough buffer and call this function again. * Returning false with pBytesRead set to zero indicates an error has occurred. * If no pending packet to be read, it will set pBytesRead to zero and return * true. * * TimeOut is not supported, and this function will always return immediately. * The caller should use the file handle returned by WTSVirtualChannelQuery to * determine whether a packet has arrived. */ FREERDP_API boolean WTSVirtualChannelRead( /* __in */ void* hChannelHandle, /* __in */ uint32 TimeOut, /* __out */ uint8* Buffer, /* __in */ uint32 BufferSize, /* __out */ uint32* pBytesRead); /** * Writes data to the server end of a virtual channel. */ FREERDP_API boolean WTSVirtualChannelWrite( /* __in */ void* hChannelHandle, /* __in */ uint8* Buffer, /* __in */ uint32 Length, /* __out */ uint32* pBytesWritten); /** * Closes an open virtual channel handle. */ FREERDP_API boolean WTSVirtualChannelClose( /* __in */ void* hChannelHandle); #endif /* __FREERDP_WTSVC_H */ FreeRDP-1.0.2/include/freerdp/codec/000077500000000000000000000000001207112532300170645ustar00rootroot00000000000000FreeRDP-1.0.2/include/freerdp/codec/bitmap.h000066400000000000000000000016101207112532300205070ustar00rootroot00000000000000/** * FreeRDP: A Remote Desktop Protocol Client * Compressed Bitmap * * Copyright 2011 Jay Sorg * * 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. */ #ifndef __BITMAP_H #define __BITMAP_H #include FREERDP_API boolean bitmap_decompress(uint8* srcData, uint8* dstData, int width, int height, int size, int srcBpp, int dstBpp); #endif /* __BITMAP_H */ FreeRDP-1.0.2/include/freerdp/codec/color.h000066400000000000000000000166641207112532300203700ustar00rootroot00000000000000/** * FreeRDP: A Remote Desktop Protocol Client * Color Conversion Routines * * Copyright 2010 Marc-Andre Moreau * * 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. */ #ifndef __COLOR_H #define __COLOR_H #include #include #ifdef __cplusplus extern "C" { #endif /* Color Space Conversions: http://msdn.microsoft.com/en-us/library/ff566496/ */ /* Color Space Conversion */ #define RGB_555_565(_r, _g, _b) \ _r = _r; \ _g = (_g << 1 & ~0x1) | (_g >> 4); \ _b = _b; #define RGB_565_555(_r, _g, _b) \ _r = _r; \ _g = (_g >> 1); \ _b = _b; #define RGB_555_888(_r, _g, _b) \ _r = (_r << 3 & ~0x7) | (_r >> 2); \ _g = (_g << 3 & ~0x7) | (_g >> 2); \ _b = (_b << 3 & ~0x7) | (_b >> 2); #define RGB_565_888(_r, _g, _b) \ _r = (_r << 3 & ~0x7) | (_r >> 2); \ _g = (_g << 2 & ~0x3) | (_g >> 4); \ _b = (_b << 3 & ~0x7) | (_b >> 2); #define RGB_888_565(_r, _g, _b) \ _r = (_r >> 3); \ _g = (_g >> 2); \ _b = (_b >> 3); #define RGB_888_555(_r, _g, _b) \ _r = (_r >> 3); \ _g = (_g >> 3); \ _b = (_b >> 3); /* RGB 15 (RGB_555) */ #define RGB555(_r, _g, _b) \ ((_r & 0x1F) << 10) | ((_g & 0x1F) << 5) | (_b & 0x1F) #define RGB15(_r, _g, _b) \ (((_r >> 3) & 0x1F) << 10) | (((_g >> 3) & 0x1F) << 5) | ((_b >> 3) & 0x1F) #define GetRGB_555(_r, _g, _b, _p) \ _r = (_p & 0x7C00) >> 10; \ _g = (_p & 0x3E0) >> 5; \ _b = (_p & 0x1F); #define GetRGB15(_r, _g, _b, _p) \ GetRGB_555(_r, _g, _b, _p); \ RGB_555_888(_r, _g, _b); /* BGR 15 (BGR_555) */ #define BGR555(_r, _g, _b) \ ((_b & 0x1F) << 10) | ((_g & 0x1F) << 5) | (_r & 0x1F) #define BGR15(_r, _g, _b) \ (((_b >> 3) & 0x1F) << 10) | (((_g >> 3) & 0x1F) << 5) | ((_r >> 3) & 0x1F) #define GetBGR_555(_r, _g, _b, _p) \ _b = (_p & 0x7C00) >> 10; \ _g = (_p & 0x3E0) >> 5; \ _r = (_p & 0x1F); #define GetBGR15(_r, _g, _b, _p) \ GetBGR_555(_r, _g, _b, _p); \ RGB_555_888(_r, _g, _b); /* RGB 16 (RGB_565) */ #define RGB565(_r, _g, _b) \ ((_r & 0x1F) << 11) | ((_g & 0x3F) << 5) | (_b & 0x1F) #define RGB16(_r, _g, _b) \ (((_r >> 3) & 0x1F) << 11) | (((_g >> 2) & 0x3F) << 5) | ((_b >> 3) & 0x1F) #define GetRGB_565(_r, _g, _b, _p) \ _r = (_p & 0xF800) >> 11; \ _g = (_p & 0x7E0) >> 5; \ _b = (_p & 0x1F); #define GetRGB16(_r, _g, _b, _p) \ GetRGB_565(_r, _g, _b, _p); \ RGB_565_888(_r, _g, _b); /* BGR 16 (BGR_565) */ #define BGR565(_r, _g, _b) \ ((_b & 0x1F) << 11) | ((_g & 0x3F) << 5) | (_r & 0x1F) #define BGR16(_r, _g, _b) \ (((_b >> 3) & 0x1F) << 11) | (((_g >> 2) & 0x3F) << 5) | ((_r >> 3) & 0x1F) #define GetBGR_565(_r, _g, _b, _p) \ _b = (_p & 0xF800) >> 11; \ _g = (_p & 0x7E0) >> 5; \ _r = (_p & 0x1F); #define GetBGR16(_r, _g, _b, _p) \ GetBGR_565(_r, _g, _b, _p); \ RGB_565_888(_r, _g, _b); /* RGB 24 (RGB_888) */ #define RGB24(_r, _g, _b) \ (_r << 16) | (_g << 8) | _b #define GetRGB24(_r, _g, _b, _p) \ _r = (_p & 0xFF0000) >> 16; \ _g = (_p & 0xFF00) >> 8; \ _b = (_p & 0xFF); /* BGR 24 (BGR_888) */ #define BGR24(_r, _g, _b) \ (_b << 16) | (_g << 8) | _r #define GetBGR24(_r, _g, _b, _p) \ _b = (_p & 0xFF0000) >> 16; \ _g = (_p & 0xFF00) >> 8; \ _r = (_p & 0xFF); /* RGB 32 (ARGB_8888), alpha ignored */ #define RGB32(_r, _g, _b) \ (_r << 16) | (_g << 8) | _b #define GetRGB32(_r, _g, _b, _p) \ _r = (_p & 0xFF0000) >> 16; \ _g = (_p & 0xFF00) >> 8; \ _b = (_p & 0xFF); /* ARGB 32 (ARGB_8888) */ #define ARGB32(_a,_r, _g, _b) \ (_a << 24) | (_r << 16) | (_g << 8) | _b #define GetARGB32(_a, _r, _g, _b, _p) \ _a = (_p & 0xFF000000) >> 24; \ _r = (_p & 0xFF0000) >> 16; \ _g = (_p & 0xFF00) >> 8; \ _b = (_p & 0xFF); /* BGR 32 (ABGR_8888), alpha ignored */ #define BGR32(_r, _g, _b) \ (_b << 16) | (_g << 8) | _r #define GetBGR32(_r, _g, _b, _p) \ _b = (_p & 0xFF0000) >> 16; \ _g = (_p & 0xFF00) >> 8; \ _r = (_p & 0xFF); /* BGR 32 (ABGR_8888) */ #define ABGR32(_a, _r, _g, _b) \ (_a << 24) | (_b << 16) | (_g << 8) | _r #define GetABGR32(_a, _r, _g, _b, _p) \ _a = (_p & 0xFF000000) >> 24; \ _b = (_p & 0xFF0000) >> 16; \ _g = (_p & 0xFF00) >> 8; \ _r = (_p & 0xFF); /* Color Conversion */ #define BGR16_RGB32(_r, _g, _b, _p) \ GetBGR16(_r, _g, _b, _p); \ RGB_565_888(_r, _g, _b); \ _p = RGB32(_r, _g, _b); #define RGB32_RGB16(_r, _g, _b, _p) \ GetRGB32(_r, _g, _b, _p); \ RGB_888_565(_r, _g, _b); \ _p = RGB565(_r, _g, _b); #define RGB15_RGB16(_r, _g, _b, _p) \ GetRGB_555(_r, _g, _b, _p); \ _g = (_g << 1 & ~0x1) | (_g >> 4); \ _p = RGB565(_r, _g, _b); #define RGB16_RGB15(_r, _g, _b, _p) \ GetRGB_565(_r, _g, _b, _p); \ _g = (_g >> 1); \ _p = RGB555(_r, _g, _b); #define CLRCONV_ALPHA 1 #define CLRCONV_INVERT 2 /* if defined RGB555 format is used when rendering with a 16-bit frame buffer */ #define CLRCONV_RGB555 4 /* Supported Internal Buffer Formats */ #define CLRBUF_16BPP 8 #define CLRBUF_24BPP 16 #define CLRBUF_32BPP 32 struct _CLRCONV { int alpha; int invert; int rgb555; rdpPalette* palette; }; typedef struct _CLRCONV CLRCONV; typedef CLRCONV* HCLRCONV; #define IBPP(_bpp) (((_bpp + 1)/ 8) % 5) typedef uint8* (*p_freerdp_image_convert)(uint8* srcData, uint8* dstData, int width, int height, int srcBpp, int dstBpp, HCLRCONV clrconv); FREERDP_API uint8* freerdp_image_convert(uint8* srcData, uint8 *dstData, int width, int height, int srcBpp, int dstBpp, HCLRCONV clrconv); FREERDP_API uint8* freerdp_glyph_convert(int width, int height, uint8* data); FREERDP_API void freerdp_bitmap_flip(uint8 * src, uint8 * dst, int scanLineSz, int height); FREERDP_API uint8* freerdp_image_flip(uint8* srcData, uint8* dstData, int width, int height, int bpp); FREERDP_API uint8* freerdp_icon_convert(uint8* srcData, uint8* dstData, uint8* mask, int width, int height, int bpp, HCLRCONV clrconv); FREERDP_API uint8* freerdp_mono_image_convert(uint8* srcData, int width, int height, int srcBpp, int dstBpp, uint32 bgcolor, uint32 fgcolor, HCLRCONV clrconv); FREERDP_API void freerdp_alpha_cursor_convert(uint8* alphaData, uint8* xorMask, uint8* andMask, int width, int height, int bpp, HCLRCONV clrconv); FREERDP_API void freerdp_image_swap_color_order(uint8* data, int width, int height); FREERDP_API uint32 freerdp_color_convert_var(uint32 srcColor, int srcBpp, int dstBpp, HCLRCONV clrconv); FREERDP_API uint32 freerdp_color_convert_rgb(uint32 srcColor, int srcBpp, int dstBpp, HCLRCONV clrconv); FREERDP_API uint32 freerdp_color_convert_bgr(uint32 srcColor, int srcBpp, int dstBpp, HCLRCONV clrconv); FREERDP_API uint32 freerdp_color_convert_rgb_bgr(uint32 srcColor, int srcBpp, int dstBpp, HCLRCONV clrconv); FREERDP_API uint32 freerdp_color_convert_bgr_rgb(uint32 srcColor, int srcBpp, int dstBpp, HCLRCONV clrconv); FREERDP_API uint32 freerdp_color_convert_var_rgb(uint32 srcColor, int srcBpp, int dstBpp, HCLRCONV clrconv); FREERDP_API uint32 freerdp_color_convert_var_bgr(uint32 srcColor, int srcBpp, int dstBpp, HCLRCONV clrconv); FREERDP_API HCLRCONV freerdp_clrconv_new(uint32 flags); FREERDP_API void freerdp_clrconv_free(HCLRCONV clrconv); #ifdef __cplusplus } #endif #endif /* __COLOR_H */ FreeRDP-1.0.2/include/freerdp/codec/nsc.h000066400000000000000000000045471207112532300200320ustar00rootroot00000000000000/** * FreeRDP: A Remote Desktop Protocol client. * NSCodec Codec * * Copyright 2011 Samsung, Author Jiten Pathy * * 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. */ #ifndef __NSC_H #define __NSC_H #include #include #include #ifdef __cplusplus extern "C" { #endif #define BYTESUM(_bs) (_bs[0] + _bs[1] + _bs[2] + _bs[3]) #define ROUND_UP_TO(_b, _n) (_b + ((~(_b & (_n-1)) + 0x1) & (_n-1))); /* NSCODEC_BITMAP_STREAM */ struct _NSC_STREAM { uint32 PlaneByteCount[4]; uint8 colorLossLevel; uint8 ChromaSubSamplingLevel; uint16 Reserved; STREAM* pdata; }; typedef struct _NSC_STREAM NSC_STREAM; struct _NSC_CONTEXT { uint32 OrgByteCount[4]; /* original byte length of luma, chroma orange, chroma green, alpha variable in order */ NSC_STREAM* nsc_stream; uint16 width; uint16 height; uint8* bmpdata; /* final argb values in little endian order */ STREAM* org_buf[4]; /* Decompressed Plane Buffers in the respective order */ }; typedef struct _NSC_CONTEXT NSC_CONTEXT; FREERDP_API NSC_CONTEXT* nsc_context_new(void); FREERDP_API void nsc_process_message(NSC_CONTEXT* context, uint8* data, uint32 length); FREERDP_API void nsc_context_initialize(NSC_CONTEXT* context, STREAM* s); FREERDP_API void nsc_stream_initialize(NSC_CONTEXT* context, STREAM* s); FREERDP_API void nsc_rle_decompress_data(NSC_CONTEXT* context); FREERDP_API void nsc_ycocg_rgb_convert(NSC_CONTEXT* context); FREERDP_API void nsc_rle_decode(STREAM* in, STREAM* out, uint32 origsz); FREERDP_API void nsc_chroma_supersample(NSC_CONTEXT* context); FREERDP_API void nsc_cl_expand(STREAM* stream, uint8 shiftcount, uint32 origsz); FREERDP_API void nsc_colorloss_recover(NSC_CONTEXT* context); FREERDP_API void nsc_ycocg_rgb(NSC_CONTEXT* context); FREERDP_API void nsc_context_destroy(NSC_CONTEXT* context); #ifdef __cplusplus } #endif #endif /* __NSC_H */ FreeRDP-1.0.2/include/freerdp/codec/rfx.h000066400000000000000000000100551207112532300200350ustar00rootroot00000000000000/** * FreeRDP: A Remote Desktop Protocol client. * RemoteFX Codec * * Copyright 2011 Vic Lee * * 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. */ #ifndef __RFX_H #define __RFX_H #include #include #include #ifdef __cplusplus extern "C" { #endif enum _RLGR_MODE { RLGR1, RLGR3 }; typedef enum _RLGR_MODE RLGR_MODE; enum _RFX_PIXEL_FORMAT { RFX_PIXEL_FORMAT_BGRA, RFX_PIXEL_FORMAT_RGBA, RFX_PIXEL_FORMAT_BGR, RFX_PIXEL_FORMAT_RGB, RFX_PIXEL_FORMAT_BGR565_LE, RFX_PIXEL_FORMAT_RGB565_LE, RFX_PIXEL_FORMAT_PALETTE4_PLANER, RFX_PIXEL_FORMAT_PALETTE8 }; typedef enum _RFX_PIXEL_FORMAT RFX_PIXEL_FORMAT; struct _RFX_RECT { uint16 x; uint16 y; uint16 width; uint16 height; }; typedef struct _RFX_RECT RFX_RECT; struct _RFX_TILE { uint16 x; uint16 y; uint8* data; }; typedef struct _RFX_TILE RFX_TILE; struct _RFX_MESSAGE { /** * The rects array represents the updated region of the frame. The UI * requires to clip drawing destination base on the union of the rects. */ uint16 num_rects; RFX_RECT* rects; /** * The tiles array represents the actual frame data. Each tile is always * 64x64. Note that only pixels inside the updated region (represented as * rects described above) are valid. Pixels outside of the region may * contain arbitrary data. */ uint16 num_tiles; RFX_TILE** tiles; }; typedef struct _RFX_MESSAGE RFX_MESSAGE; typedef struct _RFX_CONTEXT_PRIV RFX_CONTEXT_PRIV; struct _RFX_CONTEXT { uint16 flags; uint16 properties; uint16 width; uint16 height; RLGR_MODE mode; uint32 version; uint32 codec_id; uint32 codec_version; RFX_PIXEL_FORMAT pixel_format; uint8 bits_per_pixel; /* color palette allocated by the application */ const uint8* palette; /* temporary data within a frame */ uint32 frame_idx; boolean header_processed; uint8 num_quants; uint32* quants; uint8 quant_idx_y; uint8 quant_idx_cb; uint8 quant_idx_cr; /* routines */ void (*decode_ycbcr_to_rgb)(sint16* y_r_buf, sint16* cb_g_buf, sint16* cr_b_buf); void (*encode_rgb_to_ycbcr)(sint16* y_r_buf, sint16* cb_g_buf, sint16* cr_b_buf); void (*quantization_decode)(sint16* buffer, const uint32* quantization_values); void (*quantization_encode)(sint16* buffer, const uint32* quantization_values); void (*dwt_2d_decode)(sint16* buffer, sint16* dwt_buffer); void (*dwt_2d_encode)(sint16* buffer, sint16* dwt_buffer); /* private definitions */ RFX_CONTEXT_PRIV* priv; }; typedef struct _RFX_CONTEXT RFX_CONTEXT; FREERDP_API RFX_CONTEXT* rfx_context_new(void); FREERDP_API void rfx_context_free(RFX_CONTEXT* context); FREERDP_API void rfx_context_set_cpu_opt(RFX_CONTEXT* context, uint32 cpu_opt); FREERDP_API void rfx_context_set_pixel_format(RFX_CONTEXT* context, RFX_PIXEL_FORMAT pixel_format); FREERDP_API void rfx_context_reset(RFX_CONTEXT* context); FREERDP_API RFX_MESSAGE* rfx_process_message(RFX_CONTEXT* context, uint8* data, uint32 length); FREERDP_API uint16 rfx_message_get_tile_count(RFX_MESSAGE* message); FREERDP_API RFX_TILE* rfx_message_get_tile(RFX_MESSAGE* message, int index); FREERDP_API uint16 rfx_message_get_rect_count(RFX_MESSAGE* message); FREERDP_API RFX_RECT* rfx_message_get_rect(RFX_MESSAGE* message, int index); FREERDP_API void rfx_message_free(RFX_CONTEXT* context, RFX_MESSAGE* message); FREERDP_API void rfx_compose_message_header(RFX_CONTEXT* context, STREAM* s); FREERDP_API void rfx_compose_message(RFX_CONTEXT* context, STREAM* s, const RFX_RECT* rects, int num_rects, uint8* image_data, int width, int height, int rowstride); #ifdef __cplusplus } #endif #endif /* __RFX_H */ FreeRDP-1.0.2/include/freerdp/constants.h000066400000000000000000000054131207112532300201770ustar00rootroot00000000000000/** * FreeRDP: A Remote Desktop Protocol Client * RDP Constants * * Copyright 2011 Marc-Andre Moreau * * 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. */ #ifndef __FREERDP_CONSTANTS #define __FREERDP_CONSTANTS /** * Codec IDs */ enum RDP_CODEC_ID { CODEC_ID_NONE = 0x00, CODEC_ID_NSCODEC = 0x01, CODEC_ID_REMOTEFX = 0x03 }; /** * Static Virtual Channel Flags */ enum RDP_SVC_CHANNEL_FLAG { CHANNEL_FLAG_MIDDLE = 0, CHANNEL_FLAG_FIRST = 0x01, CHANNEL_FLAG_LAST = 0x02, CHANNEL_FLAG_ONLY = (CHANNEL_FLAG_FIRST | CHANNEL_FLAG_LAST), CHANNEL_FLAG_SHOW_PROTOCOL = 0x10, CHANNEL_FLAG_SUSPEND = 0x20, CHANNEL_FLAG_RESUME = 0x40, CHANNEL_FLAG_FAIL = 0x100 }; /** * Static Virtual Channel Options */ enum RDP_SVC_CHANNEL_OPTION { CHANNEL_OPTION_SHOW_PROTOCOL = 0x00200000, CHANNEL_OPTION_COMPRESS = 0x00400000, CHANNEL_OPTION_COMPRESS_RDP = 0x00800000, CHANNEL_OPTION_PRI_LOW = 0x02000000, CHANNEL_OPTION_PRI_MED = 0x04000000, CHANNEL_OPTION_PRI_HIGH = 0x08000000, CHANNEL_OPTION_ENCRYPT_CS = 0x10000000, CHANNEL_OPTION_ENCRYPT_SC = 0x20000000, CHANNEL_OPTION_ENCRYPT_RDP = 0x40000000, CHANNEL_OPTION_INITIALIZED = 0x80000000 }; /** * Static Virtual Channel Events */ enum RDP_SVC_CHANNEL_EVENT { CHANNEL_EVENT_INITIALIZED = 0, CHANNEL_EVENT_CONNECTED = 1, CHANNEL_EVENT_V1_CONNECTED = 2, CHANNEL_EVENT_DISCONNECTED = 3, CHANNEL_EVENT_TERMINATED = 4, CHANNEL_EVENT_DATA_RECEIVED = 10, CHANNEL_EVENT_WRITE_COMPLETE = 11, CHANNEL_EVENT_WRITE_CANCELLED = 12, CHANNEL_EVENT_USER = 1000 }; /** * Virtual Channel Constants */ #define CHANNEL_CHUNK_LENGTH 1600 /** * CPU Optimization flags */ #define CPU_SSE2 0x1 /** * OSMajorType */ #define OSMAJORTYPE_UNSPECIFIED 0x0000 #define OSMAJORTYPE_WINDOWS 0x0001 #define OSMAJORTYPE_OS2 0x0002 #define OSMAJORTYPE_MACINTOSH 0x0003 #define OSMAJORTYPE_UNIX 0x0004 /** * OSMinorType */ #define OSMINORTYPE_UNSPECIFIED 0x0000 #define OSMINORTYPE_WINDOWS_31X 0x0001 #define OSMINORTYPE_WINDOWS_95 0x0002 #define OSMINORTYPE_WINDOWS_NT 0x0003 #define OSMINORTYPE_OS2_V21 0x0004 #define OSMINORTYPE_POWER_PC 0x0005 #define OSMINORTYPE_MACINTOSH 0x0006 #define OSMINORTYPE_NATIVE_XSERVER 0x0007 #define OSMINORTYPE_PSEUDO_XSERVER 0x0008 #endif FreeRDP-1.0.2/include/freerdp/dvc.h000066400000000000000000000113421207112532300167350ustar00rootroot00000000000000/** * FreeRDP: A Remote Desktop Protocol client. * Dynamic Virtual Channel Interface * * Copyright 2010-2011 Vic Lee * * 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. */ /** * DVC Plugin API: See the original MS DVC Client API: * http://msdn.microsoft.com/en-us/library/bb540880%28v=VS.85%29.aspx * * The FreeRDP DVC Plugin API is a simulation of the MS DVC Client API in C. * The main difference is that every interface method must take an instance * pointer as the first parameter. */ /** * Implemented by DRDYNVC: * o IWTSVirtualChannelManager * o IWTSListener * o IWTSVirtualChannel * * Implemented by DVC plugin: * o IWTSPlugin * o IWTSListenerCallback * o IWTSVirtualChannelCallback * * A basic DVC plugin implementation: * 1. DVCPluginEntry: * The plugin entry point, which creates and initializes a new IWTSPlugin * instance * 2. IWTSPlugin.Initialize: * Call IWTSVirtualChannelManager.CreateListener with a newly created * IWTSListenerCallback instance * 3. IWTSListenerCallback.OnNewChannelConnection: * Create IWTSVirtualChannelCallback instance if the new channel is accepted */ #ifndef __FREERDP_DVC_H #define __FREERDP_DVC_H #include typedef struct _IWTSVirtualChannelManager IWTSVirtualChannelManager; typedef struct _IWTSListener IWTSListener; typedef struct _IWTSVirtualChannel IWTSVirtualChannel; typedef struct _IWTSPlugin IWTSPlugin; typedef struct _IWTSListenerCallback IWTSListenerCallback; typedef struct _IWTSVirtualChannelCallback IWTSVirtualChannelCallback; struct _IWTSListener { /* Retrieves the listener-specific configuration. */ int (*GetConfiguration) (IWTSListener* pListener, void** ppPropertyBag); }; struct _IWTSVirtualChannel { /* Starts a write request on the channel. */ int (*Write) (IWTSVirtualChannel* pChannel, uint32 cbSize, uint8* pBuffer, void* pReserved); /* Closes the channel. */ int (*Close) (IWTSVirtualChannel* pChannel); }; struct _IWTSVirtualChannelManager { /* Returns an instance of a listener object that listens on a specific endpoint, or creates a static channel. */ int (*CreateListener) (IWTSVirtualChannelManager* pChannelMgr, const char* pszChannelName, uint32 ulFlags, IWTSListenerCallback* pListenerCallback, IWTSListener** ppListener); /* Push a virtual channel event. This is a FreeRDP extension to standard MS API. */ int (*PushEvent) (IWTSVirtualChannelManager* pChannelMgr, RDP_EVENT* pEvent); }; struct _IWTSPlugin { /* Used for the first call that is made from the client to the plug-in. */ int (*Initialize) (IWTSPlugin* pPlugin, IWTSVirtualChannelManager* pChannelMgr); /* Notifies the plug-in that the Remote Desktop Connection (RDC) client has successfully connected to the Remote Desktop Session Host (RD Session Host) server. */ int (*Connected) (IWTSPlugin* pPlugin); /* Notifies the plug-in that the Remote Desktop Connection (RDC) client has disconnected from the RD Session Host server. */ int (*Disconnected) (IWTSPlugin* pPlugin, uint32 dwDisconnectCode); /* Notifies the plug-in that the Remote Desktop Connection (RDC) client has terminated. */ int (*Terminated) (IWTSPlugin* pPlugin); }; struct _IWTSListenerCallback { /* Accepts or denies a connection request for an incoming connection to the associated listener. */ int (*OnNewChannelConnection) (IWTSListenerCallback* pListenerCallback, IWTSVirtualChannel* pChannel, uint8* Data, int* pbAccept, IWTSVirtualChannelCallback** ppCallback); }; struct _IWTSVirtualChannelCallback { /* Notifies the user about data that is being received. */ int (*OnDataReceived) (IWTSVirtualChannelCallback* pChannelCallback, uint32 cbSize, uint8* pBuffer); /* Notifies the user that the channel has been closed. */ int (*OnClose) (IWTSVirtualChannelCallback* pChannelCallback); }; /* The DVC Plugin entry points */ typedef struct _IDRDYNVC_ENTRY_POINTS IDRDYNVC_ENTRY_POINTS; struct _IDRDYNVC_ENTRY_POINTS { int (*RegisterPlugin) (IDRDYNVC_ENTRY_POINTS* pEntryPoints, const char* name, IWTSPlugin* pPlugin); IWTSPlugin* (*GetPlugin) (IDRDYNVC_ENTRY_POINTS* pEntryPoints, const char* name); RDP_PLUGIN_DATA* (*GetPluginData) (IDRDYNVC_ENTRY_POINTS* pEntryPoints); }; typedef int (*PDVC_PLUGIN_ENTRY) (IDRDYNVC_ENTRY_POINTS*); #endif FreeRDP-1.0.2/include/freerdp/extension.h000066400000000000000000000036661207112532300202070ustar00rootroot00000000000000/** * FreeRDP: A Remote Desktop Protocol Client * RDP Extensions * * Copyright 2010-2011 Vic Lee * * 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. */ #ifndef __RDP_EXTENSION_H #define __RDP_EXTENSION_H #include #include #include #define FREERDP_EXT_EXPORT_FUNC_NAME "FreeRDPExtensionEntry" typedef struct rdp_ext_plugin rdpExtPlugin; struct rdp_ext_plugin { void* ext; int (*init) (rdpExtPlugin* plugin, freerdp* instance); int (*uninit) (rdpExtPlugin* plugin, freerdp* instance); }; typedef uint32 (FREERDP_CC* PFREERDP_EXTENSION_HOOK)(rdpExtPlugin* plugin, freerdp* instance); typedef uint32 (FREERDP_CC* PREGISTEREXTENSION)(rdpExtPlugin* plugin); typedef uint32 (FREERDP_CC* PREGISTERPRECONNECTHOOK)(rdpExtPlugin* plugin, PFREERDP_EXTENSION_HOOK hook); typedef uint32 (FREERDP_CC* PREGISTERPOSTCONNECTHOOK)(rdpExtPlugin* plugin, PFREERDP_EXTENSION_HOOK hook); struct _FREERDP_EXTENSION_ENTRY_POINTS { void* ext; /* Reference to internal instance */ PREGISTEREXTENSION pRegisterExtension; PREGISTERPRECONNECTHOOK pRegisterPreConnectHook; PREGISTERPOSTCONNECTHOOK pRegisterPostConnectHook; void* data; }; typedef struct _FREERDP_EXTENSION_ENTRY_POINTS FREERDP_EXTENSION_ENTRY_POINTS; typedef FREERDP_EXTENSION_ENTRY_POINTS* PFREERDP_EXTENSION_ENTRY_POINTS; typedef int (FREERDP_CC* PFREERDP_EXTENSION_ENTRY)(PFREERDP_EXTENSION_ENTRY_POINTS pEntryPoints); #endif /* __RDP_EXTENSION_H */ FreeRDP-1.0.2/include/freerdp/freerdp.h000066400000000000000000000073001207112532300176070ustar00rootroot00000000000000/** * FreeRDP: A Remote Desktop Protocol Client * FreeRDP Interface * * Copyright 2009-2011 Jay Sorg * * 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. */ #ifndef __FREERDP_H #define __FREERDP_H typedef struct rdp_rdp rdpRdp; typedef struct rdp_gdi rdpGdi; typedef struct rdp_rail rdpRail; typedef struct rdp_cache rdpCache; typedef struct rdp_channels rdpChannels; typedef struct rdp_graphics rdpGraphics; typedef struct rdp_freerdp freerdp; typedef struct rdp_context rdpContext; typedef struct rdp_freerdp_peer freerdp_peer; #include #include #include #include #include #include #ifdef __cplusplus extern "C" { #endif typedef void (*pContextNew)(freerdp* instance, rdpContext* context); typedef void (*pContextFree)(freerdp* instance, rdpContext* context); typedef boolean (*pPreConnect)(freerdp* instance); typedef boolean (*pPostConnect)(freerdp* instance); typedef boolean (*pAuthenticate)(freerdp* instance, char** username, char** password, char** domain); typedef boolean (*pVerifyCertificate)(freerdp* instance, char* subject, char* issuer, char* fingerprint); typedef int (*pSendChannelData)(freerdp* instance, int channelId, uint8* data, int size); typedef int (*pReceiveChannelData)(freerdp* instance, int channelId, uint8* data, int size, int flags, int total_size); struct rdp_context { freerdp* instance; /* 0 */ freerdp_peer* peer; /* 1 */ uint32 paddingA[16 - 2]; /* 2 */ int argc; /* 16 */ char** argv; /* 17 */ uint32 paddingB[32 - 18]; /* 18 */ rdpRdp* rdp; /* 32 */ rdpGdi* gdi; /* 33 */ rdpRail* rail; /* 34 */ rdpCache* cache; /* 35 */ rdpChannels* channels; /* 36 */ rdpGraphics* graphics; /* 37 */ uint32 paddingC[64 - 38]; /* 38 */ }; struct rdp_freerdp { rdpContext* context; /* 0 */ uint32 paddingA[16 - 1]; /* 1 */ rdpInput* input; /* 16 */ rdpUpdate* update; /* 17 */ rdpSettings* settings; /* 18 */ uint32 paddingB[32 - 19]; /* 19 */ size_t context_size; /* 32 */ pContextNew ContextNew; /* 33 */ pContextFree ContextFree; /* 34 */ uint32 paddingC[48 - 35]; /* 35 */ pPreConnect PreConnect; /* 48 */ pPostConnect PostConnect; /* 49 */ pAuthenticate Authenticate; /* 50 */ pVerifyCertificate VerifyCertificate; /* 51 */ uint32 paddingD[64 - 52]; /* 52 */ pSendChannelData SendChannelData; /* 64 */ pReceiveChannelData ReceiveChannelData; /* 65 */ uint32 paddingE[80 - 66]; /* 66 */ }; FREERDP_API void freerdp_context_new(freerdp* instance); FREERDP_API void freerdp_context_free(freerdp* instance); FREERDP_API boolean freerdp_connect(freerdp* instance); FREERDP_API boolean freerdp_shall_disconnect(freerdp* instance); FREERDP_API boolean freerdp_disconnect(freerdp* instance); FREERDP_API boolean freerdp_get_fds(freerdp* instance, void** rfds, int* rcount, void** wfds, int* wcount); FREERDP_API boolean freerdp_check_fds(freerdp* instance); FREERDP_API void freerdp_send_keep_alive(freerdp* instance); FREERDP_API uint32 freerdp_error_info(freerdp* instance); FREERDP_API void freerdp_get_version(int* major, int* minor, int* revision); FREERDP_API freerdp* freerdp_new(); FREERDP_API void freerdp_free(freerdp* instance); #ifdef __cplusplus } #endif #endif FreeRDP-1.0.2/include/freerdp/gdi/000077500000000000000000000000001207112532300165525ustar00rootroot00000000000000FreeRDP-1.0.2/include/freerdp/gdi/16bpp.h000066400000000000000000000024621207112532300176570ustar00rootroot00000000000000/** * FreeRDP: A Remote Desktop Protocol Client * GDI 16bpp Internal Buffer Routines * * Copyright 2010-2011 Marc-Andre Moreau * * 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. */ #include #include #include typedef int (*pLineTo_16bpp)(HGDI_DC hdc, int nXEnd, int nYEnd); FREERDP_API uint16 gdi_get_color_16bpp(HGDI_DC hdc, GDI_COLOR color); FREERDP_API int FillRect_16bpp(HGDI_DC hdc, HGDI_RECT rect, HGDI_BRUSH hbr); FREERDP_API int BitBlt_16bpp(HGDI_DC hdcDest, int nXDest, int nYDest, int nWidth, int nHeight, HGDI_DC hdcSrc, int nXSrc, int nYSrc, int rop); FREERDP_API int PatBlt_16bpp(HGDI_DC hdc, int nXLeft, int nYLeft, int nWidth, int nHeight, int rop); FREERDP_API int LineTo_16bpp(HGDI_DC hdc, int nXEnd, int nYEnd); FreeRDP-1.0.2/include/freerdp/gdi/32bpp.h000066400000000000000000000024621207112532300176550ustar00rootroot00000000000000/** * FreeRDP: A Remote Desktop Protocol Client * GDI 32bpp Internal Buffer Routines * * Copyright 2010-2011 Marc-Andre Moreau * * 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. */ #include #include #include typedef int (*pLineTo_32bpp)(HGDI_DC hdc, int nXEnd, int nYEnd); FREERDP_API uint32 gdi_get_color_32bpp(HGDI_DC hdc, GDI_COLOR color); FREERDP_API int FillRect_32bpp(HGDI_DC hdc, HGDI_RECT rect, HGDI_BRUSH hbr); FREERDP_API int BitBlt_32bpp(HGDI_DC hdcDest, int nXDest, int nYDest, int nWidth, int nHeight, HGDI_DC hdcSrc, int nXSrc, int nYSrc, int rop); FREERDP_API int PatBlt_32bpp(HGDI_DC hdc, int nXLeft, int nYLeft, int nWidth, int nHeight, int rop); FREERDP_API int LineTo_32bpp(HGDI_DC hdc, int nXEnd, int nYEnd); FreeRDP-1.0.2/include/freerdp/gdi/8bpp.h000066400000000000000000000024521207112532300175770ustar00rootroot00000000000000/** * FreeRDP: A Remote Desktop Protocol Client * GDI 8bpp Internal Buffer Routines * * Copyright 2010-2011 Marc-Andre Moreau * * 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. */ #include #include #include typedef int (*pLineTo_8bpp)(HGDI_DC hdc, int nXEnd, int nYEnd); FREERDP_API uint8 gdi_get_color_8bpp(HGDI_DC hdc, GDI_COLOR color); FREERDP_API int FillRect_8bpp(HGDI_DC hdc, HGDI_RECT rect, HGDI_BRUSH hbr); FREERDP_API int BitBlt_8bpp(HGDI_DC hdcDest, int nXDest, int nYDest, int nWidth, int nHeight, HGDI_DC hdcSrc, int nXSrc, int nYSrc, int rop); FREERDP_API int PatBlt_8bpp(HGDI_DC hdc, int nXLeft, int nYLeft, int nWidth, int nHeight, int rop); FREERDP_API int LineTo_8bpp(HGDI_DC hdc, int nXEnd, int nYEnd); FreeRDP-1.0.2/include/freerdp/gdi/bitmap.h000066400000000000000000000041341207112532300202010ustar00rootroot00000000000000/** * FreeRDP: A Remote Desktop Protocol Client * GDI Bitmap Functions * * Copyright 2010-2011 Marc-Andre Moreau * * 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. */ #ifndef __GDI_BITMAP_H #define __GDI_BITMAP_H #include #include FREERDP_API GDI_COLOR gdi_GetPixel(HGDI_DC hdc, int nXPos, int nYPos); FREERDP_API GDI_COLOR gdi_SetPixel(HGDI_DC hdc, int X, int Y, GDI_COLOR crColor); FREERDP_API uint8 gdi_GetPixel_8bpp(HGDI_BITMAP hBmp, int X, int Y); FREERDP_API uint16 gdi_GetPixel_16bpp(HGDI_BITMAP hBmp, int X, int Y); FREERDP_API uint32 gdi_GetPixel_32bpp(HGDI_BITMAP hBmp, int X, int Y); FREERDP_API uint8* gdi_GetPointer_8bpp(HGDI_BITMAP hBmp, int X, int Y); FREERDP_API uint16* gdi_GetPointer_16bpp(HGDI_BITMAP hBmp, int X, int Y); FREERDP_API uint32* gdi_GetPointer_32bpp(HGDI_BITMAP hBmp, int X, int Y); FREERDP_API void gdi_SetPixel_8bpp(HGDI_BITMAP hBmp, int X, int Y, uint8 pixel); FREERDP_API void gdi_SetPixel_16bpp(HGDI_BITMAP hBmp, int X, int Y, uint16 pixel); FREERDP_API void gdi_SetPixel_32bpp(HGDI_BITMAP hBmp, int X, int Y, uint32 pixel); FREERDP_API HGDI_BITMAP gdi_CreateBitmap(int nWidth, int nHeight, int cBitsPerPixel, uint8* data); FREERDP_API HGDI_BITMAP gdi_CreateCompatibleBitmap(HGDI_DC hdc, int nWidth, int nHeight); FREERDP_API int gdi_BitBlt(HGDI_DC hdcDest, int nXDest, int nYDest, int nWidth, int nHeight, HGDI_DC hdcSrc, int nXSrc, int nYSrc, int rop); typedef int (*p_BitBlt)(HGDI_DC hdcDest, int nXDest, int nYDest, int nWidth, int nHeight, HGDI_DC hdcSrc, int nXSrc, int nYSrc, int rop); #endif /* __GDI_BITMAP_H */ FreeRDP-1.0.2/include/freerdp/gdi/brush.h000066400000000000000000000022111207112532300200420ustar00rootroot00000000000000/** * FreeRDP: A Remote Desktop Protocol Client * GDI Brush Functions * * Copyright 2010-2011 Marc-Andre Moreau * * 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. */ #ifndef __GDI_BRUSH_H #define __GDI_BRUSH_H #include #include FREERDP_API HGDI_BRUSH gdi_CreateSolidBrush(GDI_COLOR crColor); FREERDP_API HGDI_BRUSH gdi_CreatePatternBrush(HGDI_BITMAP hbmp); FREERDP_API int gdi_PatBlt(HGDI_DC hdc, int nXLeft, int nYLeft, int nWidth, int nHeight, int rop); typedef int (*p_PatBlt)(HGDI_DC hdc, int nXLeft, int nYLeft, int nWidth, int nHeight, int rop); #endif /* __GDI_BRUSH_H */ FreeRDP-1.0.2/include/freerdp/gdi/clipping.h000066400000000000000000000021641207112532300205330ustar00rootroot00000000000000/** * FreeRDP: A Remote Desktop Protocol Client * GDI Clipping Functions * * Copyright 2010-2011 Marc-Andre Moreau * * 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. */ #ifndef __GDI_CLIPPING_H #define __GDI_CLIPPING_H #include #include FREERDP_API int gdi_SetClipRgn(HGDI_DC hdc, int nXLeft, int nYLeft, int nWidth, int nHeight); FREERDP_API HGDI_RGN gdi_GetClipRgn(HGDI_DC hdc); FREERDP_API int gdi_SetNullClipRgn(HGDI_DC hdc); FREERDP_API int gdi_ClipCoords(HGDI_DC hdc, int *x, int *y, int *w, int *h, int *srcx, int *srcy); #endif /* __GDI_CLIPPING_H */ FreeRDP-1.0.2/include/freerdp/gdi/dc.h000066400000000000000000000022141207112532300173100ustar00rootroot00000000000000/** * FreeRDP: A Remote Desktop Protocol Client * GDI Device Context Functions * * Copyright 2010-2011 Marc-Andre Moreau * * 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. */ #ifndef __GDI_DC_H #define __GDI_DC_H #include #include FREERDP_API HGDI_DC gdi_GetDC(); FREERDP_API HGDI_DC gdi_CreateDC(HCLRCONV clrconv, int bpp); FREERDP_API HGDI_DC gdi_CreateCompatibleDC(HGDI_DC hdc); FREERDP_API HGDIOBJECT gdi_SelectObject(HGDI_DC hdc, HGDIOBJECT hgdiobject); FREERDP_API int gdi_DeleteObject(HGDIOBJECT hgdiobject); FREERDP_API int gdi_DeleteDC(HGDI_DC hdc); #endif /* __GDI_DC_H */ FreeRDP-1.0.2/include/freerdp/gdi/drawing.h000066400000000000000000000023261207112532300203610ustar00rootroot00000000000000/** * FreeRDP: A Remote Desktop Protocol Client * GDI Drawing Functions * * Copyright 2010-2011 Marc-Andre Moreau * * 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. */ #ifndef __GDI_DRAWING_H #define __GDI_DRAWING_H #include #include FREERDP_API int gdi_GetROP2(HGDI_DC hdc); FREERDP_API int gdi_SetROP2(HGDI_DC hdc, int fnDrawMode); FREERDP_API GDI_COLOR gdi_GetBkColor(HGDI_DC hdc); FREERDP_API GDI_COLOR gdi_SetBkColor(HGDI_DC hdc, GDI_COLOR crColor); FREERDP_API int gdi_GetBkMode(HGDI_DC hdc); FREERDP_API int gdi_SetBkMode(HGDI_DC hdc, int iBkMode); FREERDP_API GDI_COLOR gdi_SetTextColor(HGDI_DC hdc, GDI_COLOR crColor); #endif /* __GDI_DRAWING_H */ FreeRDP-1.0.2/include/freerdp/gdi/gdi.h000066400000000000000000000150541207112532300174730ustar00rootroot00000000000000/** * FreeRDP: A Remote Desktop Protocol Client * GDI Library * * Copyright 2010-2011 Marc-Andre Moreau * * 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. */ #ifndef __GDI_H #define __GDI_H #include #include #include #include #include /* For more information, see [MS-RDPEGDI] */ /* Binary Raster Operations (ROP2) */ #define GDI_R2_BLACK 0x01 /* D = 0 */ #define GDI_R2_NOTMERGEPEN 0x02 /* D = ~(D | P) */ #define GDI_R2_MASKNOTPEN 0x03 /* D = D & ~P */ #define GDI_R2_NOTCOPYPEN 0x04 /* D = ~P */ #define GDI_R2_MASKPENNOT 0x05 /* D = P & ~D */ #define GDI_R2_NOT 0x06 /* D = ~D */ #define GDI_R2_XORPEN 0x07 /* D = D ^ P */ #define GDI_R2_NOTMASKPEN 0x08 /* D = ~(D & P) */ #define GDI_R2_MASKPEN 0x09 /* D = D & P */ #define GDI_R2_NOTXORPEN 0x0A /* D = ~(D ^ P) */ #define GDI_R2_NOP 0x0B /* D = D */ #define GDI_R2_MERGENOTPEN 0x0C /* D = D | ~P */ #define GDI_R2_COPYPEN 0x0D /* D = P */ #define GDI_R2_MERGEPENNOT 0x0E /* D = P | ~D */ #define GDI_R2_MERGEPEN 0x0F /* D = P | D */ #define GDI_R2_WHITE 0x10 /* D = 1 */ /* Ternary Raster Operations (ROP3) */ #define GDI_SRCCOPY 0x00CC0020 /* D = S */ #define GDI_SRCPAINT 0x00EE0086 /* D = S | D */ #define GDI_SRCAND 0x008800C6 /* D = S & D */ #define GDI_SRCINVERT 0x00660046 /* D = S ^ D */ #define GDI_SRCERASE 0x00440328 /* D = S & ~D */ #define GDI_NOTSRCCOPY 0x00330008 /* D = ~S */ #define GDI_NOTSRCERASE 0x001100A6 /* D = ~S & ~D */ #define GDI_MERGECOPY 0x00C000CA /* D = S & P */ #define GDI_MERGEPAINT 0x00BB0226 /* D = ~S | D */ #define GDI_PATCOPY 0x00F00021 /* D = P */ #define GDI_PATPAINT 0x00FB0A09 /* D = D | (P | ~S) */ #define GDI_PATINVERT 0x005A0049 /* D = P ^ D */ #define GDI_DSTINVERT 0x00550009 /* D = ~D */ #define GDI_BLACKNESS 0x00000042 /* D = 0 */ #define GDI_WHITENESS 0x00FF0062 /* D = 1 */ #define GDI_DSPDxax 0x00E20746 /* D = (S & P) | (~S & D) */ #define GDI_SPna 0x000C0324 /* D = S & ~P */ #define GDI_DSna 0x00220326 /* D = D & ~S */ #define GDI_DPa 0x00A000C9 /* D = D & P */ #define GDI_PDxn 0x00A50065 /* D = D ^ ~P */ /* Brush Styles */ #define GDI_BS_SOLID 0x00 #define GDI_BS_NULL 0x01 #define GDI_BS_HATCHED 0x02 #define GDI_BS_PATTERN 0x03 /* Hatch Patterns */ #define GDI_HS_HORIZONTAL 0x00 #define GDI_HS_VERTICAL 0x01 #define GDI_HS_FDIAGONAL 0x02 #define GDI_HS_BDIAGONAL 0x03 #define GDI_HS_CROSS 0x04 #define GDI_HS_DIAGCROSS 0x05 /* Pen Styles */ #define GDI_PS_SOLID 0x00 #define GDI_PS_DASH 0x01 #define GDI_PS_NULL 0x05 /* Background Modes */ #define GDI_OPAQUE 0x00000001 #define GDI_TRANSPARENT 0x00000002 /* GDI Object Types */ #define GDIOBJECT_BITMAP 0x00 #define GDIOBJECT_PEN 0x01 #define GDIOBJECT_PALETTE 0x02 #define GDIOBJECT_BRUSH 0x03 #define GDIOBJECT_RECT 0x04 #define GDIOBJECT_REGION 0x04 struct _GDIOBJECT { uint8 objectType; }; typedef struct _GDIOBJECT GDIOBJECT; typedef GDIOBJECT* HGDIOBJECT; /* RGB encoded as 0x00BBGGRR */ typedef unsigned int GDI_COLOR; typedef GDI_COLOR* LPGDI_COLOR; struct _GDI_RECT { uint8 objectType; int left; int top; int right; int bottom; }; typedef struct _GDI_RECT GDI_RECT; typedef GDI_RECT* HGDI_RECT; struct _GDI_RGN { uint8 objectType; int x; /* left */ int y; /* top */ int w; /* width */ int h; /* height */ int null; /* null region */ }; typedef struct _GDI_RGN GDI_RGN; typedef GDI_RGN* HGDI_RGN; struct _GDI_BITMAP { uint8 objectType; int bytesPerPixel; int bitsPerPixel; int width; int height; int scanline; uint8* data; }; typedef struct _GDI_BITMAP GDI_BITMAP; typedef GDI_BITMAP* HGDI_BITMAP; struct _GDI_PEN { uint8 objectType; int style; int width; int posX; int posY; GDI_COLOR color; }; typedef struct _GDI_PEN GDI_PEN; typedef GDI_PEN* HGDI_PEN; struct _GDI_PALETTEENTRY { uint8 red; uint8 green; uint8 blue; }; typedef struct _GDI_PALETTEENTRY GDI_PALETTEENTRY; struct _GDI_PALETTE { uint16 count; GDI_PALETTEENTRY *entries; }; typedef struct _GDI_PALETTE GDI_PALETTE; typedef GDI_PALETTE* HGDI_PALETTE; struct _GDI_POINT { int x; int y; }; typedef struct _GDI_POINT GDI_POINT; typedef GDI_POINT* HGDI_POINT; struct _GDI_BRUSH { uint8 objectType; int style; HGDI_BITMAP pattern; GDI_COLOR color; }; typedef struct _GDI_BRUSH GDI_BRUSH; typedef GDI_BRUSH* HGDI_BRUSH; struct _GDI_WND { int count; int ninvalid; HGDI_RGN invalid; HGDI_RGN cinvalid; }; typedef struct _GDI_WND GDI_WND; typedef GDI_WND* HGDI_WND; struct _GDI_DC { HGDIOBJECT selectedObject; int bytesPerPixel; int bitsPerPixel; GDI_COLOR bkColor; GDI_COLOR textColor; HGDI_BRUSH brush; HGDI_RGN clip; HGDI_PEN pen; HGDI_WND hwnd; int drawMode; int bkMode; int alpha; int invert; int rgb555; }; typedef struct _GDI_DC GDI_DC; typedef GDI_DC* HGDI_DC; struct gdi_bitmap { rdpBitmap _p; HGDI_DC hdc; HGDI_BITMAP bitmap; HGDI_BITMAP org_bitmap; }; typedef struct gdi_bitmap gdiBitmap; struct gdi_glyph { rdpBitmap _p; HGDI_DC hdc; HGDI_BITMAP bitmap; HGDI_BITMAP org_bitmap; }; typedef struct gdi_glyph gdiGlyph; struct rdp_gdi { rdpContext* context; int width; int height; int dstBpp; int srcBpp; int cursor_x; int cursor_y; int bytesPerPixel; HGDI_DC hdc; HCLRCONV clrconv; gdiBitmap* primary; gdiBitmap* drawing; uint8* primary_buffer; GDI_COLOR textColor; void* rfx_context; void* nsc_context; gdiBitmap* tile; gdiBitmap* image; }; FREERDP_API uint32 gdi_rop3_code(uint8 code); FREERDP_API uint8* gdi_get_bitmap_pointer(HGDI_DC hdcBmp, int x, int y); FREERDP_API uint8* gdi_get_brush_pointer(HGDI_DC hdcBrush, int x, int y); FREERDP_API int gdi_is_mono_pixel_set(uint8* data, int x, int y, int width); FREERDP_API void gdi_resize(rdpGdi* gdi, int width, int height); FREERDP_API int gdi_init(freerdp* instance, uint32 flags, uint8* buffer); FREERDP_API void gdi_free(freerdp* instance); #ifdef WITH_DEBUG_GDI #define DEBUG_GDI(fmt, ...) DEBUG_CLASS(GDI, fmt, ## __VA_ARGS__) #else #define DEBUG_GDI(fmt, ...) DEBUG_NULL(fmt, ## __VA_ARGS__) #endif #endif /* __GDI_H */ FreeRDP-1.0.2/include/freerdp/gdi/line.h000066400000000000000000000023751207112532300176610ustar00rootroot00000000000000/** * FreeRDP: A Remote Desktop Protocol Client * GDI Line Functions * * Copyright 2010-2011 Marc-Andre Moreau * * 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. */ #ifndef __GDI_LINE_H #define __GDI_LINE_H #include #include FREERDP_API int gdi_LineTo(HGDI_DC hdc, int nXEnd, int nYEnd); FREERDP_API int gdi_PolylineTo(HGDI_DC hdc, GDI_POINT *lppt, int cCount); FREERDP_API int gdi_Polyline(HGDI_DC hdc, GDI_POINT *lppt, int cPoints); FREERDP_API int gdi_PolyPolyline(HGDI_DC hdc, GDI_POINT *lppt, int *lpdwPolyPoints, int cCount); FREERDP_API int gdi_MoveToEx(HGDI_DC hdc, int X, int Y, HGDI_POINT lpPoint); typedef int (*p_LineTo)(HGDI_DC hdc, int nXEnd, int nYEnd); #endif /* __GDI_LINE_H */ FreeRDP-1.0.2/include/freerdp/gdi/palette.h000066400000000000000000000016771207112532300203740ustar00rootroot00000000000000/** * FreeRDP: A Remote Desktop Protocol Client * GDI Palette Functions * * Copyright 2010-2011 Marc-Andre Moreau * * 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. */ #ifndef __GDI_PALETTE_H #define __GDI_PALETTE_H #include #include FREERDP_API HGDI_PALETTE gdi_CreatePalette(HGDI_PALETTE palette); FREERDP_API HGDI_PALETTE gdi_GetSystemPalette(); #endif /* __GDI_PALETTE_H */ FreeRDP-1.0.2/include/freerdp/gdi/pen.h000066400000000000000000000020571207112532300175110ustar00rootroot00000000000000/** * FreeRDP: A Remote Desktop Protocol Client * GDI Pen Functions * * Copyright 2010-2011 Marc-Andre Moreau * * 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. */ #ifndef __GDI_PEN_H #define __GDI_PEN_H #include #include FREERDP_API HGDI_PEN gdi_CreatePen(int fnPenStyle, int nWidth, int crColor); FREERDP_API uint8 gdi_GetPenColor_8bpp(HGDI_PEN pen); FREERDP_API uint16 gdi_GetPenColor_16bpp(HGDI_PEN pen); FREERDP_API uint32 gdi_GetPenColor_32bpp(HGDI_PEN pen); #endif /* __GDI_PEN_H */ FreeRDP-1.0.2/include/freerdp/gdi/region.h000066400000000000000000000044571207112532300202200ustar00rootroot00000000000000/** * FreeRDP: A Remote Desktop Protocol Client * GDI Region Functions * * Copyright 2010-2011 Marc-Andre Moreau * * 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. */ #ifndef __GDI_REGION_H #define __GDI_REGION_H #include #include FREERDP_API HGDI_RGN gdi_CreateRectRgn(int nLeftRect, int nTopRect, int nRightRect, int nBottomRect); FREERDP_API HGDI_RECT gdi_CreateRect(int xLeft, int yTop, int xRight, int yBottom); FREERDP_API void gdi_RectToRgn(HGDI_RECT rect, HGDI_RGN rgn); FREERDP_API void gdi_CRectToRgn(int left, int top, int right, int bottom, HGDI_RGN rgn); FREERDP_API void gdi_RectToCRgn(HGDI_RECT rect, int *x, int *y, int *w, int *h); FREERDP_API void gdi_CRectToCRgn(int left, int top, int right, int bottom, int *x, int *y, int *w, int *h); FREERDP_API void gdi_RgnToRect(HGDI_RGN rgn, HGDI_RECT rect); FREERDP_API void gdi_CRgnToRect(int x, int y, int w, int h, HGDI_RECT rect); FREERDP_API void gdi_RgnToCRect(HGDI_RGN rgn, int *left, int *top, int *right, int *bottom); FREERDP_API void gdi_CRgnToCRect(int x, int y, int w, int h, int *left, int *top, int *right, int *bottom); FREERDP_API int gdi_CopyOverlap(int x, int y, int width, int height, int srcx, int srcy); FREERDP_API int gdi_SetRect(HGDI_RECT rc, int xLeft, int yTop, int xRight, int yBottom); FREERDP_API int gdi_SetRgn(HGDI_RGN hRgn, int nXLeft, int nYLeft, int nWidth, int nHeight); FREERDP_API int gdi_SetRectRgn(HGDI_RGN hRgn, int nLeftRect, int nTopRect, int nRightRect, int nBottomRect); FREERDP_API int gdi_EqualRgn(HGDI_RGN hSrcRgn1, HGDI_RGN hSrcRgn2); FREERDP_API int gdi_CopyRect(HGDI_RECT dst, HGDI_RECT src); FREERDP_API int gdi_PtInRect(HGDI_RECT rc, int x, int y); FREERDP_API int gdi_InvalidateRegion(HGDI_DC hdc, int x, int y, int w, int h); #endif /* __GDI_REGION_H */ FreeRDP-1.0.2/include/freerdp/gdi/shape.h000066400000000000000000000025271207112532300200310ustar00rootroot00000000000000/** * FreeRDP: A Remote Desktop Protocol Client * GDI Shape Functions * * Copyright 2010-2011 Marc-Andre Moreau * * 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. */ #ifndef __GDI_SHAPE_H #define __GDI_SHAPE_H #include #include FREERDP_API int gdi_Ellipse(HGDI_DC hdc, int nLeftRect, int nTopRect, int nRightRect, int nBottomRect); FREERDP_API int gdi_FillRect(HGDI_DC hdc, HGDI_RECT rect, HGDI_BRUSH hbr); FREERDP_API int gdi_Polygon(HGDI_DC hdc, GDI_POINT *lpPoints, int nCount); FREERDP_API int gdi_PolyPolygon(HGDI_DC hdc, GDI_POINT *lpPoints, int *lpPolyCounts, int nCount); FREERDP_API int gdi_Rectangle(HGDI_DC hdc, int nLeftRect, int nTopRect, int nRightRect, int nBottomRect); typedef int (*p_FillRect)(HGDI_DC hdc, HGDI_RECT rect, HGDI_BRUSH hbr); #endif /* __GDI_SHAPE_H */ FreeRDP-1.0.2/include/freerdp/graphics.h000066400000000000000000000132331207112532300177620ustar00rootroot00000000000000/** * FreeRDP: A Remote Desktop Protocol Client * Graphical Objects * * Copyright 2011 Marc-Andre Moreau * * 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. */ #ifndef __GRAPHICS_H #define __GRAPHICS_H typedef struct rdp_bitmap rdpBitmap; typedef struct rdp_pointer rdpPointer; typedef struct rdp_glyph rdpGlyph; #include #include #include #include /* Bitmap Class */ typedef void (*pBitmap_New)(rdpContext* context, rdpBitmap* bitmap); typedef void (*pBitmap_Free)(rdpContext* context, rdpBitmap* bitmap); typedef void (*pBitmap_Paint)(rdpContext* context, rdpBitmap* bitmap); typedef void (*pBitmap_Decompress)(rdpContext* context, rdpBitmap* bitmap, uint8* data, int width, int height, int bpp, int length, boolean compressed); typedef void (*pBitmap_SetSurface)(rdpContext* context, rdpBitmap* bitmap, boolean primary); struct rdp_bitmap { size_t size; /* 0 */ pBitmap_New New; /* 1 */ pBitmap_Free Free; /* 2 */ pBitmap_Paint Paint; /* 3 */ pBitmap_Decompress Decompress; /* 4 */ pBitmap_SetSurface SetSurface; /* 5 */ uint32 paddingA[16 - 6]; /* 6 */ uint32 left; /* 16 */ uint32 top; /* 17 */ uint32 right; /* 18 */ uint32 bottom; /* 19 */ uint32 width; /* 20 */ uint32 height; /* 21 */ uint32 bpp; /* 22 */ uint32 flags; /* 23 */ uint32 length; /* 24 */ uint8* data; /* 25 */ uint32 paddingB[32 - 26]; /* 26 */ boolean compressed; /* 32 */ boolean ephemeral; /* 33 */ uint32 paddingC[64 - 34]; /* 34 */ }; FREERDP_API rdpBitmap* Bitmap_Alloc(rdpContext* context); FREERDP_API void Bitmap_New(rdpContext* context, rdpBitmap* bitmap); FREERDP_API void Bitmap_Free(rdpContext* context, rdpBitmap* bitmap); FREERDP_API void Bitmap_Register(rdpContext* context, rdpBitmap* bitmap); FREERDP_API void Bitmap_Decompress(rdpContext* context, rdpBitmap* bitmap, uint8* data, int width, int height, int bpp, int length, boolean compressed); FREERDP_API void Bitmap_SetRectangle(rdpContext* context, rdpBitmap* bitmap, uint16 left, uint16 top, uint16 right, uint16 bottom); FREERDP_API void Bitmap_SetDimensions(rdpContext* context, rdpBitmap* bitmap, uint16 width, uint16 height); FREERDP_API void Bitmap_SetSurface(rdpContext* context, rdpBitmap* bitmap, boolean primary); /* Pointer Class */ typedef void (*pPointer_New)(rdpContext* context, rdpPointer* pointer); typedef void (*pPointer_Free)(rdpContext* context, rdpPointer* pointer); typedef void (*pPointer_Set)(rdpContext* context, rdpPointer* pointer); struct rdp_pointer { size_t size; /* 0 */ pPointer_New New; /* 1 */ pPointer_Free Free; /* 2 */ pPointer_Set Set; /* 3 */ uint32 paddingA[16 - 4]; /* 4 */ uint32 xPos; /* 16 */ uint32 yPos; /* 17 */ uint32 width; /* 18 */ uint32 height; /* 19 */ uint32 xorBpp; /* 20 */ uint32 lengthAndMask; /* 21 */ uint32 lengthXorMask; /* 22 */ uint8* xorMaskData; /* 23 */ uint8* andMaskData; /* 24 */ uint32 paddingB[32 - 25]; /* 25 */ }; FREERDP_API rdpPointer* Pointer_Alloc(rdpContext* context); FREERDP_API void Pointer_New(rdpContext* context, rdpPointer* pointer); FREERDP_API void Pointer_Free(rdpContext* context, rdpPointer* pointer); FREERDP_API void Pointer_Set(rdpContext* context, rdpPointer* pointer); /* Glyph Class */ typedef void (*pGlyph_New)(rdpContext* context, rdpGlyph* glyph); typedef void (*pGlyph_Free)(rdpContext* context, rdpGlyph* glyph); typedef void (*pGlyph_Draw)(rdpContext* context, rdpGlyph* glyph, int x, int y); typedef void (*pGlyph_BeginDraw)(rdpContext* context, int x, int y, int width, int height, uint32 bgcolor, uint32 fgcolor); typedef void (*pGlyph_EndDraw)(rdpContext* context, int x, int y, int width, int height, uint32 bgcolor, uint32 fgcolor); struct rdp_glyph { size_t size; /* 0 */ pGlyph_New New; /* 1 */ pGlyph_Free Free; /* 2 */ pGlyph_Draw Draw; /* 3 */ pGlyph_BeginDraw BeginDraw; /* 4 */ pGlyph_EndDraw EndDraw; /* 5 */ uint32 paddingA[16 - 6]; /* 6 */ sint32 x; /* 16 */ sint32 y; /* 17 */ uint32 cx; /* 18 */ uint32 cy; /* 19 */ uint32 cb; /* 20 */ uint8* aj; /* 21 */ uint32 paddingB[32 - 22]; /* 22 */ }; FREERDP_API rdpGlyph* Glyph_Alloc(rdpContext* context); FREERDP_API void Glyph_New(rdpContext* context, rdpGlyph* glyph); FREERDP_API void Glyph_Free(rdpContext* context, rdpGlyph* glyph); FREERDP_API void Glyph_Draw(rdpContext* context, rdpGlyph* glyph, int x, int y); FREERDP_API void Glyph_BeginDraw(rdpContext* context, int x, int y, int width, int height, uint32 bgcolor, uint32 fgcolor); FREERDP_API void Glyph_EndDraw(rdpContext* context, int x, int y, int width, int height, uint32 bgcolor, uint32 fgcolor); /* Graphics Module */ struct rdp_graphics { rdpContext* context; /* 0 */ rdpBitmap* Bitmap_Prototype; /* 1 */ rdpPointer* Pointer_Prototype; /* 2 */ rdpGlyph* Glyph_Prototype; /* 3 */ uint32 paddingA[16 - 4]; /* 4 */ }; FREERDP_API void graphics_register_bitmap(rdpGraphics* graphics, rdpBitmap* bitmap); FREERDP_API void graphics_register_pointer(rdpGraphics* graphics, rdpPointer* pointer); FREERDP_API void graphics_register_glyph(rdpGraphics* graphics, rdpGlyph* glyph); FREERDP_API rdpGraphics* graphics_new(rdpContext* context); FREERDP_API void graphics_free(rdpGraphics* graphics); #endif /* __GRAPHICS_H */ FreeRDP-1.0.2/include/freerdp/input.h000066400000000000000000000045241207112532300173240ustar00rootroot00000000000000/** * FreeRDP: A Remote Desktop Protocol Client * Input Interface API * * Copyright 2011 Marc-Andre Moreau * * 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. */ #ifndef __INPUT_API_H #define __INPUT_API_H typedef struct rdp_input rdpInput; #include /* keyboard Flags */ #define KBD_FLAGS_EXTENDED 0x0100 #define KBD_FLAGS_DOWN 0x4000 #define KBD_FLAGS_RELEASE 0x8000 /* Pointer Flags */ #define PTR_FLAGS_WHEEL 0x0200 #define PTR_FLAGS_WHEEL_NEGATIVE 0x0100 #define PTR_FLAGS_MOVE 0x0800 #define PTR_FLAGS_DOWN 0x8000 #define PTR_FLAGS_BUTTON1 0x1000 #define PTR_FLAGS_BUTTON2 0x2000 #define PTR_FLAGS_BUTTON3 0x4000 #define WheelRotationMask 0x01FF /* Extended Pointer Flags */ #define PTR_XFLAGS_DOWN 0x8000 #define PTR_XFLAGS_BUTTON1 0x0001 #define PTR_XFLAGS_BUTTON2 0x0002 /* Keyboard Toggle Flags */ #define KBD_SYNC_SCROLL_LOCK 0x00000001 #define KBD_SYNC_NUM_LOCK 0x00000002 #define KBD_SYNC_CAPS_LOCK 0x00000004 #define KBD_SYNC_KANA_LOCK 0x00000008 #define RDP_CLIENT_INPUT_PDU_HEADER_LENGTH 4 typedef void (*pSynchronizeEvent)(rdpInput* input, uint32 flags); typedef void (*pKeyboardEvent)(rdpInput* input, uint16 flags, uint16 code); typedef void (*pUnicodeKeyboardEvent)(rdpInput* input, uint16 flags, uint16 code); typedef void (*pMouseEvent)(rdpInput* input, uint16 flags, uint16 x, uint16 y); typedef void (*pExtendedMouseEvent)(rdpInput* input, uint16 flags, uint16 x, uint16 y); struct rdp_input { rdpContext* context; /* 0 */ void* param1; /* 1 */ uint32 paddingA[16 - 2]; /* 2 */ pSynchronizeEvent SynchronizeEvent; /* 16 */ pKeyboardEvent KeyboardEvent; /* 17 */ pUnicodeKeyboardEvent UnicodeKeyboardEvent; /* 18 */ pMouseEvent MouseEvent; /* 19 */ pExtendedMouseEvent ExtendedMouseEvent; /* 20 */ uint32 paddingB[32 - 21]; /* 21 */ }; #endif /* __INPUT_API_H */ FreeRDP-1.0.2/include/freerdp/kbd/000077500000000000000000000000001207112532300165475ustar00rootroot00000000000000FreeRDP-1.0.2/include/freerdp/kbd/kbd.h000066400000000000000000000027071207112532300174660ustar00rootroot00000000000000/** * FreeRDP: A Remote Desktop Protocol Client * XKB-based keyboard mapping * * Copyright 2009 Marc-Andre Moreau * * 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. */ #ifndef __FREERDP_KBD_H #define __FREERDP_KBD_H #include #include #define RDP_KEYBOARD_LAYOUT_TYPE_STANDARD 1 #define RDP_KEYBOARD_LAYOUT_TYPE_VARIANT 2 #define RDP_KEYBOARD_LAYOUT_TYPE_IME 4 typedef struct rdp_keyboard_layout { uint32 code; char name[50]; } rdpKeyboardLayout; FREERDP_API rdpKeyboardLayout* freerdp_kbd_get_layouts(int types); FREERDP_API uint32 freerdp_kbd_init(void *dpy, uint32 keyboard_layout_id); FREERDP_API uint8 freerdp_kbd_get_scancode_by_keycode(uint8 keycode, boolean* extended); FREERDP_API uint8 freerdp_kbd_get_keycode_by_scancode(uint8 scancode, boolean extended); FREERDP_API uint8 freerdp_kbd_get_scancode_by_virtualkey(int vkcode, boolean* extended); #endif /* __FREERDP_KBD_H */ FreeRDP-1.0.2/include/freerdp/kbd/layouts.h000066400000000000000000000156541207112532300204330ustar00rootroot00000000000000/** * FreeRDP: A Remote Desktop Protocol Client * XKB-based Keyboard Mapping to Microsoft Keyboard System * * Copyright 2009 Marc-Andre Moreau * * 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. */ /* Keyboard layout IDs used in the RDP protocol */ #ifndef __LAYOUT_IDS_H #define __LAYOUT_IDS_H #include #include /* Keyboard layout IDs */ #define KBD_ARABIC_101 0x00000401 #define KBD_BULGARIAN 0x00000402 #define KBD_CHINESE_TRADITIONAL_US 0x00000404 #define KBD_CZECH 0x00000405 #define KBD_DANISH 0x00000406 #define KBD_GERMAN 0x00000407 #define KBD_GREEK 0x00000408 #define KBD_US 0x00000409 #define KBD_SPANISH 0x0000040A #define KBD_FINNISH 0x0000040B #define KBD_FRENCH 0x0000040C #define KBD_HEBREW 0x0000040D #define KBD_HUNGARIAN 0x0000040E #define KBD_ICELANDIC 0x0000040F #define KBD_ITALIAN 0x00000410 #define KBD_JAPANESE 0x00000411 #define KBD_KOREAN 0x00000412 #define KBD_DUTCH 0x00000413 #define KBD_NORWEGIAN 0x00000414 #define KBD_POLISH_PROGRAMMERS 0x00000415 #define KBD_PORTUGUESE_BRAZILIAN_ABNT 0x00000416 #define KBD_ROMANIAN 0x00000418 #define KBD_RUSSIAN 0x00000419 #define KBD_CROATIAN 0x0000041A #define KBD_SLOVAK 0x0000041B #define KBD_ALBANIAN 0x0000041C #define KBD_SWEDISH 0x0000041D #define KBD_THAI_KEDMANEE 0x0000041E #define KBD_TURKISH_Q 0x0000041F #define KBD_URDU 0x00000420 #define KBD_UKRAINIAN 0x00000422 #define KBD_BELARUSIAN 0x00000423 #define KBD_SLOVENIAN 0x00000424 #define KBD_ESTONIAN 0x00000425 #define KBD_LATVIAN 0x00000426 #define KBD_LITHUANIAN_IBM 0x00000427 #define KBD_FARSI 0x00000429 #define KBD_VIETNAMESE 0x0000042A #define KBD_ARMENIAN_EASTERN 0x0000042B #define KBD_AZERI_LATIN 0x0000042C #define KBD_FYRO_MACEDONIAN 0x0000042F #define KBD_GEORGIAN 0x00000437 #define KBD_FAEROESE 0x00000438 #define KBD_DEVANAGARI_INSCRIPT 0x00000439 #define KBD_MALTESE_47_KEY 0x0000043A #define KBD_NORWEGIAN_WITH_SAMI 0x0000043B #define KBD_KAZAKH 0x0000043F #define KBD_KYRGYZ_CYRILLIC 0x00000440 #define KBD_TATAR 0x00000444 #define KBD_BENGALI 0x00000445 #define KBD_PUNJABI 0x00000446 #define KBD_GUJARATI 0x00000447 #define KBD_TAMIL 0x00000449 #define KBD_TELUGU 0x0000044A #define KBD_KANNADA 0x0000044B #define KBD_MALAYALAM 0x0000044C #define KBD_MARATHI 0x0000044E #define KBD_MONGOLIAN_CYRILLIC 0x00000450 #define KBD_UNITED_KINGDOM_EXTENDED 0x00000452 #define KBD_SYRIAC 0x0000045A #define KBD_NEPALI 0x00000461 #define KBD_PASHTO 0x00000463 #define KBD_DIVEHI_PHONETIC 0x00000465 #define KBD_LUXEMBOURGISH 0x0000046E #define KBD_MAORI 0x00000481 #define KBD_CHINESE_SIMPLIFIED_US 0x00000804 #define KBD_SWISS_GERMAN 0x00000807 #define KBD_UNITED_KINGDOM 0x00000809 #define KBD_LATIN_AMERICAN 0x0000080A #define KBD_BELGIAN_FRENCH 0x0000080C #define KBD_BELGIAN_PERIOD 0x00000813 #define KBD_PORTUGUESE 0x00000816 #define KBD_SERBIAN_LATIN 0x0000081A #define KBD_AZERI_CYRILLIC 0x0000082C #define KBD_SWEDISH_WITH_SAMI 0x0000083B #define KBD_UZBEK_CYRILLIC 0x00000843 #define KBD_INUKTITUT_LATIN 0x0000085D #define KBD_CANADIAN_FRENCH_LEGACY 0x00000C0C #define KBD_SERBIAN_CYRILLIC 0x00000C1A #define KBD_CANADIAN_FRENCH 0x00001009 #define KBD_SWISS_FRENCH 0x0000100C #define KBD_BOSNIAN 0x0000141A #define KBD_IRISH 0x00001809 #define KBD_BOSNIAN_CYRILLIC 0x0000201A /* Keyboard layout variant IDs */ #define KBD_ARABIC_102 0x00010401 #define KBD_BULGARIAN_LATIN 0x00010402 #define KBD_CZECH_QWERTY 0x00010405 #define KBD_GERMAN_IBM 0x00010407 #define KBD_GREEK_220 0x00010408 #define KBD_UNITED_STATES_DVORAK 0x00010409 #define KBD_SPANISH_VARIATION 0x0001040A #define KBD_HUNGARIAN_101_KEY 0x0001040E #define KBD_ITALIAN_142 0x00010410 #define KBD_POLISH_214 0x00010415 #define KBD_PORTUGUESE_BRAZILIAN_ABNT2 0x00010416 #define KBD_RUSSIAN_TYPEWRITER 0x00010419 #define KBD_SLOVAK_QWERTY 0x0001041B #define KBD_THAI_PATTACHOTE 0x0001041E #define KBD_TURKISH_F 0x0001041F #define KBD_LATVIAN_QWERTY 0x00010426 #define KBD_LITHUANIAN 0x00010427 #define KBD_ARMENIAN_WESTERN 0x0001042B #define KBD_HINDI_TRADITIONAL 0x00010439 #define KBD_MALTESE_48_KEY 0x0001043A #define KBD_SAMI_EXTENDED_NORWAY 0x0001043B #define KBD_BENGALI_INSCRIPT 0x00010445 #define KBD_SYRIAC_PHONETIC 0x0001045A #define KBD_DIVEHI_TYPEWRITER 0x00010465 #define KBD_BELGIAN_COMMA 0x0001080C #define KBD_FINNISH_WITH_SAMI 0x0001083B #define KBD_CANADIAN_MULTILINGUAL_STANDARD 0x00011009 #define KBD_GAELIC 0x00011809 #define KBD_ARABIC_102_AZERTY 0x00020401 #define KBD_CZECH_PROGRAMMERS 0x00020405 #define KBD_GREEK_319 0x00020408 #define KBD_UNITED_STATES_INTERNATIONAL 0x00020409 #define KBD_THAI_KEDMANEE_NON_SHIFTLOCK 0x0002041E #define KBD_SAMI_EXTENDED_FINLAND_SWEDEN 0x0002083B #define KBD_GREEK_220_LATIN 0x00030408 #define KBD_UNITED_STATES_DVORAK_FOR_LEFT_HAND 0x00030409 #define KBD_THAI_PATTACHOTE_NON_SHIFTLOCK 0x0003041E #define KBD_GREEK_319_LATIN 0x00040408 #define KBD_UNITED_STATES_DVORAK_FOR_RIGHT_HAND 0x00040409 #define KBD_GREEK_LATIN 0x00050408 #define KBD_US_ENGLISH_TABLE_FOR_IBM_ARABIC_238_L 0x00050409 #define KBD_GREEK_POLYTONIC 0x00060408 #define KBD_GERMAN_NEO 0xB0000407 /* Global Input Method Editor (IME) IDs */ #define KBD_CHINESE_TRADITIONAL_PHONETIC 0xE0010404 #define KBD_JAPANESE_INPUT_SYSTEM_MS_IME2002 0xE0010411 #define KBD_KOREAN_INPUT_SYSTEM_IME_2000 0xE0010412 #define KBD_CHINESE_SIMPLIFIED_QUANPIN 0xE0010804 #define KBD_CHINESE_TRADITIONAL_CHANGJIE 0xE0020404 #define KBD_CHINESE_SIMPLIFIED_SHUANGPIN 0xE0020804 #define KBD_CHINESE_TRADITIONAL_QUICK 0xE0030404 #define KBD_CHINESE_SIMPLIFIED_ZHENGMA 0xE0030804 #define KBD_CHINESE_TRADITIONAL_BIG5_CODE 0xE0040404 #define KBD_CHINESE_TRADITIONAL_ARRAY 0xE0050404 #define KBD_CHINESE_SIMPLIFIED_NEIMA 0xE0050804 #define KBD_CHINESE_TRADITIONAL_DAYI 0xE0060404 #define KBD_CHINESE_TRADITIONAL_UNICODE 0xE0070404 #define KBD_CHINESE_TRADITIONAL_NEW_PHONETIC 0xE0080404 #define KBD_CHINESE_TRADITIONAL_NEW_CHANGJIE 0xE0090404 #define KBD_CHINESE_TRADITIONAL_MICROSOFT_PINYIN_IME_3 0xE00E0804 #define KBD_CHINESE_TRADITIONAL_ALPHANUMERIC 0xE00F0404 FREERDP_API rdpKeyboardLayout* get_keyboard_layouts(int types); FREERDP_API const char* get_layout_name(uint32 keyboardLayoutID); #endif FreeRDP-1.0.2/include/freerdp/kbd/locales.h000066400000000000000000000235031207112532300203450ustar00rootroot00000000000000/** * FreeRDP: A Remote Desktop Protocol Client * XKB-based Keyboard Mapping to Microsoft Keyboard System * * Copyright 2009 Marc-Andre Moreau * * 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. */ /* Detection of plausible keyboard layout id based on current locale (LANG) setting. */ /* * Refer to "Windows XP/Server 2003 - List of Locale IDs, Input Locale, and Language Collection": * http://www.microsoft.com/globaldev/reference/winxp/xp-lcid.mspx */ #ifndef __LOCALES_H #define __LOCALES_H #include #include #define AFRIKAANS 0x0436 #define ALBANIAN 0x041c #define ALSATIAN 0x0484 #define AMHARIC 0x045E #define ARABIC_SAUDI_ARABIA 0x0401 #define ARABIC_IRAQ 0x0801 #define ARABIC_EGYPT 0x0c01 #define ARABIC_LIBYA 0x1001 #define ARABIC_ALGERIA 0x1401 #define ARABIC_MOROCCO 0x1801 #define ARABIC_TUNISIA 0x1c01 #define ARABIC_OMAN 0x2001 #define ARABIC_YEMEN 0x2401 #define ARABIC_SYRIA 0x2801 #define ARABIC_JORDAN 0x2c01 #define ARABIC_LEBANON 0x3001 #define ARABIC_KUWAIT 0x3401 #define ARABIC_UAE 0x3801 #define ARABIC_BAHRAIN 0x3c01 #define ARABIC_QATAR 0x4001 #define ARMENIAN 0x042b #define ASSAMESE 0x044D #define AZERI_LATIN 0x042c #define AZERI_CYRILLIC 0x082c #define BASHKIR 0x046D #define BASQUE 0x042d #define BELARUSIAN 0x0423 #define BENGALI_INDIA 0x0445 #define BOSNIAN_LATIN 0x141A #define BRETON 0x047E #define BULGARIAN 0x0402 #define CATALAN 0x0403 #define CHINESE_TAIWAN 0x0404 #define CHINESE_PRC 0x0804 #define CHINESE_HONG_KONG 0x0c04 #define CHINESE_SINGAPORE 0x1004 #define CHINESE_MACAU 0x1404 #define CROATIAN 0x041a #define CROATIAN_BOSNIA_HERZEGOVINA 0x101A #define CZECH 0x0405 #define DANISH 0x0406 #define DARI 0x048C #define DIVEHI 0x0465 #define DUTCH_STANDARD 0x0413 #define DUTCH_BELGIAN 0x0813 #define ENGLISH_UNITED_STATES 0x0409 #define ENGLISH_UNITED_KINGDOM 0x0809 #define ENGLISH_AUSTRALIAN 0x0c09 #define ENGLISH_CANADIAN 0x1009 #define ENGLISH_NEW_ZEALAND 0x1409 #define ENGLISH_INDIA 0x4009 #define ENGLISH_IRELAND 0x1809 #define ENGLISH_MALAYSIA 0x4409 #define ENGLISH_SOUTH_AFRICA 0x1c09 #define ENGLISH_JAMAICA 0x2009 #define ENGLISH_CARIBBEAN 0x2409 #define ENGLISH_BELIZE 0x2809 #define ENGLISH_TRINIDAD 0x2c09 #define ENGLISH_ZIMBABWE 0x3009 #define ENGLISH_PHILIPPINES 0x3409 #define ENGLISH_SINGAPORE 0x4809 #define ESTONIAN 0x0425 #define FAEROESE 0x0438 #define FARSI 0x0429 #define FILIPINO 0x0464 #define FINNISH 0x040b #define FRENCH_STANDARD 0x040c #define FRENCH_BELGIAN 0x080c #define FRENCH_CANADIAN 0x0c0c #define FRENCH_SWISS 0x100c #define FRENCH_LUXEMBOURG 0x140c #define FRENCH_MONACO 0x180c #define FRISIAN 0x0462 #define GEORGIAN 0x0437 #define GALICIAN 0x0456 #define GERMAN_STANDARD 0x0407 #define GERMAN_SWISS 0x0807 #define GERMAN_AUSTRIAN 0x0c07 #define GERMAN_LUXEMBOURG 0x1007 #define GERMAN_LIECHTENSTEIN 0x1407 #define GREEK 0x0408 #define GREENLANDIC 0x046F #define GUJARATI 0x0447 #define HEBREW 0x040d #define HINDI 0x0439 #define HUNGARIAN 0x040e #define ICELANDIC 0x040f #define IGBO 0x0470 #define INDONESIAN 0x0421 #define IRISH 0x083C #define ITALIAN_STANDARD 0x0410 #define ITALIAN_SWISS 0x0810 #define JAPANESE 0x0411 #define KANNADA 0x044b #define KAZAKH 0x043f #define KHMER 0x0453 #define KICHE 0x0486 #define KINYARWANDA 0x0487 #define KONKANI 0x0457 #define KOREAN 0x0412 #define KYRGYZ 0x0440 #define LAO 0x0454 #define LATVIAN 0x0426 #define LITHUANIAN 0x0427 #define LOWER_SORBIAN 0x082E #define LUXEMBOURGISH 0x046E #define MACEDONIAN 0x042f #define MALAY_MALAYSIA 0x043e #define MALAY_BRUNEI_DARUSSALAM 0x083e #define MALAYALAM 0x044c #define MALTESE 0x043a #define MAPUDUNGUN 0x047A #define MAORI 0x0481 #define MARATHI 0x044e #define MOHAWK 0x047C #define MONGOLIAN 0x0450 #define NEPALI 0x0461 #define NORWEGIAN_BOKMAL 0x0414 #define NORWEGIAN_NYNORSK 0x0814 #define OCCITAN 0x0482 #define ORIYA 0x0448 #define PASHTO 0x0463 #define POLISH 0x0415 #define PORTUGUESE_BRAZILIAN 0x0416 #define PORTUGUESE_STANDARD 0x0816 #define PUNJABI 0x0446 #define QUECHUA_BOLIVIA 0x046b #define QUECHUA_ECUADOR 0x086b #define QUECHUA_PERU 0x0c6b #define ROMANIAN 0x0418 #define ROMANSH 0x0417 #define RUSSIAN 0x0419 #define SAMI_INARI 0x243b #define SAMI_LULE_NORWAY 0x103b #define SAMI_LULE_SWEDEN 0x143b #define SAMI_NORTHERN_FINLAND 0x0c3b #define SAMI_NORTHERN_NORWAY 0x043b #define SAMI_NORTHERN_SWEDEN 0x083b #define SAMI_SKOLT 0x203b #define SAMI_SOUTHERN_NORWAY 0x183b #define SAMI_SOUTHERN_SWEDEN 0x1c3b #define SANSKRIT 0x044f #define SERBIAN_LATIN 0x081a #define SERBIAN_LATIN_BOSNIA_HERZEGOVINA 0x181a #define SERBIAN_CYRILLIC 0x0c1a #define SERBIAN_CYRILLIC_BOSNIA_HERZEGOVINA 0x1c1a #define SESOTHO_SA_LEBOA 0x046C #define SINHALA 0x045B #define SLOVAK 0x041b #define SLOVENIAN 0x0424 #define SPANISH_TRADITIONAL_SORT 0x040a #define SPANISH_MEXICAN 0x080a #define SPANISH_MODERN_SORT 0x0c0a #define SPANISH_GUATEMALA 0x100a #define SPANISH_COSTA_RICA 0x140a #define SPANISH_PANAMA 0x180a #define SPANISH_DOMINICAN_REPUBLIC 0x1c0a #define SPANISH_VENEZUELA 0x200a #define SPANISH_COLOMBIA 0x240a #define SPANISH_PERU 0x280a #define SPANISH_ARGENTINA 0x2c0a #define SPANISH_ECUADOR 0x300a #define SPANISH_CHILE 0x340a #define SPANISH_UNITED_STATES 0x540A #define SPANISH_URUGUAY 0x380a #define SPANISH_PARAGUAY 0x3c0a #define SPANISH_BOLIVIA 0x400a #define SPANISH_EL_SALVADOR 0x440a #define SPANISH_HONDURAS 0x480a #define SPANISH_NICARAGUA 0x4c0a #define SPANISH_PUERTO_RICO 0x500a #define SWAHILI 0x0441 #define SWEDISH 0x041d #define SWEDISH_FINLAND 0x081d #define SYRIAC 0x045a #define TAMIL 0x0449 #define TATAR 0x0444 #define TELUGU 0x044a #define THAI 0x041e #define TIBETAN_BHUTAN 0x0851 #define TIBETAN_PRC 0x0451 #define TSWANA 0x0432 #define UKRAINIAN 0x0422 #define TURKISH 0x041f #define TURKMEN 0x0442 #define UIGHUR 0x0480 #define UPPER_SORBIAN 0x042E #define URDU 0x0420 #define URDU_INDIA 0x0820 #define UZBEK_LATIN 0x0443 #define UZBEK_CYRILLIC 0x0843 #define VIETNAMESE 0x042a #define WELSH 0x0452 #define WOLOF 0x0488 #define XHOSA 0x0434 #define YAKUT 0x0485 #define YI 0x0478 #define YORUBA 0x046A #define ZULU 0x0435 /* Time zones, taken from Windows Server 2008 (GMT -12:00) International Date Line West (GMT -11:00) Midway Island, Samoa (GMT -10:00) Hawaii (GMT -09:00) Alaska (GMT -08:00) Pacific Time (US & Canada) (GMT -08:00) Tijuana, Baja California (GMT -07:00) Arizona (GMT -07:00) Chihuahua, La Paz, Mazatlan (GMT -07:00) Mountain Time (US & Canada) (GMT -06:00) Central America (GMT -06:00) Central Time (US & Canada) (GMT -06:00) Guadalajara, Mexico City, Monterrey (GMT -06:00) Saskatchewan (GMT -05:00) Bogota, Lima, Quito, Rio Branco (GMT -05:00) Eastern Time (US & Canada) (GMT -05:00) Indiana (East) (GMT -04:30) Caracas (GMT -04:00) Atlantic Time (Canada) (GMT -04:00) La Paz (GMT -04:00) Manaus (GMT -04:00) Santiago (GMT -03:30) Newfoundland (GMT -03:00) Brasilia (GMT -03:00) Buenos Aires (GMT -03:00) Georgetown (GMT -03:00) Greenland (GMT -03:00) Montevideo (GMT -02:00) Mid-Atlantic (GMT -01:00) Azores (GMT -01:00) Cape Verde Is. (GMT +00:00) Casablanca (GMT +00:00) Greenwich Mean Time: Dublin, Edinburgh, Lisbon, London (GMT +00:00) Monrovia, Reykjavik (GMT +01:00) Amsterdam, Berlin, Bern, Rome, Stockholm, Vienna (GMT +01:00) Belgrade, Bratislava, Budapest, Ljubljana, Prague (GMT +01:00) Brussels, Copenhagen, Madrid, Paris (GMT +01:00) Sarajevo, Skopje, Warsaw, Zagreb (GMT +01:00) West Central Africa (GMT +02:00) Amman (GMT +02:00) Athens, Bucharest, Istanbul (GMT +02:00) Beirut (GMT +02:00) Cairo (GMT +02:00) Harare, Pretoria (GMT +02:00) Helsinki, Kyiv, Riga, Sofia, Tallinn, Vilnius (GMT +02:00) Jerusalem (GMT +02:00) Minsk (GMT +02:00) Windhoek (GMT +03:00) Baghdad (GMT +03:00) Kuwait, Riyadh (GMT +03:00) Moscow, St. Petersburg, Volgograd (GMT +03:00) Nairobi (GMT +03:00) Tbilisi (GMT +03:30) Tehran (GMT +04:00) Abu Dhabi, Muscat (GMT +04:00) Baku (GMT +04:00) Port Louis (GMT +04:00) Yerevan (GMT +04:30) Kabul (GMT +05:00) Ekaterinburg (GMT +05:00) Islamabad, Karachi (GMT +05:00) Tashkent (GMT +05:30) Chennai, Kolkata, Mumbai, New Delhi (GMT +05:30) Sri Jayawardenepura (GMT +05:45) Kathmandu (GMT +06:00) Almaty, Novosibirsk (GMT +06:00) Astana, Dhaka (GMT +06:30) Yangon (Rangoon) (GMT +07:00) Bangkok, Hanoi, Jakarta (GMT +07:00) Krasnoyarsk (GMT +08:00) Beijing, Chongqing, Hong Kong, Urumqi (GMT +08:00) Irkutsk, Ulaan Bataar (GMT +08:00) Kuala Lumpur, Singapore (GMT +08:00) Perth (GMT +08:00) Taipei (GMT +09:00) Osaka, Sapporo, Tokyo (GMT +09:00) Seoul (GMT +09:00) Yakutsk (GMT +09:30) Adelaide (GMT +09:30) Darwin (GMT +10:00) Brisbane (GMT +10:00) Canberra, Melbourne, Sydney (GMT +10:00) Guam, Port Moresby (GMT +10:00) Hobart, Vladivostok (GMT +11:00) Magadan, Solomon Is., New Caledonia (GMT +12:00) Auckland, Wellington (GMT +12:00) Fiji, Kamchatka, Marshall Is. (GMT +13:00) Nuku'alofa */ FREERDP_API uint32 detect_keyboard_layout_from_locale(); #endif /* __LOCALES_H */ FreeRDP-1.0.2/include/freerdp/kbd/vkcodes.h000066400000000000000000000564071207112532300203720ustar00rootroot00000000000000/** * FreeRDP: A Remote Desktop Protocol Client * Microsoft Virtual Key Code Definitions and Conversion Tables * * Copyright 2009 Marc-Andre Moreau * * 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. */ /* Microsoft Windows Virtual Key Codes: http://msdn.microsoft.com/en-us/library/ms645540.aspx */ #ifndef __VKCODES_H #define __VKCODES_H #include #include #include /* Mouse buttons */ #define VK_LBUTTON 0x01 /* Left mouse button */ #define VK_RBUTTON 0x02 /* Right mouse button */ #define VK_CANCEL 0x03 /* Control-break processing */ #define VK_MBUTTON 0x04 /* Middle mouse button (three-button mouse) */ #define VK_XBUTTON1 0x05 /* Windows 2000/XP: X1 mouse button */ #define VK_XBUTTON2 0x06 /* Windows 2000/XP: X2 mouse button */ /* 0x07 is undefined */ #define VK_BACK 0x08 /* BACKSPACE key */ #define VK_TAB 0x09 /* TAB key */ /* 0x0A to 0x0B are reserved */ #define VK_CLEAR 0x0C /* CLEAR key */ #define VK_RETURN 0x0D /* ENTER key */ /* 0x0E to 0x0F are undefined */ #define VK_SHIFT 0x10 /* SHIFT key */ #define VK_CONTROL 0x11 /* CTRL key */ #define VK_MENU 0x12 /* ALT key */ #define VK_PAUSE 0x13 /* PAUSE key */ #define VK_CAPITAL 0x14 /* CAPS LOCK key */ #define VK_KANA 0x15 /* Input Method Editor (IME) Kana mode */ #define VK_HANGUEL 0x15 /* IME Hanguel mode (maintained for compatibility; use #define VK_HANGUL) */ #define VK_HANGUL 0x15 /* IME Hangul mode */ /* 0x16 is undefined */ #define VK_JUNJA 0x17 /* IME Junja mode */ #define VK_FINAL 0x18 /* IME final mode */ #define VK_HANJA 0x19 /* IME Hanja mode */ #define VK_KANJI 0x19 /* IME Kanji mode */ /* 0x1A is undefined */ #define VK_ESCAPE 0x1B /* ESC key */ #define VK_CONVERT 0x1C /* IME convert */ #define VK_NONCONVERT 0x1D /* IME nonconvert */ #define VK_ACCEPT 0x1E /* IME accept */ #define VK_MODECHANGE 0x1F /* IME mode change request */ #define VK_SPACE 0x20 /* SPACEBAR */ #define VK_PRIOR 0x21 /* PAGE UP key */ #define VK_NEXT 0x22 /* PAGE DOWN key */ #define VK_END 0x23 /* END key */ #define VK_HOME 0x24 /* HOME key */ #define VK_LEFT 0x25 /* LEFT ARROW key */ #define VK_UP 0x26 /* UP ARROW key */ #define VK_RIGHT 0x27 /* RIGHT ARROW key */ #define VK_DOWN 0x28 /* DOWN ARROW key */ #define VK_SELECT 0x29 /* SELECT key */ #define VK_PRINT 0x2A /* PRINT key */ #define VK_EXECUTE 0x2B /* EXECUTE key */ #define VK_SNAPSHOT 0x2C /* PRINT SCREEN key */ #define VK_INSERT 0x2D /* INS key */ #define VK_DELETE 0x2E /* DEL key */ #define VK_HELP 0x2F /* HELP key */ /* Digits, the last 4 bits of the code represent the corresponding digit */ #define VK_KEY_0 0x30 /* '0' key */ #define VK_KEY_1 0x31 /* '1' key */ #define VK_KEY_2 0x32 /* '2' key */ #define VK_KEY_3 0x33 /* '3' key */ #define VK_KEY_4 0x34 /* '4' key */ #define VK_KEY_5 0x35 /* '5' key */ #define VK_KEY_6 0x36 /* '6' key */ #define VK_KEY_7 0x37 /* '7' key */ #define VK_KEY_8 0x38 /* '8' key */ #define VK_KEY_9 0x39 /* '9' key */ /* 0x3A to 0x40 are undefined */ /* The alphabet, the code corresponds to the capitalized letter in the ASCII code */ #define VK_KEY_A 0x41 /* 'A' key */ #define VK_KEY_B 0x42 /* 'B' key */ #define VK_KEY_C 0x43 /* 'C' key */ #define VK_KEY_D 0x44 /* 'D' key */ #define VK_KEY_E 0x45 /* 'E' key */ #define VK_KEY_F 0x46 /* 'F' key */ #define VK_KEY_G 0x47 /* 'G' key */ #define VK_KEY_H 0x48 /* 'H' key */ #define VK_KEY_I 0x49 /* 'I' key */ #define VK_KEY_J 0x4A /* 'J' key */ #define VK_KEY_K 0x4B /* 'K' key */ #define VK_KEY_L 0x4C /* 'L' key */ #define VK_KEY_M 0x4D /* 'M' key */ #define VK_KEY_N 0x4E /* 'N' key */ #define VK_KEY_O 0x4F /* 'O' key */ #define VK_KEY_P 0x50 /* 'P' key */ #define VK_KEY_Q 0x51 /* 'Q' key */ #define VK_KEY_R 0x52 /* 'R' key */ #define VK_KEY_S 0x53 /* 'S' key */ #define VK_KEY_T 0x54 /* 'T' key */ #define VK_KEY_U 0x55 /* 'U' key */ #define VK_KEY_V 0x56 /* 'V' key */ #define VK_KEY_W 0x57 /* 'W' key */ #define VK_KEY_X 0x58 /* 'X' key */ #define VK_KEY_Y 0x59 /* 'Y' key */ #define VK_KEY_Z 0x5A /* 'Z' key */ #define VK_LWIN 0x5B /* Left Windows key (Microsoft Natural keyboard) */ #define VK_RWIN 0x5C /* Right Windows key (Natural keyboard) */ #define VK_APPS 0x5D /* Applications key (Natural keyboard) */ /* 0x5E is reserved */ #define VK_SLEEP 0x5F /* Computer Sleep key */ /* Numeric keypad digits, the last four bits of the code represent the corresponding digit */ #define VK_NUMPAD0 0x60 /* Numeric keypad '0' key */ #define VK_NUMPAD1 0x61 /* Numeric keypad '1' key */ #define VK_NUMPAD2 0x62 /* Numeric keypad '2' key */ #define VK_NUMPAD3 0x63 /* Numeric keypad '3' key */ #define VK_NUMPAD4 0x64 /* Numeric keypad '4' key */ #define VK_NUMPAD5 0x65 /* Numeric keypad '5' key */ #define VK_NUMPAD6 0x66 /* Numeric keypad '6' key */ #define VK_NUMPAD7 0x67 /* Numeric keypad '7' key */ #define VK_NUMPAD8 0x68 /* Numeric keypad '8' key */ #define VK_NUMPAD9 0x69 /* Numeric keypad '9' key */ /* Numeric keypad operators and special keys */ #define VK_MULTIPLY 0x6A /* Multiply key */ #define VK_ADD 0x6B /* Add key */ #define VK_SEPARATOR 0x6C /* Separator key */ #define VK_SUBTRACT 0x6D /* Subtract key */ #define VK_DECIMAL 0x6E /* Decimal key */ #define VK_DIVIDE 0x6F /* Divide key */ /* Function keys, from F1 to F24 */ #define VK_F1 0x70 /* F1 key */ #define VK_F2 0x71 /* F2 key */ #define VK_F3 0x72 /* F3 key */ #define VK_F4 0x73 /* F4 key */ #define VK_F5 0x74 /* F5 key */ #define VK_F6 0x75 /* F6 key */ #define VK_F7 0x76 /* F7 key */ #define VK_F8 0x77 /* F8 key */ #define VK_F9 0x78 /* F9 key */ #define VK_F10 0x79 /* F10 key */ #define VK_F11 0x7A /* F11 key */ #define VK_F12 0x7B /* F12 key */ #define VK_F13 0x7C /* F13 key */ #define VK_F14 0x7D /* F14 key */ #define VK_F15 0x7E /* F15 key */ #define VK_F16 0x7F /* F16 key */ #define VK_F17 0x80 /* F17 key */ #define VK_F18 0x81 /* F18 key */ #define VK_F19 0x82 /* F19 key */ #define VK_F20 0x83 /* F20 key */ #define VK_F21 0x84 /* F21 key */ #define VK_F22 0x85 /* F22 key */ #define VK_F23 0x86 /* F23 key */ #define VK_F24 0x87 /* F24 key */ /* 0x88 to 0x8F are unassigned */ #define VK_NUMLOCK 0x90 /* NUM LOCK key */ #define VK_SCROLL 0x91 /* SCROLL LOCK key */ /* 0x92 to 0x96 are OEM specific */ /* 0x97 to 0x9F are unassigned */ /* Modifier keys */ #define VK_LSHIFT 0xA0 /* Left SHIFT key */ #define VK_RSHIFT 0xA1 /* Right SHIFT key */ #define VK_LCONTROL 0xA2 /* Left CONTROL key */ #define VK_RCONTROL 0xA3 /* Right CONTROL key */ #define VK_LMENU 0xA4 /* Left MENU key */ #define VK_RMENU 0xA5 /* Right MENU key */ /* Browser related keys */ #define VK_BROWSER_BACK 0xA6 /* Windows 2000/XP: Browser Back key */ #define VK_BROWSER_FORWARD 0xA7 /* Windows 2000/XP: Browser Forward key */ #define VK_BROWSER_REFRESH 0xA8 /* Windows 2000/XP: Browser Refresh key */ #define VK_BROWSER_STOP 0xA9 /* Windows 2000/XP: Browser Stop key */ #define VK_BROWSER_SEARCH 0xAA /* Windows 2000/XP: Browser Search key */ #define VK_BROWSER_FAVORITES 0xAB /* Windows 2000/XP: Browser Favorites key */ #define VK_BROWSER_HOME 0xAC /* Windows 2000/XP: Browser Start and Home key */ /* Volume related keys */ #define VK_VOLUME_MUTE 0xAD /* Windows 2000/XP: Volume Mute key */ #define VK_VOLUME_DOWN 0xAE /* Windows 2000/XP: Volume Down key */ #define VK_VOLUME_UP 0xAF /* Windows 2000/XP: Volume Up key */ /* Media player related keys */ #define VK_MEDIA_NEXT_TRACK 0xB0 /* Windows 2000/XP: Next Track key */ #define VK_MEDIA_PREV_TRACK 0xB1 /* Windows 2000/XP: Previous Track key */ #define VK_MEDIA_STOP 0xB2 /* Windows 2000/XP: Stop Media key */ #define VK_MEDIA_PLAY_PAUSE 0xB3 /* Windows 2000/XP: Play/Pause Media key */ /* Application launcher keys */ #define VK_LAUNCH_MAIL 0xB4 /* Windows 2000/XP: Start Mail key */ #define VK_LAUNCH_MEDIA_SELECT 0xB5 /* Windows 2000/XP: Select Media key */ #define VK_LAUNCH_APP1 0xB6 /* Windows 2000/XP: Start Application 1 key */ #define VK_LAUNCH_APP2 0xB7 /* Windows 2000/XP: Start Application 2 key */ /* 0xB8 and 0xB9 are reserved */ /* OEM keys */ #define VK_OEM_1 0xBA /* Used for miscellaneous characters; it can vary by keyboard. */ /* Windows 2000/XP: For the US standard keyboard, the ';:' key */ #define VK_OEM_PLUS 0xBB /* Windows 2000/XP: For any country/region, the '+' key */ #define VK_OEM_COMMA 0xBC /* Windows 2000/XP: For any country/region, the ',' key */ #define VK_OEM_MINUS 0xBD /* Windows 2000/XP: For any country/region, the '-' key */ #define VK_OEM_PERIOD 0xBE /* Windows 2000/XP: For any country/region, the '.' key */ #define VK_OEM_2 0xBF /* Used for miscellaneous characters; it can vary by keyboard. */ /* Windows 2000/XP: For the US standard keyboard, the '/?' key */ #define VK_OEM_3 0xC0 /* Used for miscellaneous characters; it can vary by keyboard. */ /* Windows 2000/XP: For the US standard keyboard, the '`~' key */ /* 0xC1 to 0xD7 are reserved */ #define VK_ABNT_C1 0xC1 /* Brazilian (ABNT) Keyboard */ #define VK_ABNT_C2 0xC2 /* Brazilian (ABNT) Keyboard */ /* 0xD8 to 0xDA are unassigned */ #define VK_OEM_4 0xDB /* Used for miscellaneous characters; it can vary by keyboard. */ /* Windows 2000/XP: For the US standard keyboard, the '[{' key */ #define VK_OEM_5 0xDC /* Used for miscellaneous characters; it can vary by keyboard. */ /* Windows 2000/XP: For the US standard keyboard, the '\|' key */ #define VK_OEM_6 0xDD /* Used for miscellaneous characters; it can vary by keyboard. */ /* Windows 2000/XP: For the US standard keyboard, the ']}' key */ #define VK_OEM_7 0xDE /* Used for miscellaneous characters; it can vary by keyboard. */ /* Windows 2000/XP: For the US standard keyboard, the 'single-quote/double-quote' key */ #define VK_OEM_8 0xDF /* Used for miscellaneous characters; it can vary by keyboard. */ /* 0xE0 is reserved */ /* 0xE1 is OEM specific */ #define VK_OEM_102 0xE2 /* Windows 2000/XP: Either the angle bracket key or */ /* the backslash key on the RT 102-key keyboard */ /* 0xE3 and 0xE4 are OEM specific */ #define VK_PROCESSKEY 0xE5 /* Windows 95/98/Me, Windows NT 4.0, Windows 2000/XP: IME PROCESS key */ /* 0xE6 is OEM specific */ #define VK_PACKET 0xE7 /* Windows 2000/XP: Used to pass Unicode characters as if they were keystrokes. */ /* The #define VK_PACKET key is the low word of a 32-bit Virtual Key value used */ /* for non-keyboard input methods. For more information, */ /* see Remark in KEYBDINPUT, SendInput, WM_KEYDOWN, and WM_KEYUP */ /* 0xE8 is unassigned */ /* 0xE9 to 0xF5 are OEM specific */ #define VK_ATTN 0xF6 /* Attn key */ #define VK_CRSEL 0xF7 /* CrSel key */ #define VK_EXSEL 0xF8 /* ExSel key */ #define VK_EREOF 0xF9 /* Erase EOF key */ #define VK_PLAY 0xFA /* Play key */ #define VK_ZOOM 0xFB /* Zoom key */ #define VK_NONAME 0xFC /* Reserved */ #define VK_PA1 0xFD /* PA1 key */ #define VK_OEM_CLEAR 0xFE /* Clear key */ /* Use the virtual key code as an index in this array in order to get its associated scan code */ typedef struct _virtualKey { /* Windows "scan code", aka keycode in RDP */ unsigned char scancode; /* Windows "extended" flag, boolean */ unsigned char extended; /* Windows virtual key name */ char *name; /* XKB keyname */ char *x_keyname; } virtualKey; static const virtualKey virtualKeyboard[256 + 2] = { { 0x00, 0, "" , NULL }, { 0x00, 0, "VK_LBUTTON" , NULL }, { 0x00, 0, "VK_RBUTTON" , NULL }, { 0x00, 0, "VK_CANCEL" , NULL }, { 0x00, 0, "VK_MBUTTON" , NULL }, { 0x00, 0, "VK_XBUTTON1" , NULL }, { 0x00, 0, "VK_XBUTTON2" , NULL }, { 0x00, 0, "" , NULL }, { 0x0E, 0, "VK_BACK" , "BKSP" }, { 0x0F, 0, "VK_TAB" , "TAB" }, { 0x00, 0, "" , NULL }, { 0x00, 0, "" , NULL }, { 0x00, 0, "VK_CLEAR" , NULL }, { 0x1C, 0, "VK_RETURN" , "RTRN" }, { 0x00, 0, "" , NULL }, { 0x00, 0, "" , NULL }, { 0x2A, 0, "VK_SHIFT" , "LFSH" }, { 0x00, 0, "VK_CONTROL" , NULL }, { 0x38, 0, "VK_MENU" , "LALT" }, { 0x46, 1, "VK_PAUSE" , "PAUS" }, { 0x3A, 0, "VK_CAPITAL" , "CAPS" }, { 0x72, 0, "VK_KANA / VK_HANGUL" , NULL }, { 0x00, 0, "" , NULL }, { 0x00, 0, "VK_JUNJA" , NULL }, { 0x00, 0, "VK_FINAL" , NULL }, { 0x71, 0, "VK_HANJA / VK_KANJI" , NULL }, { 0x00, 0, "" , NULL }, { 0x01, 0, "VK_ESCAPE" , "ESC" }, { 0x00, 0, "VK_CONVERT" , NULL }, { 0x00, 0, "VK_NONCONVERT" , NULL }, { 0x00, 0, "VK_ACCEPT" , NULL }, { 0x00, 0, "VK_MODECHANGE" , NULL }, { 0x39, 0, "VK_SPACE" , "SPCE" }, { 0x49, 1, "VK_PRIOR" , "PGUP" }, { 0x51, 1, "VK_NEXT" , "PGDN" }, { 0x4F, 1, "VK_END" , "END" }, { 0x47, 1, "VK_HOME" , "HOME" }, { 0x4B, 1, "VK_LEFT" , "LEFT" }, { 0x48, 1, "VK_UP" , "UP" }, { 0x4D, 1, "VK_RIGHT" , "RGHT" }, { 0x50, 1, "VK_DOWN" , "DOWN" }, { 0x00, 0, "VK_SELECT" , NULL }, { 0x37, 1, "VK_PRINT" , "PRSC" }, { 0x37, 1, "VK_EXECUTE" , NULL }, { 0x37, 1, "VK_SNAPSHOT" , NULL }, { 0x52, 1, "VK_INSERT" , "INS" }, { 0x53, 1, "VK_DELETE" , "DELE" }, { 0x63, 0, "VK_HELP" , NULL }, { 0x0B, 0, "VK_KEY_0" , "AE10" }, { 0x02, 0, "VK_KEY_1" , "AE01" }, { 0x03, 0, "VK_KEY_2" , "AE02" }, { 0x04, 0, "VK_KEY_3" , "AE03" }, { 0x05, 0, "VK_KEY_4" , "AE04" }, { 0x06, 0, "VK_KEY_5" , "AE05" }, { 0x07, 0, "VK_KEY_6" , "AE06" }, { 0x08, 0, "VK_KEY_7" , "AE07" }, { 0x09, 0, "VK_KEY_8" , "AE08" }, { 0x0A, 0, "VK_KEY_9" , "AE09" }, { 0x00, 0, "" , NULL }, { 0x00, 0, "" , NULL }, { 0x00, 0, "" , NULL }, { 0x00, 0, "" , NULL }, { 0x00, 0, "" , NULL }, { 0x00, 0, "" , NULL }, { 0x00, 0, "" , NULL }, { 0x1E, 0, "VK_KEY_A" , "AC01" }, { 0x30, 0, "VK_KEY_B" , "AB05" }, { 0x2E, 0, "VK_KEY_C" , "AB03" }, { 0x20, 0, "VK_KEY_D" , "AC03" }, { 0x12, 0, "VK_KEY_E" , "AD03" }, { 0x21, 0, "VK_KEY_F" , "AC04" }, { 0x22, 0, "VK_KEY_G" , "AC05" }, { 0x23, 0, "VK_KEY_H" , "AC06" }, { 0x17, 0, "VK_KEY_I" , "AD08" }, { 0x24, 0, "VK_KEY_J" , "AC07" }, { 0x25, 0, "VK_KEY_K" , "AC08" }, { 0x26, 0, "VK_KEY_L" , "AC09" }, { 0x32, 0, "VK_KEY_M" , "AB07" }, { 0x31, 0, "VK_KEY_N" , "AB06" }, { 0x18, 0, "VK_KEY_O" , "AD09" }, { 0x19, 0, "VK_KEY_P" , "AD10" }, { 0x10, 0, "VK_KEY_Q" , "AD01" }, { 0x13, 0, "VK_KEY_R" , "AD04" }, { 0x1F, 0, "VK_KEY_S" , "AC02" }, { 0x14, 0, "VK_KEY_T" , "AD05" }, { 0x16, 0, "VK_KEY_U" , "AD07" }, { 0x2F, 0, "VK_KEY_V" , "AB04" }, { 0x11, 0, "VK_KEY_W" , "AD02" }, { 0x2D, 0, "VK_KEY_X" , "AB02" }, { 0x15, 0, "VK_KEY_Y" , "AD06" }, { 0x2C, 0, "VK_KEY_Z" , "AB01" }, { 0x5B, 1, "VK_LWIN" , "LWIN" }, { 0x5C, 1, "VK_RWIN" , "RWIN" }, { 0x5D, 1, "VK_APPS" , "COMP" }, { 0x00, 0, "" , NULL }, { 0x5F, 0, "VK_SLEEP" , NULL }, { 0x52, 0, "VK_NUMPAD0" , "KP0" }, { 0x4F, 0, "VK_NUMPAD1" , "KP1" }, { 0x50, 0, "VK_NUMPAD2" , "KP2" }, { 0x51, 0, "VK_NUMPAD3" , "KP3" }, { 0x4B, 0, "VK_NUMPAD4" , "KP4" }, { 0x4C, 0, "VK_NUMPAD5" , "KP5" }, { 0x4D, 0, "VK_NUMPAD6" , "KP6" }, { 0x47, 0, "VK_NUMPAD7" , "KP7" }, { 0x48, 0, "VK_NUMPAD8" , "KP8" }, { 0x49, 0, "VK_NUMPAD9" , "KP9" }, { 0x37, 0, "VK_MULTIPLY" , "KPMU" }, { 0x4E, 0, "VK_ADD" , "KPAD" }, { 0x00, 0, "VK_SEPARATOR" , NULL }, { 0x4A, 0, "VK_SUBTRACT" , "KPSU" }, { 0x53, 0, "VK_DECIMAL" , "KPDL" }, { 0x35, 0, "VK_DIVIDE" , "KPDV" }, { 0x3B, 0, "VK_F1" , "FK01" }, { 0x3C, 0, "VK_F2" , "FK02" }, { 0x3D, 0, "VK_F3" , "FK03" }, { 0x3E, 0, "VK_F4" , "FK04" }, { 0x3F, 0, "VK_F5" , "FK05" }, { 0x40, 0, "VK_F6" , "FK06" }, { 0x41, 0, "VK_F7" , "FK07" }, { 0x42, 0, "VK_F8" , "FK08" }, { 0x43, 0, "VK_F9" , "FK09" }, { 0x44, 0, "VK_F10" , "FK10" }, { 0x57, 0, "VK_F11" , "FK11" }, { 0x58, 0, "VK_F12" , "FK12" }, { 0x64, 0, "VK_F13" , NULL }, { 0x65, 0, "VK_F14" , NULL }, { 0x66, 0, "VK_F15" , NULL }, { 0x67, 0, "VK_F16" , NULL }, { 0x68, 0, "VK_F17" , NULL }, { 0x69, 0, "VK_F18" , NULL }, { 0x6A, 0, "VK_F19" , NULL }, { 0x6B, 0, "VK_F20" , NULL }, { 0x6C, 0, "VK_F21" , NULL }, { 0x6D, 0, "VK_F22" , NULL }, { 0x6E, 0, "VK_F23" , NULL }, { 0x6F, 0, "VK_F24" , NULL }, { 0x00, 0, "" , NULL }, { 0x00, 0, "" , NULL }, { 0x00, 0, "" , NULL }, { 0x00, 0, "" , NULL }, { 0x00, 0, "" , NULL }, { 0x00, 0, "" , NULL }, { 0x00, 0, "" , NULL }, { 0x00, 0, "" , NULL }, { 0x45, 0, "VK_NUMLOCK" , "NMLK" }, { 0x46, 0, "VK_SCROLL" , "SCLK" }, { 0x00, 0, "" , NULL }, { 0x00, 0, "" , NULL }, { 0x00, 0, "" , NULL }, { 0x00, 0, "" , NULL }, { 0x00, 0, "" , NULL }, { 0x00, 0, "" , NULL }, { 0x00, 0, "" , NULL }, { 0x00, 0, "" , NULL }, { 0x00, 0, "" , NULL }, { 0x00, 0, "" , NULL }, { 0x00, 0, "" , NULL }, { 0x00, 0, "" , NULL }, { 0x00, 0, "" , NULL }, { 0x00, 0, "" , NULL }, { 0x2A, 0, "VK_LSHIFT" , NULL }, { 0x36, 0, "VK_RSHIFT" , "RTSH" }, { 0x1D, 0, "VK_LCONTROL" , "LCTL" }, { 0x1D, 1, "VK_RCONTROL" , "RCTL" }, { 0x38, 0, "VK_LMENU" , NULL }, { 0x38, 1, "VK_RMENU" , "RALT" }, { 0x00, 0, "VK_BROWSER_BACK" , NULL }, { 0x00, 0, "VK_BROWSER_FORWARD" , NULL }, { 0x00, 0, "VK_BROWSER_REFRESH" , NULL }, { 0x00, 0, "VK_BROWSER_STOP" , NULL }, { 0x00, 0, "VK_BROWSER_SEARCH" , NULL }, { 0x00, 0, "VK_BROWSER_FAVORITES", NULL }, { 0x00, 0, "VK_BROWSER_HOME" , NULL }, { 0x00, 0, "VK_VOLUME_MUTE" , NULL }, { 0x00, 0, "VK_VOLUME_DOWN" , NULL }, { 0x00, 0, "VK_VOLUME_UP" , NULL }, { 0x00, 0, "VK_MEDIA_NEXT_TRACK" , NULL }, { 0x00, 0, "VK_MEDIA_PREV_TRACK" , NULL }, { 0x00, 0, "VK_MEDIA_STOP" , NULL }, { 0x00, 0, "VK_MEDIA_PLAY_PAUSE" , NULL }, { 0x00, 0, "VK_LAUNCH_MAIL" , NULL }, { 0x00, 0, "VK_MEDIA_SELECT" , NULL }, { 0x00, 0, "VK_LAUNCH_APP1" , NULL }, { 0x00, 0, "VK_LAUNCH_APP2" , NULL }, { 0x00, 0, "" , NULL }, { 0x00, 0, "" , NULL }, { 0x27, 0, "VK_OEM_1" , "AC10" }, { 0x0D, 0, "VK_OEM_PLUS" , "AE12" }, { 0x33, 0, "VK_OEM_COMMA" , "AB08" }, { 0x0C, 0, "VK_OEM_MINUS" , "AE11" }, { 0x34, 0, "VK_OEM_PERIOD" , "AB09" }, { 0x35, 0, "VK_OEM_2" , "AB10" }, { 0x29, 0, "VK_OEM_3" , "TLDE" }, { 0x73, 0, "VK_ABNT_C1" , "AB11" }, { 0x7E, 0, "VK_ABNT_C2" , "I129" }, { 0x00, 0, "" , NULL }, { 0x00, 0, "" , NULL }, { 0x00, 0, "" , NULL }, { 0x00, 0, "" , NULL }, { 0x00, 0, "" , NULL }, { 0x00, 0, "" , NULL }, { 0x00, 0, "" , NULL }, { 0x00, 0, "" , NULL }, { 0x00, 0, "" , NULL }, { 0x00, 0, "" , NULL }, { 0x00, 0, "" , NULL }, { 0x00, 0, "" , NULL }, { 0x00, 0, "" , NULL }, { 0x00, 0, "" , NULL }, { 0x00, 0, "" , NULL }, { 0x00, 0, "" , NULL }, { 0x00, 0, "" , NULL }, { 0x00, 0, "" , NULL }, { 0x00, 0, "" , NULL }, { 0x00, 0, "" , NULL }, { 0x00, 0, "" , NULL }, { 0x00, 0, "" , NULL }, { 0x00, 0, "" , NULL }, { 0x00, 0, "" , NULL }, { 0x1A, 0, "VK_OEM_4" , "AD11" }, { 0x2B, 0, "VK_OEM_5" , "BKSL" }, { 0x1B, 0, "VK_OEM_6" , "AD12" }, { 0x28, 0, "VK_OEM_7" , "AC11" }, { 0x1D, 0, "VK_OEM_8" , NULL }, { 0x00, 0, "" , NULL }, { 0x00, 0, "" , NULL }, { 0x56, 0, "VK_OEM_102" , "LSGT" }, { 0x00, 0, "" , NULL }, { 0x00, 0, "" , NULL }, { 0x00, 0, "VK_PROCESSKEY" , NULL }, { 0x00, 0, "" , NULL }, { 0x00, 0, "VK_PACKET" , NULL }, { 0x00, 0, "" , NULL }, { 0x00, 0, "" , NULL }, { 0x00, 0, "" , NULL }, { 0x00, 0, "" , NULL }, { 0x00, 0, "" , NULL }, { 0x00, 0, "" , NULL }, { 0x00, 0, "" , NULL }, { 0x00, 0, "" , NULL }, { 0x00, 0, "" , NULL }, { 0x00, 0, "" , NULL }, { 0x00, 0, "" , NULL }, { 0x00, 0, "" , NULL }, { 0x00, 0, "" , NULL }, { 0x00, 0, "" , NULL }, { 0x00, 0, "VK_ATTN" , NULL }, { 0x00, 0, "VK_CRSEL" , NULL }, { 0x00, 0, "VK_EXSEL" , NULL }, { 0x00, 0, "VK_EREOF" , NULL }, { 0x00, 0, "VK_PLAY" , NULL }, { 0x62, 0, "VK_ZOOM" , NULL }, { 0x00, 0, "VK_NONAME" , NULL }, { 0x00, 0, "VK_PA1" , NULL }, { 0x00, 0, "VK_OEM_CLEAR" , NULL }, { 0x00, 0, "" , NULL }, /* end of 256 VK entries */ { 0x54, 0, "" , "LVL3" }, { 0x1C, 1, "" , "KPEN" }, }; #endif /* __VKCODES_H */ FreeRDP-1.0.2/include/freerdp/listener.h000066400000000000000000000034341207112532300200110ustar00rootroot00000000000000/** * FreeRDP: A Remote Desktop Protocol client. * RDP Server Listener * * Copyright 2011 Vic Lee * * 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. */ #ifndef __FREERDP_LISTENER_H #define __FREERDP_LISTENER_H typedef struct rdp_freerdp_listener freerdp_listener; #include #include #include #include #ifdef __cplusplus extern "C" { #endif typedef boolean (*psListenerOpen)(freerdp_listener* instance, const char* bind_address, uint16 port); typedef boolean (*psListenerGetFileDescriptor)(freerdp_listener* instance, void** rfds, int* rcount); typedef boolean (*psListenerCheckFileDescriptor)(freerdp_listener* instance); typedef void (*psListenerClose)(freerdp_listener* instance); typedef void (*psPeerAccepted)(freerdp_listener* instance, freerdp_peer* client); struct rdp_freerdp_listener { void* info; void* listener; void* param1; void* param2; void* param3; void* param4; psListenerOpen Open; psListenerGetFileDescriptor GetFileDescriptor; psListenerCheckFileDescriptor CheckFileDescriptor; psListenerClose Close; psPeerAccepted PeerAccepted; }; FREERDP_API freerdp_listener* freerdp_listener_new(void); FREERDP_API void freerdp_listener_free(freerdp_listener* instance); #ifdef __cplusplus } #endif #endif FreeRDP-1.0.2/include/freerdp/peer.h000066400000000000000000000047431207112532300171230ustar00rootroot00000000000000/** * FreeRDP: A Remote Desktop Protocol client. * RDP Server Peer * * Copyright 2011 Vic Lee * * 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. */ #ifndef __FREERDP_PEER_H #define __FREERDP_PEER_H #include #include #include #include #include typedef void (*psPeerContextNew)(freerdp_peer* client, rdpContext* context); typedef void (*psPeerContextFree)(freerdp_peer* client, rdpContext* context); typedef boolean (*psPeerInitialize)(freerdp_peer* client); typedef boolean (*psPeerGetFileDescriptor)(freerdp_peer* client, void** rfds, int* rcount); typedef boolean (*psPeerCheckFileDescriptor)(freerdp_peer* client); typedef void (*psPeerDisconnect)(freerdp_peer* client); typedef boolean (*psPeerCapabilities)(freerdp_peer* client); typedef boolean (*psPeerPostConnect)(freerdp_peer* client); typedef boolean (*psPeerActivate)(freerdp_peer* client); typedef int (*psPeerSendChannelData)(freerdp_peer* client, int channelId, uint8* data, int size); typedef int (*psPeerReceiveChannelData)(freerdp_peer* client, int channelId, uint8* data, int size, int flags, int total_size); struct rdp_freerdp_peer { rdpContext* context; int sockfd; char hostname[50]; rdpInput* input; rdpUpdate* update; rdpSettings* settings; size_t context_size; psPeerContextNew ContextNew; psPeerContextFree ContextFree; psPeerInitialize Initialize; psPeerGetFileDescriptor GetFileDescriptor; psPeerCheckFileDescriptor CheckFileDescriptor; psPeerDisconnect Disconnect; psPeerCapabilities Capabilities; psPeerPostConnect PostConnect; psPeerActivate Activate; psPeerSendChannelData SendChannelData; psPeerReceiveChannelData ReceiveChannelData; }; FREERDP_API void freerdp_peer_context_new(freerdp_peer* client); FREERDP_API void freerdp_peer_context_free(freerdp_peer* client); FREERDP_API freerdp_peer* freerdp_peer_new(int sockfd); FREERDP_API void freerdp_peer_free(freerdp_peer* client); #endif /* __FREERDP_PEER_H */ FreeRDP-1.0.2/include/freerdp/plugins/000077500000000000000000000000001207112532300174705ustar00rootroot00000000000000FreeRDP-1.0.2/include/freerdp/plugins/cliprdr.h000066400000000000000000000034511207112532300213030ustar00rootroot00000000000000/** * FreeRDP: A Remote Desktop Protocol Client * Clipboard Virtual Channel Types * * Copyright 2011 Vic Lee * * 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. */ #ifndef __CLIPRDR_PLUGIN #define __CLIPRDR_PLUGIN /** * Event Types */ #define RDP_EVENT_TYPE_CB_MONITOR_READY 1 #define RDP_EVENT_TYPE_CB_FORMAT_LIST 2 #define RDP_EVENT_TYPE_CB_DATA_REQUEST 3 #define RDP_EVENT_TYPE_CB_DATA_RESPONSE 4 /** * Clipboard Formats */ #define CB_FORMAT_RAW 0x0000 #define CB_FORMAT_TEXT 0x0001 #define CB_FORMAT_DIB 0x0008 #define CB_FORMAT_UNICODETEXT 0x000D #define CB_FORMAT_HTML 0xD010 #define CB_FORMAT_PNG 0xD011 #define CB_FORMAT_JPEG 0xD012 #define CB_FORMAT_GIF 0xD013 /** * Clipboard Events */ typedef RDP_EVENT RDP_CB_MONITOR_READY_EVENT; struct _RDP_CB_FORMAT_LIST_EVENT { RDP_EVENT event; uint32* formats; uint16 num_formats; uint8* raw_format_data; uint32 raw_format_data_size; }; typedef struct _RDP_CB_FORMAT_LIST_EVENT RDP_CB_FORMAT_LIST_EVENT; struct _RDP_CB_DATA_REQUEST_EVENT { RDP_EVENT event; uint32 format; }; typedef struct _RDP_CB_DATA_REQUEST_EVENT RDP_CB_DATA_REQUEST_EVENT; struct _RDP_CB_DATA_RESPONSE_EVENT { RDP_EVENT event; uint8* data; uint32 size; }; typedef struct _RDP_CB_DATA_RESPONSE_EVENT RDP_CB_DATA_RESPONSE_EVENT; #endif /* __CLIPRDR_PLUGIN */ FreeRDP-1.0.2/include/freerdp/plugins/tsmf.h000066400000000000000000000027461207112532300206230ustar00rootroot00000000000000/** * FreeRDP: A Remote Desktop Protocol Client * Multimedia Redirection Virtual Channel Types * * Copyright 2011 Vic Lee * * 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. */ #ifndef __TSMF_PLUGIN #define __TSMF_PLUGIN /** * Event Types */ enum RDP_EVENT_TYPE_TSMF { RDP_EVENT_TYPE_TSMF_VIDEO_FRAME = 1, RDP_EVENT_TYPE_TSMF_REDRAW }; struct _RDP_VIDEO_FRAME_EVENT { RDP_EVENT event; uint8* frame_data; uint32 frame_size; uint32 frame_pixfmt; sint16 frame_width; sint16 frame_height; sint16 x; sint16 y; sint16 width; sint16 height; uint16 num_visible_rects; RDP_RECT* visible_rects; }; typedef struct _RDP_VIDEO_FRAME_EVENT RDP_VIDEO_FRAME_EVENT; struct _RDP_REDRAW_EVENT { RDP_EVENT event; sint16 x; sint16 y; sint16 width; sint16 height; }; typedef struct _RDP_REDRAW_EVENT RDP_REDRAW_EVENT; /* RDP_VIDEO_FRAME_EVENT.frame_pixfmt */ /* http://www.fourcc.org/yuv.php */ #define RDP_PIXFMT_I420 0x30323449 #define RDP_PIXFMT_YV12 0x32315659 #endif /* __TSMF_PLUGIN */ FreeRDP-1.0.2/include/freerdp/pointer.h000066400000000000000000000055061207112532300176460ustar00rootroot00000000000000/** * FreeRDP: A Remote Desktop Protocol Client * Pointer Updates Interface API * * Copyright 2011 Marc-Andre Moreau * * 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. */ #ifndef __UPDATE_POINTER_H #define __UPDATE_POINTER_H #include #define PTR_MSG_TYPE_SYSTEM 0x0001 #define PTR_MSG_TYPE_POSITION 0x0003 #define PTR_MSG_TYPE_COLOR 0x0006 #define PTR_MSG_TYPE_CACHED 0x0007 #define PTR_MSG_TYPE_POINTER 0x0008 #define SYSPTR_NULL 0x00000000 #define SYSPTR_DEFAULT 0x00007F00 struct _POINTER_POSITION_UPDATE { uint32 xPos; uint32 yPos; }; typedef struct _POINTER_POSITION_UPDATE POINTER_POSITION_UPDATE; struct _POINTER_SYSTEM_UPDATE { uint32 type; }; typedef struct _POINTER_SYSTEM_UPDATE POINTER_SYSTEM_UPDATE; struct _POINTER_COLOR_UPDATE { uint32 cacheIndex; uint32 xPos; uint32 yPos; uint32 width; uint32 height; uint32 lengthAndMask; uint32 lengthXorMask; uint8* xorMaskData; uint8* andMaskData; }; typedef struct _POINTER_COLOR_UPDATE POINTER_COLOR_UPDATE; struct _POINTER_NEW_UPDATE { uint32 xorBpp; POINTER_COLOR_UPDATE colorPtrAttr; }; typedef struct _POINTER_NEW_UPDATE POINTER_NEW_UPDATE; struct _POINTER_CACHED_UPDATE { uint32 cacheIndex; }; typedef struct _POINTER_CACHED_UPDATE POINTER_CACHED_UPDATE; typedef void (*pPointerPosition)(rdpContext* context, POINTER_POSITION_UPDATE* pointer_position); typedef void (*pPointerSystem)(rdpContext* context, POINTER_SYSTEM_UPDATE* pointer_system); typedef void (*pPointerColor)(rdpContext* context, POINTER_COLOR_UPDATE* pointer_color); typedef void (*pPointerNew)(rdpContext* context, POINTER_NEW_UPDATE* pointer_new); typedef void (*pPointerCached)(rdpContext* context, POINTER_CACHED_UPDATE* pointer_cached); struct rdp_pointer_update { rdpContext* context; /* 0 */ uint32 paddingA[16 - 1]; /* 1 */ pPointerPosition PointerPosition; /* 16 */ pPointerSystem PointerSystem; /* 17 */ pPointerColor PointerColor; /* 18 */ pPointerNew PointerNew; /* 19 */ pPointerCached PointerCached; /* 20 */ uint32 paddingB[32 - 21]; /* 21 */ /* internal */ POINTER_POSITION_UPDATE pointer_position; POINTER_SYSTEM_UPDATE pointer_system; POINTER_COLOR_UPDATE pointer_color; POINTER_NEW_UPDATE pointer_new; POINTER_CACHED_UPDATE pointer_cached; }; typedef struct rdp_pointer_update rdpPointerUpdate; #endif /* __UPDATE_POINTER_H */ FreeRDP-1.0.2/include/freerdp/primary.h000066400000000000000000000250731207112532300176520ustar00rootroot00000000000000/** * FreeRDP: A Remote Desktop Protocol Client * Primary Drawing Orders Interface API * * Copyright 2011 Marc-Andre Moreau * * 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. */ #ifndef __UPDATE_PRIMARY_H #define __UPDATE_PRIMARY_H #include struct rdp_bounds { sint32 left; sint32 top; sint32 right; sint32 bottom; }; typedef struct rdp_bounds rdpBounds; struct rdp_brush { uint32 x; uint32 y; uint32 bpp; uint32 style; uint32 hatch; uint32 index; uint8* data; uint8 p8x8[8]; }; typedef struct rdp_brush rdpBrush; struct _ORDER_INFO { uint32 orderType; uint32 fieldFlags; rdpBounds bounds; sint32 deltaBoundLeft; sint32 deltaBoundTop; sint32 deltaBoundRight; sint32 deltaBoundBottom; boolean deltaCoordinates; }; typedef struct _ORDER_INFO ORDER_INFO; struct _DSTBLT_ORDER { sint32 nLeftRect; sint32 nTopRect; sint32 nWidth; sint32 nHeight; uint32 bRop; }; typedef struct _DSTBLT_ORDER DSTBLT_ORDER; struct _PATBLT_ORDER { sint32 nLeftRect; sint32 nTopRect; sint32 nWidth; sint32 nHeight; uint32 bRop; uint32 backColor; uint32 foreColor; rdpBrush brush; }; typedef struct _PATBLT_ORDER PATBLT_ORDER; struct _SCRBLT_ORDER { sint32 nLeftRect; sint32 nTopRect; sint32 nWidth; sint32 nHeight; uint32 bRop; sint32 nXSrc; sint32 nYSrc; }; typedef struct _SCRBLT_ORDER SCRBLT_ORDER; struct _OPAQUE_RECT_ORDER { sint32 nLeftRect; sint32 nTopRect; sint32 nWidth; sint32 nHeight; uint32 color; }; typedef struct _OPAQUE_RECT_ORDER OPAQUE_RECT_ORDER; struct _DRAW_NINE_GRID_ORDER { sint32 srcLeft; sint32 srcTop; sint32 srcRight; sint32 srcBottom; uint32 bitmapId; }; typedef struct _DRAW_NINE_GRID_ORDER DRAW_NINE_GRID_ORDER; struct _DELTA_RECT { sint32 left; sint32 top; sint32 width; sint32 height; }; typedef struct _DELTA_RECT DELTA_RECT; struct _MULTI_DSTBLT_ORDER { sint32 nLeftRect; sint32 nTopRect; sint32 nWidth; sint32 nHeight; uint32 bRop; uint32 numRectangles; uint32 cbData; DELTA_RECT rectangles[45]; }; typedef struct _MULTI_DSTBLT_ORDER MULTI_DSTBLT_ORDER; struct _MULTI_PATBLT_ORDER { sint32 nLeftRect; sint32 nTopRect; sint32 nWidth; sint32 nHeight; uint32 bRop; uint32 backColor; uint32 foreColor; rdpBrush brush; uint32 numRectangles; uint32 cbData; DELTA_RECT rectangles[45]; }; typedef struct _MULTI_PATBLT_ORDER MULTI_PATBLT_ORDER; struct _MULTI_SCRBLT_ORDER { sint32 nLeftRect; sint32 nTopRect; sint32 nWidth; sint32 nHeight; uint32 bRop; sint32 nXSrc; sint32 nYSrc; uint32 numRectangles; uint32 cbData; DELTA_RECT rectangles[45]; }; typedef struct _MULTI_SCRBLT_ORDER MULTI_SCRBLT_ORDER; struct _MULTI_OPAQUE_RECT_ORDER { sint32 nLeftRect; sint32 nTopRect; sint32 nWidth; sint32 nHeight; uint32 color; uint32 numRectangles; uint32 cbData; DELTA_RECT rectangles[45]; }; typedef struct _MULTI_OPAQUE_RECT_ORDER MULTI_OPAQUE_RECT_ORDER; struct _MULTI_DRAW_NINE_GRID_ORDER { sint32 srcLeft; sint32 srcTop; sint32 srcRight; sint32 srcBottom; uint32 bitmapId; uint32 nDeltaEntries; uint32 cbData; uint8* codeDeltaList; }; typedef struct _MULTI_DRAW_NINE_GRID_ORDER MULTI_DRAW_NINE_GRID_ORDER; struct _LINE_TO_ORDER { uint32 backMode; sint32 nXStart; sint32 nYStart; sint32 nXEnd; sint32 nYEnd; uint32 backColor; uint32 bRop2; uint32 penStyle; uint32 penWidth; uint32 penColor; }; typedef struct _LINE_TO_ORDER LINE_TO_ORDER; struct _DELTA_POINT { sint32 x; sint32 y; }; typedef struct _DELTA_POINT DELTA_POINT; struct _POLYLINE_ORDER { sint32 xStart; sint32 yStart; uint32 bRop2; uint32 penColor; uint32 numPoints; uint32 cbData; DELTA_POINT* points; }; typedef struct _POLYLINE_ORDER POLYLINE_ORDER; struct _MEMBLT_ORDER { uint32 cacheId; uint32 colorIndex; sint32 nLeftRect; sint32 nTopRect; sint32 nWidth; sint32 nHeight; uint32 bRop; sint32 nXSrc; sint32 nYSrc; uint32 cacheIndex; rdpBitmap* bitmap; }; typedef struct _MEMBLT_ORDER MEMBLT_ORDER; struct _MEM3BLT_ORDER { uint32 cacheId; uint32 colorIndex; sint32 nLeftRect; sint32 nTopRect; sint32 nWidth; sint32 nHeight; uint32 bRop; sint32 nXSrc; sint32 nYSrc; uint32 backColor; uint32 foreColor; rdpBrush brush; uint32 cacheIndex; rdpBitmap* bitmap; }; typedef struct _MEM3BLT_ORDER MEM3BLT_ORDER; struct _SAVE_BITMAP_ORDER { uint32 savedBitmapPosition; sint32 nLeftRect; sint32 nTopRect; sint32 nRightRect; sint32 nBottomRect; uint32 operation; }; typedef struct _SAVE_BITMAP_ORDER SAVE_BITMAP_ORDER; struct _GLYPH_FRAGMENT_INDEX { uint32 index; uint32 delta; }; typedef struct _GLYPH_FRAGMENT_INDEX GLYPH_FRAGMENT_INDEX; struct _GLYPH_FRAGMENT { uint32 operation; uint32 index; uint32 size; uint32 nindices; GLYPH_FRAGMENT_INDEX* indices; }; typedef struct _GLYPH_FRAGMENT GLYPH_FRAGMENT; struct _GLYPH_INDEX_ORDER { uint32 cacheId; uint32 flAccel; uint32 ulCharInc; uint32 fOpRedundant; uint32 backColor; uint32 foreColor; sint32 bkLeft; sint32 bkTop; sint32 bkRight; sint32 bkBottom; sint32 opLeft; sint32 opTop; sint32 opRight; sint32 opBottom; rdpBrush brush; sint32 x; sint32 y; uint32 cbData; uint8 data[256]; }; typedef struct _GLYPH_INDEX_ORDER GLYPH_INDEX_ORDER; struct _FAST_INDEX_ORDER { uint32 cacheId; uint32 flAccel; uint32 ulCharInc; uint32 backColor; uint32 foreColor; sint32 bkLeft; sint32 bkTop; sint32 bkRight; sint32 bkBottom; sint32 opLeft; sint32 opTop; sint32 opRight; sint32 opBottom; boolean opaqueRect; sint32 x; sint32 y; uint32 cbData; uint8 data[256]; }; typedef struct _FAST_INDEX_ORDER FAST_INDEX_ORDER; struct _FAST_GLYPH_ORDER { uint32 cacheId; uint32 flAccel; uint32 ulCharInc; uint32 backColor; uint32 foreColor; sint32 bkLeft; sint32 bkTop; sint32 bkRight; sint32 bkBottom; sint32 opLeft; sint32 opTop; sint32 opRight; sint32 opBottom; sint32 x; sint32 y; uint32 cbData; uint8 data[256]; void* glyph_data; }; typedef struct _FAST_GLYPH_ORDER FAST_GLYPH_ORDER; struct _POLYGON_SC_ORDER { sint32 xStart; sint32 yStart; uint32 bRop2; uint32 fillMode; uint32 brushColor; uint32 nDeltaEntries; uint32 cbData; uint8* codeDeltaList; }; typedef struct _POLYGON_SC_ORDER POLYGON_SC_ORDER; struct _POLYGON_CB_ORDER { sint32 xStart; sint32 yStart; uint32 bRop2; uint32 fillMode; uint32 backColor; uint32 foreColor; rdpBrush brush; uint32 nDeltaEntries; uint32 cbData; uint8* codeDeltaList; }; typedef struct _POLYGON_CB_ORDER POLYGON_CB_ORDER; struct _ELLIPSE_SC_ORDER { sint32 leftRect; sint32 topRect; sint32 rightRect; sint32 bottomRect; uint32 bRop2; uint32 fillMode; uint32 color; }; typedef struct _ELLIPSE_SC_ORDER ELLIPSE_SC_ORDER; struct _ELLIPSE_CB_ORDER { sint32 leftRect; sint32 topRect; sint32 rightRect; sint32 bottomRect; uint32 bRop2; uint32 fillMode; uint32 backColor; uint32 foreColor; rdpBrush brush; }; typedef struct _ELLIPSE_CB_ORDER ELLIPSE_CB_ORDER; typedef void (*pDstBlt)(rdpContext* context, DSTBLT_ORDER* dstblt); typedef void (*pPatBlt)(rdpContext* context, PATBLT_ORDER* patblt); typedef void (*pScrBlt)(rdpContext* context, SCRBLT_ORDER* scrblt); typedef void (*pOpaqueRect)(rdpContext* context, OPAQUE_RECT_ORDER* opaque_rect); typedef void (*pDrawNineGrid)(rdpContext* context, DRAW_NINE_GRID_ORDER* draw_nine_grid); typedef void (*pMultiDstBlt)(rdpContext* context, MULTI_DSTBLT_ORDER* multi_dstblt); typedef void (*pMultiPatBlt)(rdpContext* context, MULTI_PATBLT_ORDER* multi_patblt); typedef void (*pMultiScrBlt)(rdpContext* context, MULTI_SCRBLT_ORDER* multi_scrblt); typedef void (*pMultiOpaqueRect)(rdpContext* context, MULTI_OPAQUE_RECT_ORDER* multi_opaque_rect); typedef void (*pMultiDrawNineGrid)(rdpContext* context, MULTI_DRAW_NINE_GRID_ORDER* multi_draw_nine_grid); typedef void (*pLineTo)(rdpContext* context, LINE_TO_ORDER* line_to); typedef void (*pPolyline)(rdpContext* context, POLYLINE_ORDER* polyline); typedef void (*pMemBlt)(rdpContext* context, MEMBLT_ORDER* memblt); typedef void (*pMem3Blt)(rdpContext* context, MEM3BLT_ORDER* memblt); typedef void (*pSaveBitmap)(rdpContext* context, SAVE_BITMAP_ORDER* save_bitmap); typedef void (*pGlyphIndex)(rdpContext* context, GLYPH_INDEX_ORDER* glyph_index); typedef void (*pFastIndex)(rdpContext* context, FAST_INDEX_ORDER* fast_index); typedef void (*pFastGlyph)(rdpContext* context, FAST_GLYPH_ORDER* fast_glyph); typedef void (*pPolygonSC)(rdpContext* context, POLYGON_SC_ORDER* polygon_sc); typedef void (*pPolygonCB)(rdpContext* context, POLYGON_CB_ORDER* polygon_cb); typedef void (*pEllipseSC)(rdpContext* context, ELLIPSE_SC_ORDER* ellipse_sc); typedef void (*pEllipseCB)(rdpContext* context, ELLIPSE_CB_ORDER* ellipse_cb); struct rdp_primary_update { rdpContext* context; /* 0 */ uint32 paddingA[16 - 1]; /* 1 */ pDstBlt DstBlt; /* 16 */ pPatBlt PatBlt; /* 17 */ pScrBlt ScrBlt; /* 18 */ pOpaqueRect OpaqueRect; /* 19 */ pDrawNineGrid DrawNineGrid; /* 20 */ pMultiDstBlt MultiDstBlt; /* 21 */ pMultiPatBlt MultiPatBlt; /* 22 */ pMultiScrBlt MultiScrBlt; /* 23 */ pMultiOpaqueRect MultiOpaqueRect; /* 24 */ pMultiDrawNineGrid MultiDrawNineGrid; /* 25 */ pLineTo LineTo; /* 26 */ pPolyline Polyline; /* 27 */ pMemBlt MemBlt; /* 28 */ pMem3Blt Mem3Blt; /* 29 */ pSaveBitmap SaveBitmap; /* 30 */ pGlyphIndex GlyphIndex; /* 31 */ pFastIndex FastIndex; /* 32 */ pFastGlyph FastGlyph; /* 33 */ pPolygonSC PolygonSC; /* 34 */ pPolygonCB PolygonCB; /* 35 */ pEllipseSC EllipseSC; /* 36 */ pEllipseCB EllipseCB; /* 37 */ uint32 paddingB[48 - 38]; /* 38 */ /* internal */ ORDER_INFO order_info; DSTBLT_ORDER dstblt; PATBLT_ORDER patblt; SCRBLT_ORDER scrblt; OPAQUE_RECT_ORDER opaque_rect; DRAW_NINE_GRID_ORDER draw_nine_grid; MULTI_DSTBLT_ORDER multi_dstblt; MULTI_PATBLT_ORDER multi_patblt; MULTI_SCRBLT_ORDER multi_scrblt; MULTI_OPAQUE_RECT_ORDER multi_opaque_rect; MULTI_DRAW_NINE_GRID_ORDER multi_draw_nine_grid; LINE_TO_ORDER line_to; POLYLINE_ORDER polyline; MEMBLT_ORDER memblt; MEM3BLT_ORDER mem3blt; SAVE_BITMAP_ORDER save_bitmap; GLYPH_INDEX_ORDER glyph_index; FAST_INDEX_ORDER fast_index; FAST_GLYPH_ORDER fast_glyph; POLYGON_SC_ORDER polygon_sc; POLYGON_CB_ORDER polygon_cb; ELLIPSE_SC_ORDER ellipse_sc; ELLIPSE_CB_ORDER ellipse_cb; }; typedef struct rdp_primary_update rdpPrimaryUpdate; #endif /* __UPDATE_PRIMARY_H */ FreeRDP-1.0.2/include/freerdp/rail.h000066400000000000000000000223131207112532300171100ustar00rootroot00000000000000/** * FreeRDP: A Remote Desktop Protocol Client * Remote Applications Integrated Locally (RAIL) * * Copyright 2011 Marc-Andre Moreau * Copyright 2011 Roman Barabanov * * 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. */ #ifndef __RAIL_GLOBAL_H #define __RAIL_GLOBAL_H #include /* RAIL PDU flags */ #define RAIL_EXEC_FLAG_EXPAND_WORKINGDIRECTORY 0x0001 #define RAIL_EXEC_FLAG_TRANSLATE_FILES 0x0002 #define RAIL_EXEC_FLAG_FILE 0x0004 #define RAIL_EXEC_FLAG_EXPAND_ARGUMENTS 0x0008 /* Notification Icon Balloon Tooltip */ #define NIIF_NONE 0x00000000 #define NIIF_INFO 0x00000001 #define NIIF_WARNING 0x00000002 #define NIIF_ERROR 0x00000003 #define NIIF_NOSOUND 0x00000010 #define NIIF_LARGE_ICON 0x00000020 /* Client Execute PDU Flags */ #define RAIL_EXEC_FLAG_EXPAND_WORKING_DIRECTORY 0x0001 #define RAIL_EXEC_FLAG_TRANSLATE_FILES 0x0002 #define RAIL_EXEC_FLAG_FILE 0x0004 #define RAIL_EXEC_FLAG_EXPAND_ARGUMENTS 0x0008 /* Server Execute Result PDU */ #define RAIL_EXEC_S_OK 0x0000 #define RAIL_EXEC_E_HOOK_NOT_LOADED 0x0001 #define RAIL_EXEC_E_DECODE_FAILED 0x0002 #define RAIL_EXEC_E_NOT_IN_ALLOWLIST 0x0003 #define RAIL_EXEC_E_FILE_NOT_FOUND 0x0005 #define RAIL_EXEC_E_FAIL 0x0006 #define RAIL_EXEC_E_SESSION_LOCKED 0x0007 /* Client System Parameters Update PDU */ #define SPI_SET_DRAG_FULL_WINDOWS 0x00000025 #define SPI_SET_KEYBOARD_CUES 0x0000100B #define SPI_SET_KEYBOARD_PREF 0x00000045 #define SPI_SET_MOUSE_BUTTON_SWAP 0x00000021 #define SPI_SET_WORK_AREA 0x0000002F #define SPI_DISPLAY_CHANGE 0x0000F001 #define SPI_TASKBAR_POS 0x0000F000 #define SPI_SET_HIGH_CONTRAST 0x00000043 /* Server System Parameters Update PDU */ #define SPI_SET_SCREEN_SAVE_ACTIVE 0x00000011 #define SPI_SET_SCREEN_SAVE_SECURE 0x00000077 /*Bit mask values for SPI_ parameters*/ enum SPI_MASK { SPI_MASK_SET_DRAG_FULL_WINDOWS = 0x00000001, SPI_MASK_SET_KEYBOARD_CUES = 0x00000002, SPI_MASK_SET_KEYBOARD_PREF = 0x00000004, SPI_MASK_SET_MOUSE_BUTTON_SWAP = 0x00000008, SPI_MASK_SET_WORK_AREA = 0x00000010, SPI_MASK_DISPLAY_CHANGE = 0x00000020, SPI_MASK_TASKBAR_POS = 0x00000040, SPI_MASK_SET_HIGH_CONTRAST = 0x00000080, SPI_MASK_SET_SCREEN_SAVE_ACTIVE = 0x00000100, SPI_MASK_SET_SET_SCREEN_SAVE_SECURE = 0x00000200 }; /* Client System Command PDU */ #define SC_SIZE 0xF000 #define SC_MOVE 0xF010 #define SC_MINIMIZE 0xF020 #define SC_MAXIMIZE 0xF030 #define SC_CLOSE 0xF060 #define SC_KEYMENU 0xF100 #define SC_RESTORE 0xF120 #define SC_DEFAULT 0xF160 /* Client Notify Event PDU */ #ifndef _WIN32 #define WM_LBUTTONDOWN 0x00000201 #define WM_LBUTTONUP 0x00000202 #define WM_RBUTTONDOWN 0x00000204 #define WM_RBUTTONUP 0x00000205 #define WM_CONTEXTMENU 0x0000007B #define WM_LBUTTONDBLCLK 0x00000203 #define WM_RBUTTONDBLCLK 0x00000206 #define NIN_SELECT 0x00000400 #define NIN_KEYSELECT 0x00000401 #define NIN_BALLOONSHOW 0x00000402 #define NIN_BALLOONHIDE 0x00000403 #define NIN_BALLOONTIMEOUT 0x00000404 #define NIN_BALLOONUSERCLICK 0x00000405 #endif /* Client Information PDU */ #define RAIL_CLIENTSTATUS_ALLOWLOCALMOVESIZE 0x00000001 #define RAIL_CLIENTSTATUS_AUTORECONNECT 0x00000002 /* HIGHCONTRAST flags values */ #define HCF_AVAILABLE 0x00000002 #define HCF_CONFIRMHOTKEY 0x00000008 #define HCF_HIGHCONTRASTON 0x00000001 #define HCF_HOTKEYACTIVE 0x00000004 #define HCF_HOTKEYAVAILABLE 0x00000040 #define HCF_HOTKEYSOUND 0x00000010 #define HCF_INDICATOR 0x00000020 /* Server Move/Size Start PDU */ #define RAIL_WMSZ_LEFT 0x0001 #define RAIL_WMSZ_RIGHT 0x0002 #define RAIL_WMSZ_TOP 0x0003 #define RAIL_WMSZ_TOPLEFT 0x0004 #define RAIL_WMSZ_TOPRIGHT 0x0005 #define RAIL_WMSZ_BOTTOM 0x0006 #define RAIL_WMSZ_BOTTOMLEFT 0x0007 #define RAIL_WMSZ_BOTTOMRIGHT 0x0008 #define RAIL_WMSZ_MOVE 0x0009 #define RAIL_WMSZ_KEYMOVE 0x000A #define RAIL_WMSZ_KEYSIZE 0x000B /* Language Bar Information PDU */ #define TF_SFT_SHOWNORMAL 0x00000001 #define TF_SFT_DOCK 0x00000002 #define TF_SFT_MINIMIZED 0x00000004 #define TF_SFT_HIDDEN 0x00000008 #define TF_SFT_NOTRANSPARENCY 0x00000010 #define TF_SFT_LOWTRANSPARENCY 0x00000020 #define TF_SFT_HIGHTRANSPARENCY 0x00000040 #define TF_SFT_LABELS 0x00000080 #define TF_SFT_NOLABELS 0x00000100 #define TF_SFT_EXTRAICONSONMINIMIZED 0x00000200 #define TF_SFT_NOEXTRAICONSONMINIMIZED 0x00000400 #define TF_SFT_DESKBAND 0x00000800 struct _UNICODE_STRING { uint16 length; uint8* string; }; typedef struct _UNICODE_STRING UNICODE_STRING; struct _HIGH_CONTRAST { uint32 flags; uint32 colorSchemeLength; UNICODE_STRING colorScheme; }; typedef struct _HIGH_CONTRAST HIGH_CONTRAST; /* RAIL Orders */ struct _RAIL_HANDSHAKE_ORDER { uint32 buildNumber; }; typedef struct _RAIL_HANDSHAKE_ORDER RAIL_HANDSHAKE_ORDER; struct _RAIL_CLIENT_STATUS_ORDER { uint32 flags; }; typedef struct _RAIL_CLIENT_STATUS_ORDER RAIL_CLIENT_STATUS_ORDER; struct _RAIL_EXEC_ORDER { uint16 flags; UNICODE_STRING exeOrFile; UNICODE_STRING workingDir; UNICODE_STRING arguments; }; typedef struct _RAIL_EXEC_ORDER RAIL_EXEC_ORDER; struct _RAIL_EXEC_RESULT_ORDER { uint16 flags; uint16 execResult; uint32 rawResult; UNICODE_STRING exeOrFile; }; typedef struct _RAIL_EXEC_RESULT_ORDER RAIL_EXEC_RESULT_ORDER; struct _RAIL_SYSPARAM_ORDER { uint32 param; uint32 params; boolean dragFullWindows; boolean keyboardCues; boolean keyboardPref; boolean mouseButtonSwap; RECTANGLE_16 workArea; RECTANGLE_16 displayChange; RECTANGLE_16 taskbarPos; HIGH_CONTRAST highContrast; boolean setScreenSaveActive; boolean setScreenSaveSecure; }; typedef struct _RAIL_SYSPARAM_ORDER RAIL_SYSPARAM_ORDER; struct _RAIL_ACTIVATE_ORDER { uint32 windowId; boolean enabled; }; typedef struct _RAIL_ACTIVATE_ORDER RAIL_ACTIVATE_ORDER; struct _RAIL_SYSMENU_ORDER { uint32 windowId; uint16 left; uint16 top; }; typedef struct _RAIL_SYSMENU_ORDER RAIL_SYSMENU_ORDER; struct _RAIL_SYSCOMMAND_ORDER { uint32 windowId; uint16 command; }; typedef struct _RAIL_SYSCOMMAND_ORDER RAIL_SYSCOMMAND_ORDER; struct _RAIL_NOTIFY_EVENT_ORDER { uint32 windowId; uint32 notifyIconId; uint32 message; }; typedef struct _RAIL_NOTIFY_EVENT_ORDER RAIL_NOTIFY_EVENT_ORDER; struct _RAIL_MINMAXINFO_ORDER { uint32 windowId; uint16 maxWidth; uint16 maxHeight; uint16 maxPosX; uint16 maxPosY; uint16 minTrackWidth; uint16 minTrackHeight; uint16 maxTrackWidth; uint16 maxTrackHeight; }; typedef struct _RAIL_MINMAXINFO_ORDER RAIL_MINMAXINFO_ORDER; struct _RAIL_LOCALMOVESIZE_ORDER { uint32 windowId; boolean isMoveSizeStart; uint16 moveSizeType; uint16 posX; uint16 posY; }; typedef struct _RAIL_LOCALMOVESIZE_ORDER RAIL_LOCALMOVESIZE_ORDER; struct _RAIL_WINDOWMOVE_ORDER { uint32 windowId; uint16 left; uint16 top; uint16 right; uint16 bottom; }; typedef struct _RAIL_WINDOWMOVE_ORDER RAIL_WINDOW_MOVE_ORDER; struct _RAIL_GET_APPID_REQ_ORDER { uint32 windowId; }; typedef struct _RAIL_GET_APPID_REQ_ORDER RAIL_GET_APPID_REQ_ORDER; struct _RAIL_GET_APPID_RESP_ORDER { uint32 windowId; UNICODE_STRING applicationId; uint8 applicationIdBuffer[512]; }; typedef struct _RAIL_GET_APPID_RESP_ORDER RAIL_GET_APPID_RESP_ORDER; struct _RAIL_LANGBARINFO_ORDER { uint32 languageBarStatus; }; typedef struct _RAIL_LANGBARINFO_ORDER RAIL_LANGBAR_INFO_ORDER; /* RAIL Constants */ enum RDP_RAIL_PDU_TYPE { RDP_RAIL_ORDER_EXEC = 0x0001, RDP_RAIL_ORDER_ACTIVATE = 0x0002, RDP_RAIL_ORDER_SYSPARAM = 0x0003, RDP_RAIL_ORDER_SYSCOMMAND = 0x0004, RDP_RAIL_ORDER_HANDSHAKE = 0x0005, RDP_RAIL_ORDER_NOTIFY_EVENT = 0x0006, RDP_RAIL_ORDER_WINDOWMOVE = 0x0008, RDP_RAIL_ORDER_LOCALMOVESIZE = 0x0009, RDP_RAIL_ORDER_MINMAXINFO = 0x000A, RDP_RAIL_ORDER_CLIENTSTATUS = 0x000B, RDP_RAIL_ORDER_SYSMENU = 0x000C, RDP_RAIL_ORDER_LANGBARINFO = 0x000D, RDP_RAIL_ORDER_EXEC_RESULT = 0x0080, RDP_RAIL_ORDER_GET_APPID_REQ = 0x000E, RDP_RAIL_ORDER_GET_APPID_RESP = 0x000F }; enum RDP_EVENT_TYPE_RAIL { RDP_EVENT_TYPE_RAIL_CHANNEL_GET_SYSPARAMS = 1, RDP_EVENT_TYPE_RAIL_CHANNEL_EXEC_RESULTS, RDP_EVENT_TYPE_RAIL_CHANNEL_SERVER_SYSPARAM, RDP_EVENT_TYPE_RAIL_CHANNEL_SERVER_MINMAXINFO, RDP_EVENT_TYPE_RAIL_CHANNEL_SERVER_LOCALMOVESIZE, RDP_EVENT_TYPE_RAIL_CHANNEL_APPID_RESP, RDP_EVENT_TYPE_RAIL_CHANNEL_LANGBARINFO, RDP_EVENT_TYPE_RAIL_CLIENT_SET_SYSPARAMS, RDP_EVENT_TYPE_RAIL_CLIENT_EXEC_REMOTE_APP, RDP_EVENT_TYPE_RAIL_CLIENT_ACTIVATE, RDP_EVENT_TYPE_RAIL_CLIENT_SYSMENU, RDP_EVENT_TYPE_RAIL_CLIENT_SYSCOMMAND, RDP_EVENT_TYPE_RAIL_CLIENT_NOTIFY_EVENT, RDP_EVENT_TYPE_RAIL_CLIENT_WINDOW_MOVE, RDP_EVENT_TYPE_RAIL_CLIENT_APPID_REQ, RDP_EVENT_TYPE_RAIL_CLIENT_LANGBARINFO }; #endif /* __RAIL_GLOBAL_H */ FreeRDP-1.0.2/include/freerdp/rail/000077500000000000000000000000001207112532300167365ustar00rootroot00000000000000FreeRDP-1.0.2/include/freerdp/rail/icon.h000066400000000000000000000030751207112532300200440ustar00rootroot00000000000000/** * FreeRDP: A Remote Desktop Protocol Client * Window Icon Cache * * Copyright 2011 Marc-Andre Moreau * * 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. */ #ifndef __RAIL_ICON_CACHE_H #define __RAIL_ICON_CACHE_H #include #include #include #include #include typedef struct rdp_icon rdpIcon; typedef struct rdp_icon_cache rdpIconCache; #include struct rdp_icon { ICON_INFO* entry; boolean big; void* extra; }; struct _WINDOW_ICON_CACHE { rdpIcon* entries; }; typedef struct _WINDOW_ICON_CACHE WINDOW_ICON_CACHE; struct rdp_icon_cache { rdpRail* rail; uint8 numCaches; uint16 numCacheEntries; WINDOW_ICON_CACHE* caches; }; ICON_INFO* icon_cache_get(rdpIconCache* cache, uint8 id, uint16 index, void** extra); void icon_cache_put(rdpIconCache* cache, uint8 id, uint16 index, ICON_INFO* entry, void* extra); rdpIconCache* icon_cache_new(rdpRail* rail); void icon_cache_free(rdpIconCache* cache); #endif /* __RAIL_ICON_H */ FreeRDP-1.0.2/include/freerdp/rail/rail.h000066400000000000000000000044241207112532300200420ustar00rootroot00000000000000/** * FreeRDP: A Remote Desktop Protocol Client * Remote Applications Integrated Locally (RAIL) * * Copyright 2011 Marc-Andre Moreau * * 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. */ #ifndef __RAIL_H #define __RAIL_H #include #include #include #include #include #include #include #include #include #include typedef void (*railCreateWindow)(rdpRail* rail, rdpWindow* window); typedef void (*railDestroyWindow)(rdpRail* rail, rdpWindow* window); typedef void (*railMoveWindow)(rdpRail* rail, rdpWindow* window); typedef void (*railShowWindow)(rdpRail* rail, rdpWindow* window, uint8 state); typedef void (*railSetWindowText)(rdpRail* rail, rdpWindow* window); typedef void (*railSetWindowIcon)(rdpRail* rail, rdpWindow* window, rdpIcon* icon); typedef void (*railSetWindowRects)(rdpRail* rail, rdpWindow* window); typedef void (*railSetWindowVisibilityRects)(rdpRail* rail, rdpWindow* window); struct rdp_rail { void* extra; UNICONV* uniconv; CLRCONV* clrconv; rdpIconCache* cache; rdpWindowList* list; rdpSettings* settings; railCreateWindow rail_CreateWindow; railDestroyWindow rail_DestroyWindow; railMoveWindow rail_MoveWindow; railShowWindow rail_ShowWindow; railSetWindowText rail_SetWindowText; railSetWindowIcon rail_SetWindowIcon; railSetWindowRects rail_SetWindowRects; railSetWindowVisibilityRects rail_SetWindowVisibilityRects; }; FREERDP_API void rail_register_update_callbacks(rdpRail* rail, rdpUpdate* update); FREERDP_API rdpRail* rail_new(rdpSettings* settings); FREERDP_API void rail_free(rdpRail* rail); #endif /* __RAIL_H */ FreeRDP-1.0.2/include/freerdp/rail/window.h000066400000000000000000000040751207112532300204240ustar00rootroot00000000000000/** * FreeRDP: A Remote Desktop Protocol Client * RAIL Windows * * Copyright 2011 Marc-Andre Moreau * * 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. */ #ifndef __RAIL_WINDOW_H #define __RAIL_WINDOW_H #include #include #include #include #include typedef struct rdp_window rdpWindow; #include #include struct rdp_window { void* extra; void* extraId; char* title; rdpIcon* bigIcon; rdpIcon* smallIcon; uint32 fieldFlags; rdpWindow* prev; rdpWindow* next; uint32 windowId; uint32 ownerWindowId; rdpWindow* ownerWindow; uint32 style; uint32 extendedStyle; uint8 showState; UNICODE_STRING titleInfo; uint32 clientOffsetX; uint32 clientOffsetY; uint32 clientAreaWidth; uint32 clientAreaHeight; uint8 RPContent; uint32 rootParentHandle; sint32 windowOffsetX; sint32 windowOffsetY; uint32 windowClientDeltaX; uint32 windowClientDeltaY; uint32 windowWidth; uint32 windowHeight; uint16 numWindowRects; RECTANGLE_16* windowRects; uint32 visibleOffsetX; uint32 visibleOffsetY; uint16 numVisibilityRects; RECTANGLE_16* visibilityRects; }; FREERDP_API void window_state_update(rdpWindow* window, WINDOW_ORDER_INFO* orderInfo, WINDOW_STATE_ORDER* window_state); FREERDP_API void rail_CreateWindow(rdpRail* rail, rdpWindow* window); FREERDP_API void rail_UpdateWindow(rdpRail* rail, rdpWindow* window); FREERDP_API void rail_DestroyWindow(rdpRail* rail, rdpWindow* window); #endif /* __RAIL_WINDOW_H */ FreeRDP-1.0.2/include/freerdp/rail/window_list.h000066400000000000000000000036151207112532300214560ustar00rootroot00000000000000/** * FreeRDP: A Remote Desktop Protocol Client * RAIL Window List * * Copyright 2011 Marc-Andre Moreau * * 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. */ #ifndef __RAIL_WINDOW_LIST_H #define __RAIL_WINDOW_LIST_H #include #include #include #include typedef struct rdp_window_list rdpWindowList; #include #include struct rdp_window_list { rdpRail* rail; rdpWindow* head; rdpWindow* tail; rdpWindow* iterator; }; FREERDP_API void window_list_rewind(rdpWindowList* list); FREERDP_API boolean window_list_has_next(rdpWindowList* list); FREERDP_API rdpWindow* window_list_get_next(rdpWindowList* list); FREERDP_API rdpWindow* window_list_get_by_id(rdpWindowList* list, uint32 windowId); FREERDP_API rdpWindow* window_list_get_by_extra_id(rdpWindowList* list, void* extraId); FREERDP_API void window_list_create(rdpWindowList* list, WINDOW_ORDER_INFO* orderInfo, WINDOW_STATE_ORDER* window_state); FREERDP_API void window_list_update(rdpWindowList* list, WINDOW_ORDER_INFO* orderInfo, WINDOW_STATE_ORDER* window_state); FREERDP_API void window_list_delete(rdpWindowList* list, WINDOW_ORDER_INFO* orderInfo); FREERDP_API rdpWindowList* window_list_new(rdpRail* rail); FREERDP_API void window_list_free(rdpWindowList* list); #endif /* __RAIL_WINDOW_LIST_H */ FreeRDP-1.0.2/include/freerdp/secondary.h000066400000000000000000000125201207112532300201470ustar00rootroot00000000000000/** * FreeRDP: A Remote Desktop Protocol Client * Secondary Drawing Orders Interface API * * Copyright 2011 Marc-Andre Moreau * * 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. */ #ifndef __UPDATE_SECONDARY_H #define __UPDATE_SECONDARY_H #include #define GLYPH_FRAGMENT_NOP 0x00 #define GLYPH_FRAGMENT_USE 0xFE #define GLYPH_FRAGMENT_ADD 0xFF #define CBR2_HEIGHT_SAME_AS_WIDTH 0x01 #define CBR2_PERSISTENT_KEY_PRESENT 0x02 #define CBR2_NO_BITMAP_COMPRESSION_HDR 0x08 #define CBR2_DO_NOT_CACHE 0x10 #define SCREEN_BITMAP_SURFACE 0xFFFF #define BITMAP_CACHE_WAITING_LIST_INDEX 0x7FFF #define CACHED_BRUSH 0x80 #define BMF_1BPP 0x1 #define BMF_8BPP 0x3 #define BMF_16BPP 0x4 #define BMF_24BPP 0x5 #define BMF_32BPP 0x6 #ifndef _WIN32 #define BS_SOLID 0x00 #define BS_NULL 0x01 #define BS_HATCHED 0x02 #define BS_PATTERN 0x03 #endif #ifndef _WIN32 #define HS_HORIZONTAL 0x00 #define HS_VERTICAL 0x01 #define HS_FDIAGONAL 0x02 #define HS_BDIAGONAL 0x03 #define HS_CROSS 0x04 #define HS_DIAGCROSS 0x05 #endif #define SO_FLAG_DEFAULT_PLACEMENT 0x01 #define SO_HORIZONTAL 0x02 #define SO_VERTICAL 0x04 #define SO_REVERSED 0x08 #define SO_ZERO_BEARINGS 0x10 #define SO_CHAR_INC_EQUAL_BM_BASE 0x20 #define SO_MAXEXT_EQUAL_BM_SIDE 0x40 struct _CACHE_BITMAP_ORDER { uint32 cacheId; uint32 bitmapBpp; uint32 bitmapWidth; uint32 bitmapHeight; uint32 bitmapLength; uint32 cacheIndex; boolean compressed; uint8 bitmapComprHdr[8]; uint8* bitmapDataStream; }; typedef struct _CACHE_BITMAP_ORDER CACHE_BITMAP_ORDER; struct _CACHE_BITMAP_V2_ORDER { uint32 cacheId; uint32 flags; uint32 key1; uint32 key2; uint32 bitmapBpp; uint32 bitmapWidth; uint32 bitmapHeight; uint32 bitmapLength; uint32 cacheIndex; boolean compressed; uint32 cbCompFirstRowSize; uint32 cbCompMainBodySize; uint32 cbScanWidth; uint32 cbUncompressedSize; uint8* bitmapDataStream; }; typedef struct _CACHE_BITMAP_V2_ORDER CACHE_BITMAP_V2_ORDER; struct _BITMAP_DATA_EX { uint32 bpp; uint32 codecID; uint32 width; uint32 height; uint32 length; uint8* data; }; typedef struct _BITMAP_DATA_EX BITMAP_DATA_EX; struct _CACHE_BITMAP_V3_ORDER { uint32 cacheId; uint32 bpp; uint32 flags; uint32 cacheIndex; uint32 key1; uint32 key2; BITMAP_DATA_EX bitmapData; }; typedef struct _CACHE_BITMAP_V3_ORDER CACHE_BITMAP_V3_ORDER; struct _CACHE_COLOR_TABLE_ORDER { uint32 cacheIndex; uint32 numberColors; uint32* colorTable; }; typedef struct _CACHE_COLOR_TABLE_ORDER CACHE_COLOR_TABLE_ORDER; struct _GLYPH_DATA { uint32 cacheIndex; sint32 x; sint32 y; uint32 cx; uint32 cy; uint32 cb; uint8* aj; }; typedef struct _GLYPH_DATA GLYPH_DATA; struct _CACHE_GLYPH_ORDER { uint32 cacheId; uint32 cGlyphs; GLYPH_DATA* glyphData[255]; uint8* unicodeCharacters; }; typedef struct _CACHE_GLYPH_ORDER CACHE_GLYPH_ORDER; struct _GLYPH_DATA_V2 { uint32 cacheIndex; sint32 x; sint32 y; uint32 cx; uint32 cy; uint32 cb; uint8* aj; }; typedef struct _GLYPH_DATA_V2 GLYPH_DATA_V2; struct _CACHE_GLYPH_V2_ORDER { uint32 cacheId; uint32 flags; uint32 cGlyphs; GLYPH_DATA_V2* glyphData[255]; uint8* unicodeCharacters; }; typedef struct _CACHE_GLYPH_V2_ORDER CACHE_GLYPH_V2_ORDER; struct _CACHE_BRUSH_ORDER { uint32 index; uint32 bpp; uint32 cx; uint32 cy; uint32 style; uint32 length; uint8* data; }; typedef struct _CACHE_BRUSH_ORDER CACHE_BRUSH_ORDER; typedef void (*pCacheBitmap)(rdpContext* context, CACHE_BITMAP_ORDER* cache_bitmap_order); typedef void (*pCacheBitmapV2)(rdpContext* context, CACHE_BITMAP_V2_ORDER* cache_bitmap_v2_order); typedef void (*pCacheBitmapV3)(rdpContext* context, CACHE_BITMAP_V3_ORDER* cache_bitmap_v3_order); typedef void (*pCacheColorTable)(rdpContext* context, CACHE_COLOR_TABLE_ORDER* cache_color_table_order); typedef void (*pCacheGlyph)(rdpContext* context, CACHE_GLYPH_ORDER* cache_glyph_order); typedef void (*pCacheGlyphV2)(rdpContext* context, CACHE_GLYPH_V2_ORDER* cache_glyph_v2_order); typedef void (*pCacheBrush)(rdpContext* context, CACHE_BRUSH_ORDER* cache_brush_order); struct rdp_secondary_update { rdpContext* context; /* 0 */ uint32 paddingA[16 - 1]; /* 1 */ pCacheBitmap CacheBitmap; /* 16 */ pCacheBitmapV2 CacheBitmapV2; /* 17 */ pCacheBitmapV3 CacheBitmapV3; /* 18 */ pCacheColorTable CacheColorTable; /* 19 */ pCacheGlyph CacheGlyph; /* 20 */ pCacheGlyphV2 CacheGlyphV2; /* 21 */ pCacheBrush CacheBrush; /* 22 */ uint32 paddingE[32 - 23]; /* 23 */ /* internal */ boolean glyph_v2; CACHE_BITMAP_ORDER cache_bitmap_order; CACHE_BITMAP_V2_ORDER cache_bitmap_v2_order; CACHE_BITMAP_V3_ORDER cache_bitmap_v3_order; CACHE_COLOR_TABLE_ORDER cache_color_table_order; CACHE_GLYPH_ORDER cache_glyph_order; CACHE_GLYPH_V2_ORDER cache_glyph_v2_order; CACHE_BRUSH_ORDER cache_brush_order; }; typedef struct rdp_secondary_update rdpSecondaryUpdate; #endif /* __UPDATE_SECONDARY_H */ FreeRDP-1.0.2/include/freerdp/settings.h000066400000000000000000000275261207112532300200340ustar00rootroot00000000000000/** * FreeRDP: A Remote Desktop Protocol Client * RDP Settings * * Copyright 2009-2011 Jay Sorg * * 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. */ #ifndef __RDP_SETTINGS_H #define __RDP_SETTINGS_H #include #include #include /* Performance Flags */ #define PERF_FLAG_NONE 0x00000000 #define PERF_DISABLE_WALLPAPER 0x00000001 #define PERF_DISABLE_FULLWINDOWDRAG 0x00000002 #define PERF_DISABLE_MENUANIMATIONS 0x00000004 #define PERF_DISABLE_THEMING 0x00000008 #define PERF_DISABLE_CURSOR_SHADOW 0x00000020 #define PERF_DISABLE_CURSORSETTINGS 0x00000040 #define PERF_ENABLE_FONT_SMOOTHING 0x00000080 #define PERF_ENABLE_DESKTOP_COMPOSITION 0x00000100 /* Connection Types */ #define CONNECTION_TYPE_MODEM 0x01 #define CONNECTION_TYPE_BROADBAND_LOW 0x02 #define CONNECTION_TYPE_SATELLITE 0x03 #define CONNECTION_TYPE_BROADBAND_HIGH 0x04 #define CONNECTION_TYPE_WAN 0x05 #define CONNECTION_TYPE_LAN 0x06 /* Encryption Methods */ #define ENCRYPTION_METHOD_NONE 0x00000000 #define ENCRYPTION_METHOD_40BIT 0x00000001 #define ENCRYPTION_METHOD_128BIT 0x00000002 #define ENCRYPTION_METHOD_56BIT 0x00000008 #define ENCRYPTION_METHOD_FIPS 0x00000010 /* Encryption Levels */ #define ENCRYPTION_LEVEL_NONE 0x00000000 #define ENCRYPTION_LEVEL_LOW 0x00000001 #define ENCRYPTION_LEVEL_CLIENT_COMPATIBLE 0x00000002 #define ENCRYPTION_LEVEL_HIGH 0x00000003 #define ENCRYPTION_LEVEL_FIPS 0x00000004 /* Auto Reconnect Version */ #define AUTO_RECONNECT_VERSION_1 0x00000001 /* Order Support */ #define NEG_DSTBLT_INDEX 0x00 #define NEG_PATBLT_INDEX 0x01 #define NEG_SCRBLT_INDEX 0x02 #define NEG_MEMBLT_INDEX 0x03 #define NEG_MEM3BLT_INDEX 0x04 #define NEG_ATEXTOUT_INDEX 0x05 #define NEG_AEXTTEXTOUT_INDEX 0x06 #define NEG_DRAWNINEGRID_INDEX 0x07 #define NEG_LINETO_INDEX 0x08 #define NEG_MULTI_DRAWNINEGRID_INDEX 0x09 #define NEG_OPAQUE_RECT_INDEX 0x0A #define NEG_SAVEBITMAP_INDEX 0x0B #define NEG_WTEXTOUT_INDEX 0x0C #define NEG_MEMBLT_V2_INDEX 0x0D #define NEG_MEM3BLT_V2_INDEX 0x0E #define NEG_MULTIDSTBLT_INDEX 0x0F #define NEG_MULTIPATBLT_INDEX 0x10 #define NEG_MULTISCRBLT_INDEX 0x11 #define NEG_MULTIOPAQUERECT_INDEX 0x12 #define NEG_FAST_INDEX_INDEX 0x13 #define NEG_POLYGON_SC_INDEX 0x14 #define NEG_POLYGON_CB_INDEX 0x15 #define NEG_POLYLINE_INDEX 0x16 #define NEG_FAST_GLYPH_INDEX 0x18 #define NEG_ELLIPSE_SC_INDEX 0x19 #define NEG_ELLIPSE_CB_INDEX 0x1A #define NEG_GLYPH_INDEX_INDEX 0x1B #define NEG_GLYPH_WEXTTEXTOUT_INDEX 0x1C #define NEG_GLYPH_WLONGTEXTOUT_INDEX 0x1D #define NEG_GLYPH_WLONGEXTTEXTOUT_INDEX 0x1E /* Glyph Support Level */ #define GLYPH_SUPPORT_NONE 0x0000 #define GLYPH_SUPPORT_PARTIAL 0x0001 #define GLYPH_SUPPORT_FULL 0x0002 #define GLYPH_SUPPORT_ENCODE 0x0003 /* SYSTEM_TIME */ typedef struct { uint16 wYear; uint16 wMonth; uint16 wDayOfWeek; uint16 wDay; uint16 wHour; uint16 wMinute; uint16 wSecond; uint16 wMilliseconds; } SYSTEM_TIME; /* TIME_ZONE_INFORMATION */ struct _TIME_ZONE_INFO { uint32 bias; char standardName[32]; SYSTEM_TIME standardDate; uint32 standardBias; char daylightName[32]; SYSTEM_TIME daylightDate; uint32 daylightBias; }; typedef struct _TIME_ZONE_INFO TIME_ZONE_INFO; /* ARC_CS_PRIVATE_PACKET */ typedef struct { uint32 cbLen; uint32 version; uint32 logonId; uint8 securityVerifier[16]; } ARC_CS_PRIVATE_PACKET; /* ARC_SC_PRIVATE_PACKET */ typedef struct { uint32 cbLen; uint32 version; uint32 logonId; uint8 arcRandomBits[16]; } ARC_SC_PRIVATE_PACKET; /* Certificates */ typedef struct rdp_certificate rdpCertificate; typedef struct rdp_key rdpKey; struct rdp_CertBlob { uint32 length; uint8* data; }; typedef struct rdp_CertBlob rdpCertBlob; struct rdp_X509CertChain { uint32 count; rdpCertBlob* array; }; typedef struct rdp_X509CertChain rdpX509CertChain; struct rdp_CertInfo { rdpBlob modulus; uint8 exponent[4]; }; typedef struct rdp_CertInfo rdpCertInfo; struct rdp_certificate { rdpCertInfo cert_info; rdpX509CertChain* x509_cert_chain; }; /* Channels */ struct rdp_channel { char name[8]; /* ui sets */ int options; /* ui sets */ int channel_id; /* core sets */ boolean joined; /* client has joined the channel */ void* handle; /* just for ui */ }; typedef struct rdp_channel rdpChannel; /* Extensions */ struct rdp_ext_set { char name[256]; /* plugin name or path */ void* data; /* plugin data */ }; /* Bitmap Cache */ struct _BITMAP_CACHE_CELL_INFO { uint16 numEntries; uint16 maxSize; }; typedef struct _BITMAP_CACHE_CELL_INFO BITMAP_CACHE_CELL_INFO; struct _BITMAP_CACHE_V2_CELL_INFO { uint32 numEntries; boolean persistent; }; typedef struct _BITMAP_CACHE_V2_CELL_INFO BITMAP_CACHE_V2_CELL_INFO; /* Glyph Cache */ struct _GLYPH_CACHE_DEFINITION { uint16 cacheEntries; uint16 cacheMaximumCellSize; }; typedef struct _GLYPH_CACHE_DEFINITION GLYPH_CACHE_DEFINITION; /* Monitors */ struct rdp_monitor { int x; int y; int width; int height; int is_primary; }; /* Settings */ struct rdp_settings { void* instance; /* 0 */ uint32 paddingA[16 - 1]; /* 1 */ /* Core Protocol Parameters */ uint32 width; /* 16 */ uint32 height; /* 17 */ uint32 rdp_version; /* 18 */ uint32 color_depth; /* 19 */ uint32 kbd_layout; /* 20 */ uint32 kbd_type; /* 21 */ uint32 kbd_subtype; /* 22 */ uint32 kbd_fn_keys; /* 23 */ uint32 client_build; /* 24 */ uint32 requested_protocols; /* 25 */ uint32 selected_protocol; /* 26 */ uint32 encryption_method; /* 27 */ uint32 encryption_level; /* 28 */ boolean authentication; /* 29 */ uint32 negotiationFlags; /* 30 */ uint32 paddingB[48 - 31]; /* 31 */ /* Connection Settings */ uint32 port; /* 48 */ boolean ipv6; /* 49 */ char* hostname; /* 50 */ char* username; /* 51 */ char* password; /* 52 */ char* domain; /* 53 */ char* shell; /* 54 */ char* directory; /* 55 */ char* ip_address; /* 56 */ char* client_dir; /* 57 */ boolean autologon; /* 58 */ boolean compression; /* 59 */ uint32 performance_flags; /* 60 */ rdpBlob* password_cookie; /* 61 */ char* kerberos_kdc; /* 62 */ char* kerberos_realm; /* 63 */ boolean ts_gateway; /* 64 */ char* tsg_hostname; /* 65 */ char* tsg_username; /* 66 */ char* tsg_password; /* 67 */ boolean local; /* 68 */ boolean authentication_only; /* 69 */ boolean from_stdin; /* 70 */ uint32 paddingC[80 - 71]; /* 71 */ /* User Interface Parameters */ boolean sw_gdi; /* 80 */ boolean workarea; /* 81 */ boolean fullscreen; /* 82 */ boolean grab_keyboard; /* 83 */ boolean decorations; /* 84 */ uint32 percent_screen; /* 85 */ boolean mouse_motion; /* 86 */ char* window_title; /* 87 */ uint64 parent_window_xid; /* 88 */ uint32 paddingD[112 - 89]; /* 89 */ /* Internal Parameters */ char* home_path; /* 112 */ uint32 share_id; /* 113 */ uint32 pdu_source; /* 114 */ UNICONV* uniconv; /* 115 */ boolean server_mode; /* 116 */ char* config_path; /* 117 */ char* current_path; /* 118 */ char* development_path; /* 119 */ boolean development_mode; /* 120 */ uint32 paddingE[144 - 121]; /* 121 */ /* Security */ boolean encryption; /* 144 */ boolean tls_security; /* 145 */ boolean nla_security; /* 146 */ boolean rdp_security; /* 147 */ uint32 ntlm_version; /* 148 */ boolean secure_checksum; /* 149 */ uint32 paddingF[160 - 150]; /* 150 */ /* Session */ boolean console_audio; /* 160 */ boolean console_session; /* 161 */ uint32 redirected_session_id; /* 162 */ boolean audio_playback; /* 163 */ boolean audio_capture; /* 164 */ uint32 paddingG[176 - 165]; /* 165 */ /* Output Control */ boolean refresh_rect; /* 176 */ boolean suppress_output; /* 177 */ boolean desktop_resize; /* 178 */ uint32 paddingH[192 - 179]; /* 179 */ /* Reconnection */ boolean auto_reconnection; /* 192 */ ARC_CS_PRIVATE_PACKET* client_auto_reconnect_cookie; /* 193 */ ARC_SC_PRIVATE_PACKET* server_auto_reconnect_cookie; /* 194 */ uint32 paddingI[208 - 195]; /* 195 */ /* Time Zone */ TIME_ZONE_INFO* client_time_zone; /* 208 */ uint32 paddingJ[216 - 209]; /* 209 */ /* Capabilities */ uint32 os_major_type; /* 216 */ uint32 os_minor_type; /* 217 */ uint32 vc_chunk_size; /* 218 */ boolean sound_beeps; /* 219 */ boolean smooth_fonts; /* 220 */ boolean frame_marker; /* 221 */ boolean fastpath_input; /* 222 */ boolean fastpath_output; /* 223 */ uint8 received_caps[32]; /* 224 (8) */ uint8 order_support[32]; /* 232 (8) */ boolean surface_commands; /* 240 */ boolean disable_wallpaper; /* 241 */ boolean disable_full_window_drag; /* 242 */ boolean disable_menu_animations; /* 243 */ boolean disable_theming; /* 244 */ uint32 connection_type; /* 245 */ uint32 multifrag_max_request_size; /* 246 */ uint32 paddingK[248 - 247]; /* 247 */ /* Certificate */ char* cert_file; /* 248 */ char* privatekey_file; /* 249 */ char client_hostname[32]; /* 250 (8) */ char client_product_id[32]; /* 258 (8) */ rdpBlob* server_random; /* 266 */ rdpBlob* server_certificate; /* 267 */ boolean ignore_certificate; /* 268 */ rdpCertificate* server_cert; /* 269 */ char* rdp_key_file; /* 270 */ rdpKey* server_key; /* 271 */ char* certificate_name; /* 272 */ uint32 paddingL[280 - 273]; /* 273 */ /* Codecs */ boolean rfx_codec; /* 280 */ boolean ns_codec; /* 281 */ uint32 rfx_codec_id; /* 282 */ uint32 ns_codec_id; /* 283 */ uint32 rfx_codec_mode; /* 284 */ boolean frame_acknowledge; /* 285 */ uint32 paddingM[296 - 286]; /* 286 */ /* Recording */ boolean dump_rfx; /* 296 */ boolean play_rfx; /* 297 */ char* dump_rfx_file; /* 298 */ char* play_rfx_file; /* 299 */ uint32 paddingN[312 - 300]; /* 300 */ /* RemoteApp */ boolean remote_app; /* 312 */ uint32 num_icon_caches; /* 313 */ uint32 num_icon_cache_entries; /* 314 */ boolean rail_langbar_supported; /* 315 */ uint32 paddingO[320 - 316]; /* 316 */ /* Pointer */ boolean large_pointer; /* 320 */ boolean color_pointer; /* 321 */ uint32 pointer_cache_size; /* 322 */ uint32 paddingP[328 - 323]; /* 323 */ /* Bitmap Cache */ boolean bitmap_cache; /* 328 */ boolean bitmap_cache_v3; /* 329 */ boolean persistent_bitmap_cache; /* 330 */ uint32 bitmapCacheV2NumCells; /* 331 */ BITMAP_CACHE_V2_CELL_INFO* bitmapCacheV2CellInfo; /* 332 */ uint32 paddingQ[344 - 333]; /* 333 */ /* Offscreen Bitmap Cache */ boolean offscreen_bitmap_cache; /* 344 */ uint32 offscreen_bitmap_cache_size; /* 345 */ uint32 offscreen_bitmap_cache_entries; /* 346 */ uint32 paddingR[352 - 347]; /* 347 */ /* Glyph Cache */ boolean glyph_cache; /* 352 */ uint32 glyphSupportLevel; /* 353 */ GLYPH_CACHE_DEFINITION* glyphCache; /* 354 */ GLYPH_CACHE_DEFINITION* fragCache; /* 355 */ uint32 paddingS[360 - 356]; /* 356 */ /* Draw Nine Grid */ boolean draw_nine_grid; /* 360 */ uint32 draw_nine_grid_cache_size; /* 361 */ uint32 draw_nine_grid_cache_entries; /* 362 */ uint32 paddingT[368 - 363]; /* 363 */ /* Draw GDI+ */ boolean draw_gdi_plus; /* 368 */ boolean draw_gdi_plus_cache; /* 369 */ uint32 paddingU[376 - 370]; /* 370 */ /* Desktop Composition */ boolean desktop_composition; /* 376 */ uint32 paddingV[384 - 377]; /* 377 */ /* Channels */ int num_channels; rdpChannel channels[16]; /* Monitors */ int num_monitors; struct rdp_monitor monitors[16]; /* Extensions */ int num_extensions; struct rdp_ext_set extensions[16]; }; typedef struct rdp_settings rdpSettings; rdpSettings* settings_new(void* instance); void settings_free(rdpSettings* settings); #endif /* __RDP_SETTINGS_H */ FreeRDP-1.0.2/include/freerdp/svc.h000066400000000000000000000077051207112532300167640ustar00rootroot00000000000000/** * FreeRDP: A Remote Desktop Protocol client. * Static Virtual Channel Interface * * Copyright 2009-2011 Jay Sorg * * 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. */ /** * MS compatible SVC plugin interface * reference: * http://msdn.microsoft.com/en-us/library/aa383580.aspx */ #ifndef __FREERDP_SVC_H #define __FREERDP_SVC_H #include #include #define CHANNEL_EXPORT_FUNC_NAME "VirtualChannelEntry" #define CHANNEL_NAME_LEN 7 struct _CHANNEL_DEF { char name[CHANNEL_NAME_LEN + 1]; uint32 options; }; typedef struct _CHANNEL_DEF CHANNEL_DEF; typedef CHANNEL_DEF* PCHANNEL_DEF; typedef CHANNEL_DEF** PPCHANNEL_DEF; typedef void (FREERDP_CC * PCHANNEL_INIT_EVENT_FN)(void* pInitHandle, uint32 event, void* pData, uint32 dataLength); typedef void (FREERDP_CC * PCHANNEL_OPEN_EVENT_FN)(uint32 openHandle, uint32 event, void* pData, uint32 dataLength, uint32 totalLength, uint32 dataFlags); #define CHANNEL_RC_OK 0 #define CHANNEL_RC_ALREADY_INITIALIZED 1 #define CHANNEL_RC_NOT_INITIALIZED 2 #define CHANNEL_RC_ALREADY_CONNECTED 3 #define CHANNEL_RC_NOT_CONNECTED 4 #define CHANNEL_RC_TOO_MANY_CHANNELS 5 #define CHANNEL_RC_BAD_CHANNEL 6 #define CHANNEL_RC_BAD_CHANNEL_HANDLE 7 #define CHANNEL_RC_NO_BUFFER 8 #define CHANNEL_RC_BAD_INIT_HANDLE 9 #define CHANNEL_RC_NOT_OPEN 10 #define CHANNEL_RC_BAD_PROC 11 #define CHANNEL_RC_NO_MEMORY 12 #define CHANNEL_RC_UNKNOWN_CHANNEL_NAME 13 #define CHANNEL_RC_ALREADY_OPEN 14 #define CHANNEL_RC_NOT_IN_VIRTUALCHANNELENTRY 15 #define CHANNEL_RC_NULL_DATA 16 #define CHANNEL_RC_ZERO_LENGTH 17 #define VIRTUAL_CHANNEL_VERSION_WIN2000 1 typedef uint32 (FREERDP_CC * PVIRTUALCHANNELINIT)(void** ppInitHandle, PCHANNEL_DEF pChannel, int channelCount, uint32 versionRequested, PCHANNEL_INIT_EVENT_FN pChannelInitEventProc); typedef uint32 (FREERDP_CC * PVIRTUALCHANNELOPEN)(void* pInitHandle, uint32* pOpenHandle, char* pChannelName, PCHANNEL_OPEN_EVENT_FN pChannelOpenEventProc); typedef uint32 (FREERDP_CC * PVIRTUALCHANNELCLOSE)(uint32 openHandle); typedef uint32 (FREERDP_CC * PVIRTUALCHANNELWRITE)(uint32 openHandle, void* pData, uint32 dataLength, void* pUserData); typedef uint32 (FREERDP_CC * PVIRTUALCHANNELEVENTPUSH)(uint32 openHandle, RDP_EVENT* event); struct _CHANNEL_ENTRY_POINTS { uint32 cbSize; uint32 protocolVersion; PVIRTUALCHANNELINIT pVirtualChannelInit; PVIRTUALCHANNELOPEN pVirtualChannelOpen; PVIRTUALCHANNELCLOSE pVirtualChannelClose; PVIRTUALCHANNELWRITE pVirtualChannelWrite; }; typedef struct _CHANNEL_ENTRY_POINTS CHANNEL_ENTRY_POINTS; typedef CHANNEL_ENTRY_POINTS* PCHANNEL_ENTRY_POINTS; typedef int (FREERDP_CC * PVIRTUALCHANNELENTRY)(PCHANNEL_ENTRY_POINTS pEntryPoints); struct _CHANNEL_ENTRY_POINTS_EX { uint32 cbSize; uint32 protocolVersion; PVIRTUALCHANNELINIT pVirtualChannelInit; PVIRTUALCHANNELOPEN pVirtualChannelOpen; PVIRTUALCHANNELCLOSE pVirtualChannelClose; PVIRTUALCHANNELWRITE pVirtualChannelWrite; void* pExtendedData; /* extended data field to pass initial parameters */ PVIRTUALCHANNELEVENTPUSH pVirtualChannelEventPush; }; typedef struct _CHANNEL_ENTRY_POINTS_EX CHANNEL_ENTRY_POINTS_EX; typedef CHANNEL_ENTRY_POINTS_EX* PCHANNEL_ENTRY_POINTS_EX; #endif FreeRDP-1.0.2/include/freerdp/types.h000066400000000000000000000055541207112532300173350ustar00rootroot00000000000000/** * FreeRDP: A Remote Desktop Protocol Client * Type Definitions * * Copyright 2009-2011 Jay Sorg * Copyright 2011 Marc-Andre Moreau * * 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. */ #ifndef __RDP_TYPES_H #define __RDP_TYPES_H #ifdef _WIN32 #include #endif /* Base Types */ #ifdef HAVE_LIMITS_H #include #endif #ifdef HAVE_STDINT_H #include #endif #ifdef HAVE_INTTYPES_H #include typedef uint8_t uint8; typedef int8_t sint8; typedef uint16_t uint16; typedef int16_t sint16; typedef uint32_t uint32; typedef int32_t sint32; typedef uint64_t uint64; typedef int64_t sint64; #else typedef unsigned char uint8; typedef signed char sint8; typedef unsigned short uint16; typedef signed short sint16; typedef unsigned int uint32; typedef signed int sint32; #ifdef _WIN32 typedef unsigned __int64 uint64; typedef signed __int64 sint64; #else typedef unsigned long long uint64; typedef signed long long sint64; #endif #endif /* HAVE_INTTYPES_H */ #ifdef HAVE_STDBOOL_H #include typedef int boolean; #else #ifndef __cplusplus #ifndef __bool_true_false_are_defined #define __bool_true_false_are_defined 1 #define true 1 #define false 0 #ifdef _WIN32 #define boolean BOOLEAN #else typedef int boolean; #endif #endif /* __bool_true_false_are_defined */ #else #ifndef true #define true 1 #endif #ifndef false #define false 0 #endif typedef int boolean; #endif /* __cplusplus */ #endif /* HAVE_STDBOOL_H */ #ifndef MIN #define MIN(x,y) (((x) < (y)) ? (x) : (y)) #endif #ifndef MAX #define MAX(x,y) (((x) > (y)) ? (x) : (y)) #endif #include struct _RDP_PLUGIN_DATA { uint16 size; void* data[4]; }; typedef struct _RDP_PLUGIN_DATA RDP_PLUGIN_DATA; struct _RDP_RECT { sint16 x; sint16 y; sint16 width; sint16 height; }; typedef struct _RDP_RECT RDP_RECT; struct _RECTANGLE_16 { uint16 left; uint16 top; uint16 right; uint16 bottom; }; typedef struct _RECTANGLE_16 RECTANGLE_16; /* Plugin events */ typedef struct _RDP_EVENT RDP_EVENT; typedef void (*RDP_EVENT_CALLBACK) (RDP_EVENT* event); struct _RDP_EVENT { uint16 event_class; uint16 event_type; RDP_EVENT_CALLBACK on_event_free_callback; void* user_data; }; enum RDP_EVENT_CLASS { RDP_EVENT_CLASS_DEBUG = 0, RDP_EVENT_CLASS_CLIPRDR, RDP_EVENT_CLASS_TSMF, RDP_EVENT_CLASS_RAIL }; #endif /* __RDP_TYPES_H */ FreeRDP-1.0.2/include/freerdp/update.h000066400000000000000000000112421207112532300174420ustar00rootroot00000000000000/** * FreeRDP: A Remote Desktop Protocol Client * Update Interface API * * Copyright 2011 Marc-Andre Moreau * * 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. */ #ifndef __UPDATE_API_H #define __UPDATE_API_H typedef struct rdp_update rdpUpdate; #include #include #include #include #include #include #include #include #include #include #include /* Bitmap Updates */ struct _BITMAP_DATA { uint32 destLeft; uint32 destTop; uint32 destRight; uint32 destBottom; uint32 width; uint32 height; uint32 bitsPerPixel; uint32 flags; uint32 bitmapLength; uint32 cbCompFirstRowSize; uint32 cbCompMainBodySize; uint32 cbScanWidth; uint32 cbUncompressedSize; uint8* bitmapDataStream; boolean compressed; }; typedef struct _BITMAP_DATA BITMAP_DATA; struct _BITMAP_UPDATE { uint32 count; uint32 number; BITMAP_DATA* rectangles; }; typedef struct _BITMAP_UPDATE BITMAP_UPDATE; /* Palette Updates */ struct _PALETTE_ENTRY { uint8 red; uint8 green; uint8 blue; }; typedef struct _PALETTE_ENTRY PALETTE_ENTRY; struct _PALETTE_UPDATE { uint32 number; PALETTE_ENTRY entries[256]; }; typedef struct _PALETTE_UPDATE PALETTE_UPDATE; struct rdp_palette { uint32 count; PALETTE_ENTRY* entries; }; typedef struct rdp_palette rdpPalette; /* Play Sound (System Beep) Updates */ struct _PLAY_SOUND_UPDATE { uint32 duration; uint32 frequency; }; typedef struct _PLAY_SOUND_UPDATE PLAY_SOUND_UPDATE; /* Surface Command Updates */ struct _SURFACE_BITS_COMMAND { uint32 cmdType; uint32 destLeft; uint32 destTop; uint32 destRight; uint32 destBottom; uint32 bpp; uint32 codecID; uint32 width; uint32 height; uint32 bitmapDataLength; uint8* bitmapData; }; typedef struct _SURFACE_BITS_COMMAND SURFACE_BITS_COMMAND; struct _SURFACE_FRAME_MARKER { uint32 frameAction; uint32 frameId; }; typedef struct _SURFACE_FRAME_MARKER SURFACE_FRAME_MARKER; /* Update Interface */ typedef void (*pBeginPaint)(rdpContext* context); typedef void (*pEndPaint)(rdpContext* context); typedef void (*pSetBounds)(rdpContext* context, rdpBounds* bounds); typedef void (*pSynchronize)(rdpContext* context); typedef void (*pDesktopResize)(rdpContext* context); typedef void (*pBitmapUpdate)(rdpContext* context, BITMAP_UPDATE* bitmap); typedef void (*pPalette)(rdpContext* context, PALETTE_UPDATE* palette); typedef void (*pPlaySound)(rdpContext* context, PLAY_SOUND_UPDATE* play_sound); typedef void (*pRefreshRect)(rdpContext* context, uint8 count, RECTANGLE_16* areas); typedef void (*pSuppressOutput)(rdpContext* context, uint8 allow, RECTANGLE_16* area); typedef void (*pSurfaceCommand)(rdpContext* context, STREAM* s); typedef void (*pSurfaceBits)(rdpContext* context, SURFACE_BITS_COMMAND* surface_bits_command); typedef void (*pSurfaceFrameMarker)(rdpContext* context, SURFACE_FRAME_MARKER* surface_frame_marker); struct rdp_update { rdpContext* context; /* 0 */ uint32 paddingA[16 - 1]; /* 1 */ pBeginPaint BeginPaint; /* 16 */ pEndPaint EndPaint; /* 17 */ pSetBounds SetBounds; /* 18 */ pSynchronize Synchronize; /* 19 */ pDesktopResize DesktopResize; /* 20 */ pBitmapUpdate BitmapUpdate; /* 21 */ pPalette Palette; /* 22 */ pPlaySound PlaySound; /* 23 */ uint32 paddingB[32 - 24]; /* 24 */ rdpPointerUpdate* pointer; /* 32 */ rdpPrimaryUpdate* primary; /* 33 */ rdpSecondaryUpdate* secondary; /* 34 */ rdpAltSecUpdate* altsec; /* 35 */ rdpWindowUpdate* window; /* 36 */ uint32 paddingC[48 - 37]; /* 37 */ pRefreshRect RefreshRect; /* 48 */ pSuppressOutput SuppressOutput; /* 49 */ uint32 paddingD[64 - 50]; /* 50 */ pSurfaceCommand SurfaceCommand; /* 64 */ pSurfaceBits SurfaceBits; /* 65 */ pSurfaceFrameMarker SurfaceFrameMarker; /* 66 */ uint32 paddingE[80 - 67]; /* 67 */ /* internal */ boolean dump_rfx; boolean play_rfx; rdpPcap* pcap_rfx; BITMAP_UPDATE bitmap_update; PALETTE_UPDATE palette_update; PLAY_SOUND_UPDATE play_sound; SURFACE_BITS_COMMAND surface_bits_command; SURFACE_FRAME_MARKER surface_frame_marker; }; #endif /* __UPDATE_API_H */ FreeRDP-1.0.2/include/freerdp/utils/000077500000000000000000000000001207112532300171475ustar00rootroot00000000000000FreeRDP-1.0.2/include/freerdp/utils/args.h000066400000000000000000000030111207112532300202470ustar00rootroot00000000000000/** * FreeRDP: A Remote Desktop Protocol client. * Arguments Parsing * * Copyright 2011 Vic Lee * * 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. */ #ifndef __ARGS_UTILS_H #define __ARGS_UTILS_H #include #include #include typedef enum _FREERDP_ARGS_PARSE_RESULT { FREERDP_ARGS_PARSE_FAILURE = -1, FREERDP_ARGS_PARSE_HELP = -2, FREERDP_ARGS_PARSE_VERSION = -3, } FREERDP_ARGS_PARSE_RESULT; /* Returns 1 if succeed, otherwise returns zero */ typedef int (*ProcessPluginArgs) (rdpSettings* settings, const char* name, RDP_PLUGIN_DATA* plugin_data, void* user_data); /* Returns number of arguments processed (1 or 2), otherwise returns zero */ typedef int (*ProcessUIArgs) (rdpSettings* settings, const char* opt, const char* val, void* user_data); FREERDP_API int freerdp_parse_args(rdpSettings* settings, int argc, char** argv, ProcessPluginArgs plugin_callback, void* plugin_user_data, ProcessUIArgs ui_callback, void* ui_user_data); #endif /* __ARGS_UTILS_H */ FreeRDP-1.0.2/include/freerdp/utils/bitmap.h000066400000000000000000000016231207112532300205760ustar00rootroot00000000000000/** * FreeRDP: A Remote Desktop Protocol Client * Bitmap File Format Utils * * Copyright 2011 Marc-Andre Moreau * * 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. */ #ifndef __UTILS_BITMAP_H #define __UTILS_BITMAP_H #include FREERDP_API void freerdp_bitmap_write(char* filename, void* data, int width, int height, int bpp); #endif /* __UTILS_BITMAP_H */ FreeRDP-1.0.2/include/freerdp/utils/blob.h000066400000000000000000000017401207112532300202400ustar00rootroot00000000000000/** * FreeRDP: A Remote Desktop Protocol Client * BLOB Utils * * Copyright 2011 Marc-Andre Moreau * * 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. */ #ifndef __BLOB_UTILS_H #define __BLOB_UTILS_H #include struct rdp_blob { void* data; int length; }; typedef struct rdp_blob rdpBlob; FREERDP_API void freerdp_blob_alloc(rdpBlob* blob, int length); FREERDP_API void freerdp_blob_free(rdpBlob* blob); #endif /* __BLOB_UTILS_H */ FreeRDP-1.0.2/include/freerdp/utils/debug.h000066400000000000000000000024511207112532300204100ustar00rootroot00000000000000/** * FreeRDP: A Remote Desktop Protocol Client * Debug Utils * * Copyright 2011 Marc-Andre Moreau * * 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. */ #ifndef __UTILS_DEBUG_H #define __UTILS_DEBUG_H #include "config.h" #include #define DEBUG_NULL(fmt, ...) do { } while (0) #define DEBUG_PRINT(_dbg_str, fmt, ...) printf(_dbg_str fmt "\n" , __FUNCTION__, __LINE__, ## __VA_ARGS__) #define DEBUG_CLASS(_dbg_class, fmt, ...) DEBUG_PRINT("DBG_" #_dbg_class " %s (%d): ", fmt, ## __VA_ARGS__) #define DEBUG_WARN(fmt, ...) DEBUG_PRINT("Warning %s (%d): ", fmt, ## __VA_ARGS__) #ifdef WITH_DEBUG #define DEBUG(fmt, ...) DEBUG_PRINT("DBG %s (%d): ", fmt, ## __VA_ARGS__) #else #define DEBUG(fmt, ...) DEBUG_NULL(fmt, ## __VA_ARGS__) #endif #endif /* __UTILS_DEBUG_H */ FreeRDP-1.0.2/include/freerdp/utils/dsp.h000066400000000000000000000023671207112532300201160ustar00rootroot00000000000000/** * FreeRDP: A Remote Desktop Protocol client. * Digital Sound Processing * * Copyright 2010-2011 Vic Lee * * 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. */ #ifndef __DSP_UTILS_H #define __DSP_UTILS_H #include struct _ADPCM { sint16 last_sample[2]; sint16 last_step[2]; }; typedef struct _ADPCM ADPCM; FREERDP_API uint8* dsp_resample(uint8* src, int bytes_per_sample, uint32 schan, uint32 srate, int sframes, uint32 rchan, uint32 rrate, int * prframes); FREERDP_API uint8* dsp_decode_ima_adpcm(ADPCM* adpcm, uint8* src, int size, int channels, int block_size, int* out_size); FREERDP_API uint8* dsp_encode_ima_adpcm(ADPCM* adpcm, uint8* src, int size, int channels, int block_size, int* out_size); #endif /* __DSP_UTILS_H */ FreeRDP-1.0.2/include/freerdp/utils/event.h000066400000000000000000000016771207112532300204540ustar00rootroot00000000000000/** * FreeRDP: A Remote Desktop Protocol client. * Events * * Copyright 2011 Vic Lee * * 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. */ #ifndef __EVENT_UTILS_H #define __EVENT_UTILS_H #include #include FREERDP_API RDP_EVENT* freerdp_event_new(uint16 event_class, uint16 event_type, RDP_EVENT_CALLBACK on_event_free_callback, void* user_data); FREERDP_API void freerdp_event_free(RDP_EVENT* event); #endif FreeRDP-1.0.2/include/freerdp/utils/file.h000066400000000000000000000030541207112532300202410ustar00rootroot00000000000000/** * FreeRDP: A Remote Desktop Protocol Client * File Utils * * Copyright 2011 Marc-Andre Moreau * * 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. */ #ifndef __FILE_UTILS_H #define __FILE_UTILS_H #include #include #include FREERDP_API void freerdp_mkdir(char* path); FREERDP_API boolean freerdp_check_file_exists(char* file); FREERDP_API char* freerdp_get_home_path(rdpSettings* settings); FREERDP_API char* freerdp_get_config_path(rdpSettings* settings); FREERDP_API char* freerdp_get_current_path(rdpSettings* settings); FREERDP_API char* freerdp_construct_path(char* base_path, char* relative_path); FREERDP_API char* freerdp_append_shared_library_suffix(char* file_path); FREERDP_API char* freerdp_get_parent_path(char* base_path, int depth); FREERDP_API boolean freerdp_path_contains_separator(char* path); FREERDP_API boolean freerdp_detect_development_mode(rdpSettings* settings); FREERDP_API void freerdp_detect_paths(rdpSettings* settings); #endif /* __FILE_UTILS_H */ FreeRDP-1.0.2/include/freerdp/utils/hexdump.h000066400000000000000000000016141207112532300207740ustar00rootroot00000000000000/** * FreeRDP: A Remote Desktop Protocol Client * Hex Dump Utils * * Copyright 2011 Marc-Andre Moreau * * 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. */ #ifndef __UTILS_HEXDUMP_H #define __UTILS_HEXDUMP_H #include #define FREERDP_HEXDUMP_LINE_LENGTH 16 FREERDP_API void freerdp_hexdump(uint8* data, int length); #endif /* __UTILS_HEXDUMP_H */ FreeRDP-1.0.2/include/freerdp/utils/list.h000066400000000000000000000026101207112532300202720ustar00rootroot00000000000000/** * FreeRDP: A Remote Desktop Protocol Client * Double-linked List Utils * * Copyright 2011 Vic Lee * * 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. */ #ifndef __LIST_UTILS_H #define __LIST_UTILS_H #include #include typedef struct _LIST_ITEM LIST_ITEM; struct _LIST_ITEM { void* data; LIST_ITEM* prev; LIST_ITEM* next; }; typedef struct _LIST LIST; struct _LIST { int count; LIST_ITEM* head; LIST_ITEM* tail; }; FREERDP_API LIST* list_new(void); FREERDP_API void list_free(LIST* list); FREERDP_API void list_enqueue(LIST* list, void* data); FREERDP_API void* list_dequeue(LIST* list); FREERDP_API void* list_peek(LIST* list); FREERDP_API void* list_next(LIST* list, void* data); #define list_add(_l, _d) list_enqueue(_l, _d) FREERDP_API void* list_remove(LIST* list, void* data); FREERDP_API int list_size(LIST* list); #endif /* __LIST_UTILS_H */ FreeRDP-1.0.2/include/freerdp/utils/load_plugin.h000066400000000000000000000024111207112532300216130ustar00rootroot00000000000000/** * FreeRDP: A Remote Desktop Protocol Client * Plugin Loading Utils * * Copyright 2011 Vic Lee * * 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. */ #ifndef __LOAD_PLUGIN_UTILS_H #define __LOAD_PLUGIN_UTILS_H #include #include FREERDP_API void* freerdp_open_library(const char* file); FREERDP_API void* freerdp_get_library_symbol(void* library, const char* name); FREERDP_API boolean freerdp_close_library(void* library); FREERDP_API void* freerdp_load_library_symbol(const char* file, const char* name); FREERDP_API void* freerdp_load_plugin(const char* name, const char* entry_name); FREERDP_API void* freerdp_load_channel_plugin(rdpSettings* settings, const char* name, const char* entry_name); #endif /* __LOAD_PLUGIN_UTILS_H */ FreeRDP-1.0.2/include/freerdp/utils/memory.h000066400000000000000000000020361207112532300206310ustar00rootroot00000000000000/** * FreeRDP: A Remote Desktop Protocol Client * Memory Utils * * Copyright 2009-2011 Jay Sorg * * 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. */ #ifndef __MEMORY_UTILS_H #define __MEMORY_UTILS_H #include #include FREERDP_API void* xmalloc(size_t size); FREERDP_API void* xzalloc(size_t size); FREERDP_API void* xrealloc(void* ptr, size_t size); FREERDP_API void xfree(void* ptr); FREERDP_API char* xstrdup(const char* str); #define xnew(_type) (_type*)xzalloc(sizeof(_type)) #endif /* __MEMORY_UTILS_H */ FreeRDP-1.0.2/include/freerdp/utils/mutex.h000066400000000000000000000017721207112532300204710ustar00rootroot00000000000000/** * FreeRDP: A Remote Desktop Protocol Client * Mutex Utils * * Copyright 2011 Vic Lee * * 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. */ #ifndef __MUTEX_UTILS_H #define __MUTEX_UTILS_H #include typedef void* freerdp_mutex; FREERDP_API freerdp_mutex freerdp_mutex_new(void); FREERDP_API void freerdp_mutex_free(freerdp_mutex mutex); FREERDP_API void freerdp_mutex_lock(freerdp_mutex mutex); FREERDP_API void freerdp_mutex_unlock(freerdp_mutex mutex); #endif /* __MUTEX_UTILS_H */ FreeRDP-1.0.2/include/freerdp/utils/passphrase.h000066400000000000000000000016511207112532300214740ustar00rootroot00000000000000/** * FreeRDP: A Remote Desktop Protocol Client * Passphrase Handling Utils * * Copyright 2011 Shea Levy * * 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. */ #ifndef __UTILS_PASSPHRASE_H #define __UTILS_PASSPHRASE_H #include #include FREERDP_API char* freerdp_passphrase_read(const char* prompt, char* buf, size_t bufsiz, int from_stdin); #endif /* __UTILS_PASSPHRASE_H */ FreeRDP-1.0.2/include/freerdp/utils/pcap.h000066400000000000000000000046511207112532300202510ustar00rootroot00000000000000/** * FreeRDP: A Remote Desktop Protocol Client * pcap File Format Utils * * Copyright 2011 Marc-Andre Moreau * * 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. */ #ifndef __UTILS_PCAP_H #define __UTILS_PCAP_H #include #include struct _pcap_header { uint32 magic_number; /* magic number */ uint16 version_major; /* major version number */ uint16 version_minor; /* minor version number */ sint32 thiszone; /* GMT to local correction */ uint32 sigfigs; /* accuracy of timestamps */ uint32 snaplen; /* max length of captured packets, in octets */ uint32 network; /* data link type */ }; typedef struct _pcap_header pcap_header; struct _pcap_record_header { uint32 ts_sec; /* timestamp seconds */ uint32 ts_usec; /* timestamp microseconds */ uint32 incl_len; /* number of octets of packet saved in file */ uint32 orig_len; /* actual length of packet */ }; typedef struct _pcap_record_header pcap_record_header; typedef struct _pcap_record pcap_record; struct _pcap_record { pcap_record_header header; void* data; uint32 length; pcap_record* next; }; struct rdp_pcap { FILE* fp; char* name; boolean write; int file_size; int record_count; pcap_header header; pcap_record* head; pcap_record* tail; pcap_record* record; }; typedef struct rdp_pcap rdpPcap; FREERDP_API rdpPcap* pcap_open(char* name, boolean write); FREERDP_API void pcap_close(rdpPcap* pcap); FREERDP_API void pcap_add_record(rdpPcap* pcap, void* data, uint32 length); FREERDP_API boolean pcap_has_next_record(rdpPcap* pcap); FREERDP_API boolean pcap_get_next_record(rdpPcap* pcap, pcap_record* record); FREERDP_API boolean pcap_get_next_record_header(rdpPcap* pcap, pcap_record* record); FREERDP_API boolean pcap_get_next_record_content(rdpPcap* pcap, pcap_record* record); FREERDP_API void pcap_flush(rdpPcap* pcap); #endif /* __UTILS_PCAP_H */ FreeRDP-1.0.2/include/freerdp/utils/print.h000066400000000000000000000015121207112532300204530ustar00rootroot00000000000000/** * FreeRDP: A Remote Desktop Protocol Client * Print Utils * * Copyright 2011 Marc-Andre Moreau * * 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. */ #ifndef __PRINT_UTILS_H #define __PRINT_UTILS_H #include #ifdef _WIN32 #define snprintf sprintf_s #endif #endif /* __PRINT_UTILS_H */ FreeRDP-1.0.2/include/freerdp/utils/profiler.h000066400000000000000000000043051207112532300211440ustar00rootroot00000000000000/** * FreeRDP: A Remote Desktop Protocol Client * Profiler Utils * * Copyright 2011 Stephen Erisman * * 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. */ #ifndef __UTILS_PROFILER_H #define __UTILS_PROFILER_H #include #include "config.h" #include #include #include struct _PROFILER { char* name; STOPWATCH* stopwatch; }; typedef struct _PROFILER PROFILER; FREERDP_API PROFILER* profiler_create(char* name); FREERDP_API void profiler_free(PROFILER* profiler); FREERDP_API void profiler_enter(PROFILER* profiler); FREERDP_API void profiler_exit(PROFILER* profiler); FREERDP_API void profiler_print_header(); FREERDP_API void profiler_print(PROFILER* profiler); FREERDP_API void profiler_print_footer(); #ifdef WITH_PROFILER #define IF_PROFILER(then) then #define PROFILER_DEFINE(prof) PROFILER* prof #define PROFILER_CREATE(prof,name) prof = profiler_create(name) #define PROFILER_FREE(prof) profiler_free(prof) #define PROFILER_ENTER(prof) profiler_enter(prof) #define PROFILER_EXIT(prof) profiler_exit(prof) #define PROFILER_PRINT_HEADER profiler_print_header() #define PROFILER_PRINT(prof) profiler_print(prof) #define PROFILER_PRINT_FOOTER profiler_print_footer() #else #define IF_PROFILER(then) do { } while (0) #define PROFILER_DEFINE(prof) void* prof #define PROFILER_CREATE(prof,name) do { } while (0) #define PROFILER_FREE(prof) do { } while (0) #define PROFILER_ENTER(prof) do { } while (0) #define PROFILER_EXIT(prof) do { } while (0) #define PROFILER_PRINT_HEADER do { } while (0) #define PROFILER_PRINT(prof) do { } while (0) #define PROFILER_PRINT_FOOTER do { } while (0) #endif #endif /* __UTILS_PROFILER_H */ FreeRDP-1.0.2/include/freerdp/utils/rail.h000066400000000000000000000030441207112532300202500ustar00rootroot00000000000000/** * FreeRDP: A Remote Desktop Protocol Client * Remote Applications Integrated Locally (RAIL) Utils * * Copyright 2011 Marc-Andre Moreau * * 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. */ #ifndef __RAIL_UTILS_H #define __RAIL_UTILS_H #include #include #include #include #define RAIL_ARRAY_SIZE(array) (sizeof(array) / sizeof(array[0])) FREERDP_API void rail_unicode_string_alloc(UNICODE_STRING* unicode_string, uint16 cbString); FREERDP_API void rail_unicode_string_free(UNICODE_STRING* unicode_string); FREERDP_API void rail_read_unicode_string(STREAM* s, UNICODE_STRING* unicode_string); FREERDP_API void rail_write_unicode_string(STREAM* s, UNICODE_STRING* unicode_string); FREERDP_API void rail_write_unicode_string_value(STREAM* s, UNICODE_STRING* unicode_string); FREERDP_API void* rail_clone_order(uint32 event_type, void* order); FREERDP_API void rail_free_cloned_order(uint32 event_type, void* order); #endif /* __RAIL_UTILS_H */ FreeRDP-1.0.2/include/freerdp/utils/rect.h000066400000000000000000000022701207112532300202560ustar00rootroot00000000000000/** * FreeRDP: A Remote Desktop Protocol Client * Rectangle Utils * * Copyright 2011 Marc-Andre Moreau * * 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. */ #ifndef __RECT_UTILS_H #define __RECT_UTILS_H #include #include #include FREERDP_API void freerdp_read_rectangle_16(STREAM* s, RECTANGLE_16* rectangle_16); FREERDP_API void freerdp_write_rectangle_16(STREAM* s, RECTANGLE_16* rectangle_16); FREERDP_API RECTANGLE_16* freerdp_rectangle_16_new(uint16 left, uint16 top, uint16 right, uint16 bottom); FREERDP_API void freerdp_rectangle_16_free(RECTANGLE_16* rectangle_16); #endif /* __RECT_UTILS_H */ FreeRDP-1.0.2/include/freerdp/utils/registry.h000066400000000000000000000033151207112532300211720ustar00rootroot00000000000000/** * FreeRDP: A Remote Desktop Protocol Client * Registry Utils * * Copyright 2011 Marc-Andre Moreau * * 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. */ #ifndef __REGISTRY_UTILS_H #define __REGISTRY_UTILS_H typedef struct rdp_registry rdpRegistry; #include #include #include #include #include #include #include enum REG_TYPE { REG_TYPE_NONE, REG_TYPE_STRING, REG_TYPE_INTEGER, REG_TYPE_BOOLEAN, REG_TYPE_SECTION }; typedef struct { uint8 type; char* name; uint32 length; void* value; } REG_ENTRY; typedef REG_ENTRY REG_STRING; typedef REG_ENTRY REG_INTEGER; typedef REG_ENTRY REG_BOOLEAN; typedef REG_ENTRY REG_SECTION; struct rdp_registry { FILE* fp; char* path; char* file; char* home; boolean available; struct rdp_settings* settings; }; FREERDP_API void registry_open(rdpRegistry* registry); FREERDP_API void registry_close(rdpRegistry* registry); FREERDP_API void registry_init(rdpRegistry* registry); FREERDP_API rdpRegistry* registry_new(rdpSettings* settings); FREERDP_API void registry_free(rdpRegistry* registry); #endif /* __REGISTRY_UTILS_H */ FreeRDP-1.0.2/include/freerdp/utils/semaphore.h000066400000000000000000000020331207112532300213010ustar00rootroot00000000000000/** * FreeRDP: A Remote Desktop Protocol Client * Semaphore Utils * * Copyright 2011 Marc-Andre Moreau * * 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. */ #ifndef __SEMAPHORE_UTILS_H #define __SEMAPHORE_UTILS_H #include typedef void* freerdp_sem; FREERDP_API freerdp_sem freerdp_sem_new(int iv); FREERDP_API void freerdp_sem_free(freerdp_sem sem); FREERDP_API void freerdp_sem_signal(freerdp_sem sem); FREERDP_API void freerdp_sem_wait(freerdp_sem sem); #endif /* __SEMAPHORE_UTILS_H */ FreeRDP-1.0.2/include/freerdp/utils/signal.h000066400000000000000000000020261207112532300205750ustar00rootroot00000000000000/** * FreeRDP: A Remote Desktop Protocol Client * Signal handling * * Copyright 2011 Shea Levy * * 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. */ #ifndef __UTILS_SIGNAL_H #define __UTILS_SIGNAL_H #include #ifndef _WIN32 #include #include extern volatile sig_atomic_t terminal_needs_reset; extern int terminal_fildes; extern struct termios orig_flags; extern struct termios new_flags; #endif FREERDP_API int freerdp_handle_signals(void); #endif /* __UTILS_SIGNAL_H */ FreeRDP-1.0.2/include/freerdp/utils/sleep.h000066400000000000000000000016351207112532300204350ustar00rootroot00000000000000/** * FreeRDP: A Remote Desktop Protocol Client * Sleep Utils * * Copyright 2011 Marc-Andre Moreau * * 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. */ #ifndef __SLEEP_UTILS_H #define __SLEEP_UTILS_H #include #include FREERDP_API void freerdp_sleep(uint32 seconds); FREERDP_API void freerdp_usleep(uint32 useconds); #endif /* __SLEEP_UTILS_H */ FreeRDP-1.0.2/include/freerdp/utils/stopwatch.h000066400000000000000000000026411207112532300213370ustar00rootroot00000000000000/** * FreeRDP: A Remote Desktop Protocol Client * Stopwatch Utils * * Copyright 2011 Stephen Erisman * * 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. */ #ifndef __UTILS_STOPWATCH_H #define __UTILS_STOPWATCH_H #include #include #include #include struct _STOPWATCH { clock_t start; clock_t end; double elapsed; clock_t count; }; typedef struct _STOPWATCH STOPWATCH; FREERDP_API STOPWATCH* stopwatch_create(); FREERDP_API void stopwatch_free(STOPWATCH* stopwatch); FREERDP_API void stopwatch_start(STOPWATCH* stopwatch); FREERDP_API void stopwatch_stop(STOPWATCH* stopwatch); FREERDP_API void stopwatch_reset(STOPWATCH* stopwatch); FREERDP_API double stopwatch_get_elapsed_time_in_seconds(STOPWATCH* stopwatch); FREERDP_API void stopwatch_get_elapsed_time_in_useconds(STOPWATCH* stopwatch, uint32* sec, uint32* usec); #endif /* __UTILS_STOPWATCH_H */ FreeRDP-1.0.2/include/freerdp/utils/stream.h000066400000000000000000000130071207112532300206140ustar00rootroot00000000000000/** * FreeRDP: A Remote Desktop Protocol Client * Stream Utils * * Copyright 2009-2011 Jay Sorg * Copyright 2011 Vic Lee * * 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. */ #ifndef __STREAM_UTILS_H #define __STREAM_UTILS_H #include #include #include struct _STREAM { int size; uint8* p; uint8* data; }; typedef struct _STREAM STREAM; FREERDP_API STREAM* stream_new(int size); FREERDP_API void stream_free(STREAM* stream); #define stream_attach(_s, _buf, _size) do { \ _s->size = _size; \ _s->data = _buf; \ _s->p = _buf; } while (0) #define stream_detach(_s) memset(_s, 0, sizeof(STREAM)) #define stream_clear(_s) memset(_s->data, 0, _s->size) FREERDP_API void stream_extend(STREAM* stream, int request_size); #define stream_check_size(_s, _n) \ while (_s->p - _s->data + (_n) > _s->size) \ stream_extend(_s, _n) #define stream_get_pos(_s) (_s->p - _s->data) #define stream_set_pos(_s,_m) _s->p = _s->data + (_m) #define stream_seek(_s,_offset) _s->p += (_offset) #define stream_rewind(_s,_offset) _s->p -= (_offset) #define stream_seal(_s) _s->size = (_s->p - _s->data) #define stream_get_mark(_s,_mark) _mark = _s->p #define stream_set_mark(_s,_mark) _s->p = _mark #define stream_get_head(_s) _s->data #define stream_get_tail(_s) _s->p #define stream_get_length(_s) (_s->p - _s->data) #define stream_get_data(_s) (_s->data) #define stream_get_size(_s) (_s->size) #define stream_get_left(_s) (_s->size - (_s->p - _s->data)) #define stream_read_uint8(_s, _v) do { _v = *_s->p++; } while (0) #define stream_read_uint16(_s, _v) do { _v = \ (uint16)(*_s->p) + \ (((uint16)(*(_s->p + 1))) << 8); \ _s->p += 2; } while (0) #define stream_read_uint32(_s, _v) do { _v = \ (uint32)(*_s->p) + \ (((uint32)(*(_s->p + 1))) << 8) + \ (((uint32)(*(_s->p + 2))) << 16) + \ (((uint32)(*(_s->p + 3))) << 24); \ _s->p += 4; } while (0) #define stream_read_uint64(_s, _v) do { _v = \ (uint64)(*_s->p) + \ (((uint64)(*(_s->p + 1))) << 8) + \ (((uint64)(*(_s->p + 2))) << 16) + \ (((uint64)(*(_s->p + 3))) << 24) + \ (((uint64)(*(_s->p + 4))) << 32) + \ (((uint64)(*(_s->p + 5))) << 40) + \ (((uint64)(*(_s->p + 6))) << 48) + \ (((uint64)(*(_s->p + 7))) << 56); \ _s->p += 8; } while (0) #define stream_read(_s, _b, _n) do { \ memcpy(_b, (_s->p), (_n)); \ _s->p += (_n); \ } while (0) #define stream_write_uint8(_s, _v) do { \ *_s->p++ = (uint8)(_v); } while (0) #define stream_write_uint16(_s, _v) do { \ *_s->p++ = (_v) & 0xFF; \ *_s->p++ = ((_v) >> 8) & 0xFF; } while (0) #define stream_write_uint32(_s, _v) do { \ *_s->p++ = (_v) & 0xFF; \ *_s->p++ = ((_v) >> 8) & 0xFF; \ *_s->p++ = ((_v) >> 16) & 0xFF; \ *_s->p++ = ((_v) >> 24) & 0xFF; } while (0) #define stream_write_uint64(_s, _v) do { \ *_s->p++ = (uint64)(_v) & 0xFF; \ *_s->p++ = ((uint64)(_v) >> 8) & 0xFF; \ *_s->p++ = ((uint64)(_v) >> 16) & 0xFF; \ *_s->p++ = ((uint64)(_v) >> 24) & 0xFF; \ *_s->p++ = ((uint64)(_v) >> 32) & 0xFF; \ *_s->p++ = ((uint64)(_v) >> 40) & 0xFF; \ *_s->p++ = ((uint64)(_v) >> 48) & 0xFF; \ *_s->p++ = ((uint64)(_v) >> 56) & 0xFF; } while (0) #define stream_write(_s, _b, _n) do { \ memcpy(_s->p, (_b), (_n)); \ _s->p += (_n); \ } while (0) #define stream_write_zero(_s, _n) do { \ memset(_s->p, '\0', (_n)); \ _s->p += (_n); \ } while (0) #define stream_set_byte(_s, _v, _n) do { \ memset(_s->p, _v, (_n)); \ _s->p += (_n); \ } while (0) #define stream_peek_uint8(_s, _v) do { _v = *_s->p; } while (0) #define stream_peek_uint16(_s, _v) do { _v = \ (uint16)(*_s->p) + \ (((uint16)(*(_s->p + 1))) << 8); \ } while (0) #define stream_peek_uint32(_s, _v) do { _v = \ (uint32)(*_s->p) + \ (((uint32)(*(_s->p + 1))) << 8) + \ (((uint32)(*(_s->p + 2))) << 16) + \ (((uint32)(*(_s->p + 3))) << 24); \ } while (0) #define stream_peek_uint64(_s, _v) do { _v = \ (uint64)(*_s->p) + \ (((uint64)(*(_s->p + 1))) << 8) + \ (((uint64)(*(_s->p + 2))) << 16) + \ (((uint64)(*(_s->p + 3))) << 24) + \ (((uint64)(*(_s->p + 4))) << 32) + \ (((uint64)(*(_s->p + 5))) << 40) + \ (((uint64)(*(_s->p + 6))) << 48) + \ (((uint64)(*(_s->p + 7))) << 56); \ } while (0) #define stream_seek_uint8(_s) stream_seek(_s, 1) #define stream_seek_uint16(_s) stream_seek(_s, 2) #define stream_seek_uint32(_s) stream_seek(_s, 4) #define stream_seek_uint64(_s) stream_seek(_s, 8) #define stream_read_uint16_be(_s, _v) do { _v = \ (((uint16)(*_s->p)) << 8) + \ (uint16)(*(_s->p + 1)); \ _s->p += 2; } while (0) #define stream_read_uint32_be(_s, _v) do { _v = \ (((uint32)(*(_s->p))) << 8) + \ (((uint32)(*(_s->p + 1)))) + \ (((uint32)(*(_s->p + 2))) << 24) + \ (((uint32)(*(_s->p + 3))) << 16); \ _s->p += 4; } while (0) #define stream_write_uint16_be(_s, _v) do { \ *_s->p++ = ((_v) >> 8) & 0xFF; \ *_s->p++ = (_v) & 0xFF; } while (0) #define stream_write_uint32_be(_s, _v) do { \ stream_write_uint16_be(_s, ((_v) >> 16 & 0xFFFF)); \ stream_write_uint16_be(_s, ((_v) & 0xFFFF)); \ } while (0) #define stream_copy(_dst, _src, _n) do { \ memcpy(_dst->p, _src->p, _n); \ _dst->p += _n; \ _src->p += _n; \ } while (0) #endif /* __STREAM_UTILS_H */ FreeRDP-1.0.2/include/freerdp/utils/string.h000066400000000000000000000022071207112532300206270ustar00rootroot00000000000000/** * FreeRDP: A Remote Desktop Protocol Client * String Utils * * Copyright 2011 Marc-Andre Moreau * * 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. */ #ifndef __STRING_UTILS_H #define __STRING_UTILS_H #include #include #include #include struct rdp_string { char* ascii; char* unicode; uint32 length; }; typedef struct rdp_string rdpString; FREERDP_API void freerdp_string_read_length32(STREAM* s, rdpString* string, UNICONV* uniconv); FREERDP_API void freerdp_string_free(rdpString* string); #endif /* __STRING_UTILS_H */ FreeRDP-1.0.2/include/freerdp/utils/svc_plugin.h000066400000000000000000000051301207112532300214700ustar00rootroot00000000000000/** * FreeRDP: A Remote Desktop Protocol client. * Static Virtual Channel Interface * * Copyright 2009-2011 Jay Sorg * Copyright 2010-2011 Vic Lee * * 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. */ #ifndef __SVC_PLUGIN_UTILS_H #define __SVC_PLUGIN_UTILS_H /* static channel plugin base implementation */ #include #include #include #include #include typedef struct rdp_svc_plugin_private rdpSvcPluginPrivate; typedef struct rdp_svc_plugin rdpSvcPlugin; struct rdp_svc_plugin { CHANNEL_ENTRY_POINTS_EX channel_entry_points; CHANNEL_DEF channel_def; int interval_ms; void (*connect_callback)(rdpSvcPlugin* plugin); void (*receive_callback)(rdpSvcPlugin* plugin, STREAM* data_in); void (*event_callback)(rdpSvcPlugin* plugin, RDP_EVENT* event); void (*interval_callback)(rdpSvcPlugin* plugin); void (*terminate_callback)(rdpSvcPlugin* plugin); rdpSvcPluginPrivate* priv; }; FREERDP_API void svc_plugin_init(rdpSvcPlugin* plugin, CHANNEL_ENTRY_POINTS* pEntryPoints); FREERDP_API int svc_plugin_send(rdpSvcPlugin* plugin, STREAM* data_out); FREERDP_API int svc_plugin_send_event(rdpSvcPlugin* plugin, RDP_EVENT* event); #define svc_plugin_get_data(_p) (RDP_PLUGIN_DATA*)(((rdpSvcPlugin*)_p)->channel_entry_points.pExtendedData) #ifdef WITH_DEBUG_SVC #define DEBUG_SVC(fmt, ...) DEBUG_CLASS(SVC, fmt, ## __VA_ARGS__) #else #define DEBUG_SVC(fmt, ...) DEBUG_NULL(fmt, ## __VA_ARGS__) #endif #define DEFINE_SVC_PLUGIN(_prefix, _name, _options) \ \ int VirtualChannelEntry(PCHANNEL_ENTRY_POINTS pEntryPoints) \ { \ _prefix##Plugin* _p; \ \ _p = xnew(_prefix##Plugin); \ \ _p->plugin.channel_def.options = _options; \ strcpy(_p->plugin.channel_def.name, _name); \ \ _p->plugin.connect_callback = _prefix##_process_connect; \ _p->plugin.receive_callback = _prefix##_process_receive; \ _p->plugin.event_callback = _prefix##_process_event; \ _p->plugin.terminate_callback = _prefix##_process_terminate; \ \ svc_plugin_init((rdpSvcPlugin*)_p, pEntryPoints); \ \ return 1; \ } #endif /* __SVC_PLUGIN_UTILS_H */ FreeRDP-1.0.2/include/freerdp/utils/thread.h000066400000000000000000000037261207112532300205770ustar00rootroot00000000000000/** * FreeRDP: A Remote Desktop Protocol client. * Thread Utils * * Copyright 2011 Vic Lee * * 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. */ #ifndef __THREAD_UTILS_H #define __THREAD_UTILS_H #include #include #include #include #ifndef _WIN32 #include #endif typedef struct _freerdp_thread freerdp_thread; struct _freerdp_thread { freerdp_mutex* mutex; struct wait_obj* signals[5]; int num_signals; int status; }; FREERDP_API freerdp_thread* freerdp_thread_new(void); FREERDP_API void freerdp_thread_start(freerdp_thread* thread, void* func, void* arg); FREERDP_API void freerdp_thread_stop(freerdp_thread* thread); FREERDP_API void freerdp_thread_free(freerdp_thread* thread); #define freerdp_thread_wait(_t) wait_obj_select(_t->signals, _t->num_signals, -1) #define freerdp_thread_wait_timeout(_t, _timeout) wait_obj_select(_t->signals, _t->num_signals, _timeout) #define freerdp_thread_is_stopped(_t) wait_obj_is_set(_t->signals[0]) #define freerdp_thread_is_running(_t) (_t->status == 1) #define freerdp_thread_quit(_t) do { \ _t->status = -1; \ wait_obj_clear(_t->signals[0]); } while (0) #define freerdp_thread_signal(_t) wait_obj_set(_t->signals[1]) #define freerdp_thread_reset(_t) wait_obj_clear(_t->signals[1]) #define freerdp_thread_lock(_t) freerdp_mutex_lock(_t->mutex) #define freerdp_thread_unlock(_t) freerdp_mutex_unlock(_t->mutex) #endif /* __THREAD_UTILS_H */ FreeRDP-1.0.2/include/freerdp/utils/unicode.h000066400000000000000000000027521207112532300207540ustar00rootroot00000000000000/** * FreeRDP: A Remote Desktop Protocol Client * Unicode Utils * * Copyright 2011 Marc-Andre Moreau * * 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. */ #ifndef __UNICODE_UTILS_H #define __UNICODE_UTILS_H #include #include #include #define DEFAULT_CODEPAGE "UTF-8" #define WINDOWS_CODEPAGE "UTF-16LE" #ifdef HAVE_ICONV #include #endif #ifndef ICONV_CONST #define ICONV_CONST "" #endif struct _UNICONV { int iconv; #ifdef HAVE_ICONV iconv_t* in_iconv_h; iconv_t* out_iconv_h; #endif }; typedef struct _UNICONV UNICONV; FREERDP_API UNICONV* freerdp_uniconv_new(); FREERDP_API void freerdp_uniconv_free(UNICONV *uniconv); FREERDP_API char* freerdp_uniconv_in(UNICONV *uniconv, unsigned char* pin, size_t in_len); FREERDP_API char* freerdp_uniconv_out(UNICONV *uniconv, char *str, size_t *pout_len); FREERDP_API void freerdp_uniconv_uppercase(UNICONV *uniconv, char *wstr, int length); #endif /* __UNICODE_UTILS_H */ FreeRDP-1.0.2/include/freerdp/utils/wait_obj.h000066400000000000000000000023451207112532300211220ustar00rootroot00000000000000/** * FreeRDP: A Remote Desktop Protocol client. * Virtual Channel Manager * * Copyright 2009-2011 Jay Sorg * * 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. */ #ifndef __WAIT_OBJ_UTILS #define __WAIT_OBJ_UTILS #include FREERDP_API struct wait_obj* wait_obj_new(void); FREERDP_API struct wait_obj* wait_obj_new_with_fd(void* fd); FREERDP_API void wait_obj_free(struct wait_obj* obj); FREERDP_API int wait_obj_is_set(struct wait_obj* obj); FREERDP_API void wait_obj_set(struct wait_obj* obj); FREERDP_API void wait_obj_clear(struct wait_obj* obj); FREERDP_API int wait_obj_select(struct wait_obj** listobj, int numobj, int timeout); FREERDP_API void wait_obj_get_fds(struct wait_obj* obj, void** fds, int* count); #endif FreeRDP-1.0.2/include/freerdp/window.h000066400000000000000000000210361207112532300174710ustar00rootroot00000000000000/** * FreeRDP: A Remote Desktop Protocol Client * Window Alternate Secondary Drawing Orders Interface API * * Copyright 2011 Marc-Andre Moreau * * 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. */ #ifndef __UPDATE_WINDOW_H #define __UPDATE_WINDOW_H #include #ifdef _WIN32 #include #endif /* Window Order Header Flags */ #define WINDOW_ORDER_TYPE_WINDOW 0x01000000 #define WINDOW_ORDER_TYPE_NOTIFY 0x02000000 #define WINDOW_ORDER_TYPE_DESKTOP 0x04000000 #define WINDOW_ORDER_STATE_NEW 0x10000000 #define WINDOW_ORDER_STATE_DELETED 0x20000000 #define WINDOW_ORDER_FIELD_OWNER 0x00000002 #define WINDOW_ORDER_FIELD_STYLE 0x00000008 #define WINDOW_ORDER_FIELD_SHOW 0x00000010 #define WINDOW_ORDER_FIELD_TITLE 0x00000004 #define WINDOW_ORDER_FIELD_CLIENT_AREA_OFFSET 0x00004000 #define WINDOW_ORDER_FIELD_CLIENT_AREA_SIZE 0x00010000 #define WINDOW_ORDER_FIELD_RP_CONTENT 0x00020000 #define WINDOW_ORDER_FIELD_ROOT_PARENT 0x00040000 #define WINDOW_ORDER_FIELD_WND_OFFSET 0x00000800 #define WINDOW_ORDER_FIELD_WND_CLIENT_DELTA 0x00008000 #define WINDOW_ORDER_FIELD_WND_SIZE 0x00000400 #define WINDOW_ORDER_FIELD_WND_RECTS 0x00000100 #define WINDOW_ORDER_FIELD_VIS_OFFSET 0x00001000 #define WINDOW_ORDER_FIELD_VISIBILITY 0x00000200 #define WINDOW_ORDER_FIELD_ICON_BIG 0x00002000 #define WINDOW_ORDER_ICON 0x40000000 #define WINDOW_ORDER_CACHED_ICON 0x80000000 #define WINDOW_ORDER_FIELD_NOTIFY_VERSION 0x00000008 #define WINDOW_ORDER_FIELD_NOTIFY_TIP 0x00000001 #define WINDOW_ORDER_FIELD_NOTIFY_INFO_TIP 0x00000002 #define WINDOW_ORDER_FIELD_NOTIFY_STATE 0x00000004 #define WINDOW_ORDER_FIELD_DESKTOP_NONE 0x00000001 #define WINDOW_ORDER_FIELD_DESKTOP_HOOKED 0x00000002 #define WINDOW_ORDER_FIELD_DESKTOP_ARC_COMPLETED 0x00000004 #define WINDOW_ORDER_FIELD_DESKTOP_ARC_BEGAN 0x00000008 #define WINDOW_ORDER_FIELD_DESKTOP_ZORDER 0x00000010 #define WINDOW_ORDER_FIELD_DESKTOP_ACTIVE_WND 0x00000020 /* Window Show States */ #define WINDOW_HIDE 0x00 #define WINDOW_SHOW_MINIMIZED 0x02 #define WINDOW_SHOW_MAXIMIZED 0x03 #define WINDOW_SHOW 0x05 /* Window Styles */ #ifndef _WIN32 #define WS_BORDER 0x00800000 #define WS_CAPTION 0x00C00000 #define WS_CHILD 0x40000000 #define WS_CLIPCHILDREN 0x02000000 #define WS_CLIPSIBLINGS 0x04000000 #define WS_DISABLED 0x08000000 #define WS_DLGFRAME 0x00400000 #define WS_GROUP 0x00020000 #define WS_HSCROLL 0x00100000 #define WS_ICONIC 0x20000000 #define WS_MAXIMIZE 0x01000000 #define WS_MAXIMIZEBOX 0x00010000 #define WS_MINIMIZE 0x20000000 #define WS_MINIMIZEBOX 0x00020000 #define WS_OVERLAPPED 0x00000000 #define WS_OVERLAPPEDWINDOW (WS_OVERLAPPED | WS_CAPTION | WS_SYSMENU | WS_THICKFRAME | WS_MINIMIZEBOX | WS_MAXIMIZEBOX) #define WS_POPUP 0x80000000 #define WS_POPUPWINDOW (WS_POPUP | WS_BORDER | WS_SYSMENU) #define WS_SIZEBOX 0x00040000 #define WS_SYSMENU 0x00080000 #define WS_TABSTOP 0x00010000 #define WS_THICKFRAME 0x00040000 #define WS_VISIBLE 0x10000000 #define WS_VSCROLL 0x00200000 #endif /* Extended Window Styles */ #ifndef _WIN32 #define WS_EX_ACCEPTFILES 0x00000010 #define WS_EX_APPWINDOW 0x00040000 #define WS_EX_CLIENTEDGE 0x00000200 #define WS_EX_COMPOSITED 0x02000000 #define WS_EX_CONTEXTHELP 0x00000400 #define WS_EX_CONTROLPARENT 0x00010000 #define WS_EX_DLGMODALFRAME 0x00000001 #define WS_EX_LAYERED 0x00080000 #define WS_EX_LAYOUTRTL 0x00400000 #define WS_EX_LEFT 0x00000000 #define WS_EX_LEFTSCROLLBAR 0x00004000 #define WS_EX_LTRREADING 0x00000000 #define WS_EX_MDICHILD 0x00000040 #define WS_EX_NOACTIVATE 0x08000000 #define WS_EX_NOINHERITLAYOUT 0x00100000 #define WS_EX_NOPARENTNOTIFY 0x00000004 #define WS_EX_OVERLAPPEDWINDOW (WS_EX_WINDOWEDGE | WS_EX_CLIENTEDGE) #define WS_EX_PALETTEWINDOW (WS_EX_WINDOWEDGE | WS_EX_TOOLWINDOW | WS_EX_TOPMOST) #define WS_EX_RIGHT 0x00001000 #define WS_EX_RIGHTSCROLLBAR 0x00000000 #define WS_EX_RTLREADING 0x00002000 #define WS_EX_STATICEDGE 0x00020000 #define WS_EX_TOOLWINDOW 0x00000080 #define WS_EX_TOPMOST 0x00000008 #define WS_EX_TRANSPARENT 0x00000020 #define WS_EX_WINDOWEDGE 0x00000100 #endif struct _WINDOW_ORDER_INFO { uint32 windowId; uint32 fieldFlags; uint32 notifyIconId; }; typedef struct _WINDOW_ORDER_INFO WINDOW_ORDER_INFO; struct _ICON_INFO { uint32 cacheEntry; uint32 cacheId; uint32 bpp; uint32 width; uint32 height; uint32 cbColorTable; uint32 cbBitsMask; uint32 cbBitsColor; uint8* bitsMask; uint8* colorTable; uint8* bitsColor; }; typedef struct _ICON_INFO ICON_INFO; struct _CACHED_ICON_INFO { uint32 cacheEntry; uint32 cacheId; }; typedef struct _CACHED_ICON_INFO CACHED_ICON_INFO; struct _NOTIFY_ICON_INFOTIP { uint32 timeout; uint32 flags; UNICODE_STRING text; UNICODE_STRING title; }; typedef struct _NOTIFY_ICON_INFOTIP NOTIFY_ICON_INFOTIP; struct _WINDOW_STATE_ORDER { uint32 ownerWindowId; uint32 style; uint32 extendedStyle; uint32 showState; UNICODE_STRING titleInfo; uint32 clientOffsetX; uint32 clientOffsetY; uint32 clientAreaWidth; uint32 clientAreaHeight; uint32 RPContent; uint32 rootParentHandle; uint32 windowOffsetX; uint32 windowOffsetY; uint32 windowClientDeltaX; uint32 windowClientDeltaY; uint32 windowWidth; uint32 windowHeight; uint32 numWindowRects; RECTANGLE_16* windowRects; uint32 visibleOffsetX; uint32 visibleOffsetY; uint32 numVisibilityRects; RECTANGLE_16* visibilityRects; }; typedef struct _WINDOW_STATE_ORDER WINDOW_STATE_ORDER; struct _WINDOW_ICON_ORDER { ICON_INFO* iconInfo; }; typedef struct _WINDOW_ICON_ORDER WINDOW_ICON_ORDER; struct _WINDOW_CACHED_ICON_ORDER { CACHED_ICON_INFO cachedIcon; }; typedef struct _WINDOW_CACHED_ICON_ORDER WINDOW_CACHED_ICON_ORDER; struct _NOTIFY_ICON_STATE_ORDER { uint32 version; UNICODE_STRING toolTip; NOTIFY_ICON_INFOTIP infoTip; uint32 state; ICON_INFO icon; CACHED_ICON_INFO cachedIcon; }; typedef struct _NOTIFY_ICON_STATE_ORDER NOTIFY_ICON_STATE_ORDER; struct _MONITORED_DESKTOP_ORDER { uint32 activeWindowId; uint32 numWindowIds; uint32* windowIds; }; typedef struct _MONITORED_DESKTOP_ORDER MONITORED_DESKTOP_ORDER; typedef void (*pWindowCreate)(rdpContext* context, WINDOW_ORDER_INFO* orderInfo, WINDOW_STATE_ORDER* window_state); typedef void (*pWindowUpdate)(rdpContext* context, WINDOW_ORDER_INFO* orderInfo, WINDOW_STATE_ORDER* window_state); typedef void (*pWindowIcon)(rdpContext* context, WINDOW_ORDER_INFO* orderInfo, WINDOW_ICON_ORDER* window_icon); typedef void (*pWindowCachedIcon)(rdpContext* context, WINDOW_ORDER_INFO* orderInfo, WINDOW_CACHED_ICON_ORDER* window_cached_icon); typedef void (*pWindowDelete)(rdpContext* context, WINDOW_ORDER_INFO* orderInfo); typedef void (*pNotifyIconCreate)(rdpContext* context, WINDOW_ORDER_INFO* orderInfo, NOTIFY_ICON_STATE_ORDER* notify_icon_state); typedef void (*pNotifyIconUpdate)(rdpContext* context, WINDOW_ORDER_INFO* orderInfo, NOTIFY_ICON_STATE_ORDER* notify_icon_state); typedef void (*pNotifyIconDelete)(rdpContext* context, WINDOW_ORDER_INFO* orderInfo); typedef void (*pMonitoredDesktop)(rdpContext* context, WINDOW_ORDER_INFO* orderInfo, MONITORED_DESKTOP_ORDER* monitored_desktop); typedef void (*pNonMonitoredDesktop)(rdpContext* context, WINDOW_ORDER_INFO* orderInfo); struct rdp_window_update { rdpContext* context; /* 0 */ uint32 paddingA[16 - 1]; /* 1 */ pWindowCreate WindowCreate; /* 16 */ pWindowUpdate WindowUpdate; /* 17 */ pWindowIcon WindowIcon; /* 18 */ pWindowCachedIcon WindowCachedIcon; /* 19 */ pWindowDelete WindowDelete; /* 20 */ pNotifyIconCreate NotifyIconCreate; /* 21 */ pNotifyIconUpdate NotifyIconUpdate; /* 22 */ pNotifyIconDelete NotifyIconDelete; /* 23 */ pMonitoredDesktop MonitoredDesktop; /* 24 */ pNonMonitoredDesktop NonMonitoredDesktop; /* 25 */ uint32 paddingB[32 - 26]; /* 26 */ /* internal */ WINDOW_ORDER_INFO orderInfo; WINDOW_STATE_ORDER window_state; WINDOW_ICON_ORDER window_icon; WINDOW_CACHED_ICON_ORDER window_cached_icon; NOTIFY_ICON_STATE_ORDER notify_icon_state; MONITORED_DESKTOP_ORDER monitored_desktop; }; typedef struct rdp_window_update rdpWindowUpdate; #endif /* __UPDATE_WINDOW_H */ FreeRDP-1.0.2/keymaps/000077500000000000000000000000001207112532300144065ustar00rootroot00000000000000FreeRDP-1.0.2/keymaps/CMakeLists.txt000066400000000000000000000005111207112532300171430ustar00rootroot00000000000000install(FILES aliases amiga ataritt empty evdev fujitsu hp ibm macintosh macosx sony sun xfree86 xfree98 xkb.pl DESTINATION share/freerdp/keymaps) install(DIRECTORY digital_vndr DESTINATION share/freerdp/keymaps FILES_MATCHING PATTERN "*") install(DIRECTORY sgi_vndr DESTINATION share/freerdp/keymaps FILES_MATCHING PATTERN "*") FreeRDP-1.0.2/keymaps/aliases000066400000000000000000000004061207112532300157520ustar00rootroot00000000000000# This file was generated with xkb.pl (Wed Aug 11 09:09:10 2010) # and is based on the X Keyboard Configuration Database version 1.9 # Please use xkb.pl to re-export newer versions of XKB keyboard "qwerty" { }; keyboard "azerty" { }; keyboard "qwertz" { }; FreeRDP-1.0.2/keymaps/amiga000066400000000000000000000057041207112532300154150ustar00rootroot00000000000000# This file was generated with xkb.pl (Wed Aug 11 09:09:10 2010) # and is based on the X Keyboard Configuration Database version 1.9 # Please use xkb.pl to re-export newer versions of XKB keyboard "usa1" { VK_ESCAPE <77> VK_F1 <88> VK_F2 <89> VK_F3 <90> VK_F4 <91> VK_F5 <92> VK_F6 <93> VK_F7 <94> VK_F8 <95> VK_F9 <96> VK_F10 <97> VK_OEM_3 <8> VK_KEY_1 <9> VK_KEY_2 <10> VK_KEY_3 <11> VK_KEY_4 <12> VK_KEY_5 <13> VK_KEY_6 <14> VK_KEY_7 <15> VK_KEY_8 <16> VK_KEY_9 <17> VK_KEY_0 <18> VK_OEM_MINUS <19> VK_OEM_PLUS <20> VK_OEM_5 <21> VK_BACK <73> VK_TAB <74> VK_KEY_Q <24> VK_KEY_W <25> VK_KEY_E <26> VK_KEY_R <27> VK_KEY_T <28> VK_KEY_Y <29> VK_KEY_U <30> VK_KEY_I <31> VK_KEY_O <32> VK_KEY_P <33> VK_OEM_4 <34> VK_OEM_6 <35> VK_RETURN <76> VK_LCONTROL <107> VK_CAPITAL <106> VK_KEY_A <40> VK_KEY_S <41> VK_KEY_D <42> VK_KEY_F <43> VK_KEY_G <44> VK_KEY_H <45> VK_KEY_J <46> VK_KEY_K <47> VK_KEY_L <48> VK_OEM_1 <49> VK_OEM_7 <50> VK_LSHIFT <104> VK_KEY_Z <57> VK_KEY_X <58> VK_KEY_C <59> VK_KEY_V <60> VK_KEY_B <61> VK_KEY_N <62> VK_KEY_M <63> VK_OEM_COMMA <64> VK_OEM_PERIOD <65> VK_OEM_2 <66> VK_RSHIFT <105> VK_LMENU <108> VK_SPACE <72> VK_RMENU <109> VK_DELETE <78> VK_HELP <103> VK_UP <84> VK_LEFT <87> VK_DOWN <85> VK_RIGHT <86> VK_DIVIDE <100> VK_MULTIPLY <101> VK_NUMPAD7 <69> VK_NUMPAD8 <70> VK_NUMPAD9 <71> VK_SUBTRACT <82> VK_NUMPAD4 <53> VK_NUMPAD5 <54> VK_NUMPAD6 <55> VK_ADD <102> VK_NUMPAD1 <37> VK_NUMPAD2 <38> VK_NUMPAD3 <39> VK_NUMPAD0 <23> VK_RETURN <75> }; keyboard "de" { VK_ESCAPE <77> VK_F1 <88> VK_F2 <89> VK_F3 <90> VK_F4 <91> VK_F5 <92> VK_F6 <93> VK_F7 <94> VK_F8 <95> VK_F9 <96> VK_F10 <97> VK_OEM_3 <8> VK_KEY_1 <9> VK_KEY_2 <10> VK_KEY_3 <11> VK_KEY_4 <12> VK_KEY_5 <13> VK_KEY_6 <14> VK_KEY_7 <15> VK_KEY_8 <16> VK_KEY_9 <17> VK_KEY_0 <18> VK_OEM_MINUS <19> VK_OEM_PLUS <20> VK_OEM_5 <21> VK_BACK <73> VK_TAB <74> VK_KEY_Q <24> VK_KEY_W <25> VK_KEY_E <26> VK_KEY_R <27> VK_KEY_T <28> VK_KEY_Y <29> VK_KEY_U <30> VK_KEY_I <31> VK_KEY_O <32> VK_KEY_P <33> VK_OEM_4 <34> VK_OEM_6 <35> VK_RETURN <76> VK_LCONTROL <107> VK_CAPITAL <106> VK_KEY_A <40> VK_KEY_S <41> VK_KEY_D <42> VK_KEY_F <43> VK_KEY_G <44> VK_KEY_H <45> VK_KEY_J <46> VK_KEY_K <47> VK_KEY_L <48> VK_OEM_1 <49> VK_OEM_7 <50> VK_OEM_5 <51> VK_LSHIFT <104> VK_OEM_102 <56> VK_KEY_Z <57> VK_KEY_X <58> VK_KEY_C <59> VK_KEY_V <60> VK_KEY_B <61> VK_KEY_N <62> VK_KEY_M <63> VK_OEM_COMMA <64> VK_OEM_PERIOD <65> VK_OEM_2 <66> VK_RSHIFT <105> VK_LMENU <108> VK_SPACE <72> VK_RMENU <109> VK_DELETE <78> VK_HELP <103> VK_UP <84> VK_LEFT <87> VK_DOWN <85> VK_RIGHT <86> VK_DIVIDE <100> VK_MULTIPLY <101> VK_NUMPAD7 <69> VK_NUMPAD8 <70> VK_NUMPAD9 <71> VK_SUBTRACT <82> VK_NUMPAD4 <53> VK_NUMPAD5 <54> VK_NUMPAD6 <55> VK_ADD <102> VK_NUMPAD1 <37> VK_NUMPAD2 <38> VK_NUMPAD3 <39> VK_NUMPAD0 <23> VK_RETURN <75> }; FreeRDP-1.0.2/keymaps/ataritt000066400000000000000000000031641207112532300160050ustar00rootroot00000000000000# This file was generated with xkb.pl (Wed Aug 11 09:09:10 2010) # and is based on the X Keyboard Configuration Database version 1.9 # Please use xkb.pl to re-export newer versions of XKB keyboard "us" { VK_ESCAPE <9> VK_KEY_1 <10> VK_KEY_2 <11> VK_KEY_3 <12> VK_KEY_4 <13> VK_KEY_5 <14> VK_KEY_6 <15> VK_KEY_7 <16> VK_KEY_8 <17> VK_KEY_9 <18> VK_KEY_0 <19> VK_OEM_MINUS <20> VK_OEM_PLUS <21> VK_OEM_3 <49> VK_BACK <22> VK_TAB <23> VK_KEY_Q <24> VK_KEY_W <25> VK_KEY_E <26> VK_KEY_R <27> VK_KEY_T <28> VK_KEY_Y <29> VK_KEY_U <30> VK_KEY_I <31> VK_KEY_O <32> VK_KEY_P <33> VK_OEM_4 <34> VK_OEM_6 <35> VK_RETURN <36> VK_DELETE <91> VK_LCONTROL <37> VK_KEY_A <38> VK_KEY_S <39> VK_KEY_D <40> VK_KEY_F <41> VK_KEY_G <42> VK_KEY_H <43> VK_KEY_J <44> VK_KEY_K <45> VK_KEY_L <46> VK_OEM_1 <47> VK_OEM_7 <48> VK_OEM_5 <51> VK_LSHIFT <50> VK_KEY_Z <52> VK_KEY_X <53> VK_KEY_C <54> VK_KEY_V <55> VK_KEY_B <56> VK_KEY_N <57> VK_KEY_M <58> VK_OEM_COMMA <59> VK_OEM_PERIOD <60> VK_OEM_2 <61> VK_RSHIFT <62> VK_SPACE <65> VK_CAPITAL <66> VK_F1 <67> VK_F2 <68> VK_F3 <69> VK_F4 <70> VK_F5 <71> VK_F6 <72> VK_F7 <73> VK_F8 <74> VK_F9 <75> VK_F10 <76> VK_HELP <106> VK_INSERT <90> VK_HOME <79> VK_UP <80> VK_LEFT <83> VK_DOWN <88> VK_RIGHT <85> VK_DIVIDE <109> VK_MULTIPLY <110> VK_NUMPAD7 <111> VK_NUMPAD8 <112> VK_NUMPAD9 <113> VK_SUBTRACT <82> VK_NUMPAD4 <114> VK_NUMPAD5 <115> VK_NUMPAD6 <116> VK_ADD <86> VK_NUMPAD1 <117> VK_NUMPAD2 <118> VK_NUMPAD3 <119> VK_NUMPAD0 <120> VK_RETURN <122> }; keyboard "de" : extends "ataritt(us)" { VK_OEM_102 <104> }; FreeRDP-1.0.2/keymaps/digital_vndr/000077500000000000000000000000001207112532300170545ustar00rootroot00000000000000FreeRDP-1.0.2/keymaps/digital_vndr/lk000066400000000000000000000057561207112532300174220ustar00rootroot00000000000000# This file was generated with xkb.pl (Wed Aug 11 09:09:10 2010) # and is based on the X Keyboard Configuration Database version 1.9 # Please use xkb.pl to re-export newer versions of XKB keyboard "lk_common" { VK_F1 <86> VK_F2 <87> VK_F3 <88> VK_F4 <89> VK_F5 <90> VK_F6 <100> VK_F7 <101> VK_F8 <102> VK_F9 <103> VK_F10 <104> VK_F11 <113> VK_F12 <114> VK_UP <170> VK_LEFT <167> VK_DOWN <169> VK_RIGHT <168> VK_NUMPAD7 <157> VK_NUMPAD8 <158> VK_NUMPAD9 <159> VK_NUMPAD4 <153> VK_NUMPAD5 <154> VK_NUMPAD6 <155> VK_NUMPAD1 <150> VK_NUMPAD2 <151> VK_NUMPAD3 <152> VK_RETURN <149> VK_NUMPAD0 <146> VK_DECIMAL <148> VK_TILDE <191> VK_KEY_1 <192> VK_KEY_2 <197> VK_KEY_3 <203> VK_KEY_4 <208> VK_KEY_5 <214> VK_KEY_6 <219> VK_KEY_7 <224> VK_KEY_8 <229> VK_KEY_9 <234> VK_KEY_0 <239> VK_OEM_MINUS <249> VK_OEM_PLUS <245> VK_BACK <188> VK_TAB <190> VK_KEY_Q <193> VK_KEY_W <198> VK_KEY_E <204> VK_KEY_R <209> VK_KEY_T <215> VK_KEY_Y <220> VK_KEY_U <225> VK_KEY_I <230> VK_KEY_O <235> VK_KEY_P <240> VK_OEM_4 <250> VK_OEM_6 <246> VK_RETURN <189> VK_LCONTROL <175> VK_CAPITAL <176> VK_KEY_A <194> VK_KEY_S <199> VK_KEY_D <205> VK_KEY_F <210> VK_KEY_G <216> VK_KEY_H <221> VK_KEY_J <226> VK_KEY_K <231> VK_KEY_L <236> VK_OEM_1 <242> VK_OEM_7 <251> VK_LSHIFT <174> VK_KEY_Z <195> VK_KEY_X <200> VK_KEY_C <206> VK_KEY_V <211> VK_KEY_B <217> VK_KEY_N <222> VK_KEY_M <227> VK_OEM_COMMA <232> VK_OEM_PERIOD <237> VK_OEM_2 <243> VK_RSHIFT <171> VK_SPACE <212> }; keyboard "lkx01" : extends "digital_vndr/lk(lk_common)" { VK_LSHIFT <201> VK_F13 <115> VK_F14 <116> VK_F17 <128> VK_F18 <129> VK_F19 <130> VK_F20 <131> VK_HELP <124> VK_INSERT <139> VK_DELETE <140> VK_SELECT <141> VK_PRIOR <142> VK_NEXT <143> VK_NUMLOCK <161> VK_DIVIDE <162> VK_MULTIPLY <163> VK_SUBTRACT <164> VK_SUBTRACT <160> VK_ADD <156> VK_OEM_5 <247> }; keyboard "lk201" : extends "digital_vndr/lk(lkx01)" { }; keyboard "lk421" : extends "digital_vndr/lk(lkx01)" { VK_LMENU <172> VK_RMENU <178> }; keyboard "lk401" : extends "digital_vndr/lk(lk421)" { }; keyboard "lk44x" : extends "digital_vndr/lk(lk_common)" { VK_ESCAPE <85> VK_SNAPSHOT <115> VK_SCROLL <116> VK_PAUSE <124> VK_INSERT <138> VK_HOME <139> VK_PRIOR <140> VK_DELETE <141> VK_END <142> VK_NEXT <143> VK_NUMLOCK <161> VK_DIVIDE <162> VK_MULTIPLY <163> VK_SUBTRACT <164> VK_ADD <156> VK_LMENU <172> VK_RMENU <178> VK_RCONTROL <173> }; keyboard "lk443" : extends "digital_vndr/lk(lk44x)" { VK_OEM_5 <247> }; keyboard "lk444" : extends "digital_vndr/lk(lk44x)" { VK_OEM_5 <201> VK_OEM_5 <247> }; keyboard "lk421aj" : extends "digital_vndr/lk(lk421)" { VK_ABNT_C1 <252> }; keyboard "lk421jj" : extends "digital_vndr/lk(lk421aj)" { VK_NONCONVERT <94> VK_KANJI <95> VK_KANA <97> }; keyboard "lk401bj" : extends "digital_vndr/lk(lk401)" { VK_NONCONVERT <94> VK_KANJI <95> VK_KANA <97> }; keyboard "lk401jj" : extends "digital_vndr/lk(lk401bj)" { VK_ABNT_C1 <252> }; FreeRDP-1.0.2/keymaps/digital_vndr/pc000066400000000000000000000056021207112532300174040ustar00rootroot00000000000000# This file was generated with xkb.pl (Wed Aug 11 09:09:10 2010) # and is based on the X Keyboard Configuration Database version 1.9 # Please use xkb.pl to re-export newer versions of XKB keyboard "pc_common" { VK_F1 <9> VK_F2 <15> VK_F3 <23> VK_F4 <31> VK_F5 <39> VK_F6 <47> VK_F7 <55> VK_F8 <63> VK_F9 <71> VK_F10 <79> VK_F11 <86> VK_F12 <94> VK_UP <99> VK_LEFT <97> VK_DOWN <96> VK_RIGHT <106> VK_NUMPAD7 <108> VK_NUMPAD8 <117> VK_NUMPAD9 <125> VK_NUMPAD4 <107> VK_NUMPAD5 <115> VK_NUMPAD6 <116> VK_NUMPAD1 <105> VK_NUMPAD2 <114> VK_NUMPAD3 <122> VK_RETURN <121> VK_NUMPAD0 <112> VK_DECIMAL <113> VK_KEY_1 <22> VK_KEY_2 <30> VK_KEY_3 <38> VK_KEY_4 <37> VK_KEY_5 <46> VK_KEY_6 <54> VK_KEY_7 <61> VK_KEY_8 <62> VK_KEY_9 <70> VK_KEY_0 <69> VK_OEM_MINUS <78> VK_OEM_PLUS <85> VK_BACK <102> VK_TAB <13> VK_KEY_Q <21> VK_KEY_W <29> VK_KEY_E <36> VK_KEY_R <45> VK_KEY_T <44> VK_KEY_Y <53> VK_KEY_U <60> VK_KEY_I <67> VK_KEY_O <68> VK_KEY_P <77> VK_OEM_4 <84> VK_OEM_6 <91> VK_CAPITAL <20> VK_KEY_A <28> VK_KEY_S <27> VK_KEY_D <35> VK_KEY_F <43> VK_KEY_G <52> VK_KEY_H <51> VK_KEY_J <59> VK_KEY_K <66> VK_KEY_L <75> VK_OEM_1 <76> VK_OEM_7 <82> VK_RETURN <90> VK_LSHIFT <18> VK_KEY_Z <26> VK_KEY_X <34> VK_KEY_C <33> VK_KEY_V <42> VK_KEY_B <50> VK_KEY_N <49> VK_KEY_M <58> VK_OEM_COMMA <65> VK_OEM_PERIOD <73> VK_OEM_2 <74> VK_RSHIFT <89> VK_LCONTROL <17> VK_LMENU <25> VK_SPACE <41> VK_RMENU <57> }; keyboard "pc10x" : extends "digital_vndr/pc(pc_common)" { VK_ESCAPE <8> VK_TILDE <14> VK_SNAPSHOT <87> VK_SCROLL <95> VK_PAUSE <98> VK_INSERT <103> VK_HOME <110> VK_PRIOR <111> VK_DELETE <100> VK_END <101> VK_NEXT <109> VK_NUMLOCK <118> VK_DIVIDE <119> VK_MULTIPLY <126> VK_SUBTRACT <132> VK_ADD <124> VK_RCONTROL <88> }; keyboard "pc101" : extends "digital_vndr/pc(pc10x)" { VK_OEM_5 <92> }; keyboard "pc102" : extends "digital_vndr/pc(pc10x)" { VK_OEM_5 <19> VK_OEM_5 <83> }; keyboard "pc104" : extends "digital_vndr/pc(pc101)" { VK_LWIN <139> VK_RWIN <140> VK_APPS <141> }; keyboard "lk411_common" : extends "digital_vndr/pc(pc_common)" { VK_TILDE <8> VK_LSHIFT <14> VK_F13 <24> VK_F14 <10> VK_F17 <16> VK_F18 <87> VK_F19 <95> VK_F20 <98> VK_HELP <11> VK_INSERT <103> VK_DELETE <100> VK_SELECT <101> VK_PRIOR <111> VK_NEXT <109> VK_NUMLOCK <118> VK_DIVIDE <119> VK_MULTIPLY <126> VK_SUBTRACT <132> VK_SUBTRACT <19> VK_ADD <124> }; keyboard "lk411" : extends "digital_vndr/pc(lk411_common)" { VK_OEM_5 <92> }; keyboard "lk450" : extends "digital_vndr/pc(lk411)" { }; keyboard "pcxajaa" : extends "digital_vndr/pc(pc10x)" { VK_OEM_5 <93> VK_OEM_5 <83> VK_ABNT_C1 <81> VK_NONCONVERT <133> VK_KANJI <134> VK_KANA <135> }; keyboard "lk411jj" : extends "digital_vndr/pc(lk411_common)" { VK_ABNT_C1 <81> VK_OEM_5 <83> VK_NONCONVERT <133> VK_KANJI <134> VK_KANA <135> }; FreeRDP-1.0.2/keymaps/empty000066400000000000000000000003541207112532300154710ustar00rootroot00000000000000# This file was generated with xkb.pl (Wed Aug 11 09:09:10 2010) # and is based on the X Keyboard Configuration Database version 1.9 # Please use xkb.pl to re-export newer versions of XKB keyboard "empty" { }; keyboard "empty" { }; FreeRDP-1.0.2/keymaps/evdev000066400000000000000000000041401207112532300154410ustar00rootroot00000000000000# This file was generated with xkb.pl (Wed Aug 11 09:09:10 2010) # and is based on the X Keyboard Configuration Database version 1.9 # Please use xkb.pl to re-export newer versions of XKB keyboard "evdev" { VK_OEM_102 <94> VK_OEM_3 <49> VK_KEY_1 <10> VK_KEY_2 <11> VK_KEY_3 <12> VK_KEY_4 <13> VK_KEY_5 <14> VK_KEY_6 <15> VK_KEY_7 <16> VK_KEY_8 <17> VK_KEY_9 <18> VK_KEY_0 <19> VK_OEM_MINUS <20> VK_OEM_PLUS <21> VK_BACK <22> VK_TAB <23> VK_KEY_Q <24> VK_KEY_W <25> VK_KEY_E <26> VK_KEY_R <27> VK_KEY_T <28> VK_KEY_Y <29> VK_KEY_U <30> VK_KEY_I <31> VK_KEY_O <32> VK_KEY_P <33> VK_OEM_4 <34> VK_OEM_6 <35> VK_OEM_5 <51> VK_RETURN <36> VK_CAPITAL <66> VK_KEY_A <38> VK_KEY_S <39> VK_KEY_D <40> VK_KEY_F <41> VK_KEY_G <42> VK_KEY_H <43> VK_KEY_J <44> VK_KEY_K <45> VK_KEY_L <46> VK_OEM_1 <47> VK_OEM_7 <48> VK_LSHIFT <50> VK_KEY_Z <52> VK_KEY_X <53> VK_KEY_C <54> VK_KEY_V <55> VK_KEY_B <56> VK_KEY_N <57> VK_KEY_M <58> VK_OEM_COMMA <59> VK_OEM_PERIOD <60> VK_OEM_2 <61> VK_RSHIFT <62> VK_LMENU <64> VK_LCONTROL <37> VK_SPACE <65> VK_RCONTROL <105> VK_RMENU <108> VK_LWIN <133> VK_RWIN <134> VK_APPS <135> VK_ESCAPE <9> VK_F1 <67> VK_F2 <68> VK_F3 <69> VK_F4 <70> VK_F5 <71> VK_F6 <72> VK_F7 <73> VK_F8 <74> VK_F9 <75> VK_F10 <76> VK_F11 <95> VK_F12 <96> VK_SNAPSHOT <107> VK_SCROLL <78> VK_PAUSE <127> VK_INSERT <118> VK_HOME <110> VK_PRIOR <112> VK_DELETE <119> VK_END <115> VK_NEXT <117> VK_UP <111> VK_LEFT <113> VK_DOWN <116> VK_RIGHT <114> VK_NUMLOCK <77> VK_DIVIDE <106> VK_MULTIPLY <63> VK_SUBTRACT <82> VK_NUMPAD7 <79> VK_NUMPAD8 <80> VK_NUMPAD9 <81> VK_ADD <86> VK_NUMPAD4 <83> VK_NUMPAD5 <84> VK_NUMPAD6 <85> VK_NUMPAD1 <87> VK_NUMPAD2 <88> VK_NUMPAD3 <89> VK_RETURN <104> VK_NUMPAD0 <90> VK_DECIMAL <91> VK_F13 <191> VK_F14 <192> VK_F15 <193> VK_F16 <194> VK_F17 <195> VK_F18 <196> VK_F19 <197> VK_F20 <198> VK_F21 <199> VK_F22 <200> VK_F23 <201> VK_F24 <202> VK_ABNT_C1 <97> VK_NONCONVERT <102> VK_KANA <99> VK_HELP <146> }; keyboard "pc98" : extends "evdev(evdev)" { }; FreeRDP-1.0.2/keymaps/fujitsu000066400000000000000000000035761207112532300160350ustar00rootroot00000000000000# This file was generated with xkb.pl (Wed Aug 11 09:09:10 2010) # and is based on the X Keyboard Configuration Database version 1.9 # Please use xkb.pl to re-export newer versions of XKB keyboard "138" { VK_ESCAPE <37> VK_KEY_1 <38> VK_KEY_2 <39> VK_KEY_3 <40> VK_KEY_4 <41> VK_KEY_5 <42> VK_KEY_6 <43> VK_KEY_7 <44> VK_KEY_8 <45> VK_KEY_9 <46> VK_KEY_0 <47> VK_OEM_MINUS <48> VK_OEM_PLUS <49> VK_OEM_3 <50> VK_BACK <51> VK_TAB <61> VK_KEY_Q <62> VK_KEY_W <63> VK_KEY_E <64> VK_KEY_R <65> VK_KEY_T <66> VK_KEY_Y <67> VK_KEY_U <68> VK_KEY_I <69> VK_KEY_O <70> VK_KEY_P <71> VK_OEM_4 <72> VK_OEM_6 <73> VK_LCONTROL <84> VK_KEY_A <85> VK_KEY_S <86> VK_KEY_D <87> VK_KEY_F <88> VK_KEY_G <89> VK_KEY_H <90> VK_KEY_J <91> VK_KEY_K <92> VK_KEY_L <93> VK_OEM_1 <94> VK_OEM_7 <95> VK_OEM_5 <96> VK_RETURN <97> VK_LSHIFT <107> VK_KEY_Z <108> VK_KEY_X <109> VK_KEY_C <110> VK_KEY_V <111> VK_KEY_B <112> VK_KEY_N <113> VK_KEY_M <114> VK_OEM_COMMA <115> VK_OEM_PERIOD <116> VK_OEM_2 <117> VK_ABNT_C1 <52> VK_RSHIFT <118> VK_CAPITAL <127> VK_LMENU <27> VK_SPACE <129> VK_RMENU <23> VK_APPS <75> VK_F1 <13> VK_F2 <14> VK_F3 <16> VK_F4 <18> VK_F5 <20> VK_F6 <22> VK_F7 <24> VK_F8 <25> VK_F9 <26> VK_F10 <15> VK_F11 <17> VK_F12 <19> VK_F13 <137> VK_F14 <138> VK_F15 <139> VK_F16 <140> VK_F17 <141> VK_F18 <142> VK_F19 <143> VK_F20 <144> VK_F21 <145> VK_F22 <146> VK_F23 <147> VK_F24 <148> VK_HELP <126> VK_SNAPSHOT <30> VK_PAUSE <29> VK_PRIOR <35> VK_HOME <32> VK_NEXT <36> VK_INSERT <60> VK_UP <33> VK_DOWN <103> VK_LEFT <57> VK_RIGHT <80> VK_MULTIPLY <55> VK_DIVIDE <54> VK_ADD <133> VK_SUBTRACT <79> VK_NUMPAD7 <76> VK_NUMPAD8 <77> VK_NUMPAD9 <78> VK_NUMPAD4 <99> VK_NUMPAD5 <100> VK_NUMPAD6 <101> VK_NUMPAD1 <120> VK_NUMPAD2 <121> VK_NUMPAD3 <122> VK_RETURN <98> VK_NUMPAD0 <102> }; FreeRDP-1.0.2/keymaps/hp000066400000000000000000000032611207112532300147420ustar00rootroot00000000000000# This file was generated with xkb.pl (Wed Aug 11 09:09:10 2010) # and is based on the X Keyboard Configuration Database version 1.9 # Please use xkb.pl to re-export newer versions of XKB keyboard "hil" { VK_OEM_3 <71> VK_KEY_1 <70> VK_KEY_2 <69> VK_KEY_3 <68> VK_KEY_4 <67> VK_KEY_5 <66> VK_KEY_6 <65> VK_KEY_7 <64> VK_KEY_8 <96> VK_KEY_9 <97> VK_KEY_0 <98> VK_OEM_MINUS <99> VK_OEM_PLUS <100> VK_BACK <101> VK_TAB <63> VK_KEY_Q <62> VK_KEY_W <61> VK_KEY_E <60> VK_KEY_R <59> VK_KEY_T <58> VK_KEY_Y <57> VK_KEY_U <56> VK_KEY_I <104> VK_KEY_O <105> VK_KEY_P <106> VK_OEM_4 <107> VK_OEM_6 <108> VK_OEM_5 <109> VK_CAPITAL <55> VK_KEY_A <53> VK_KEY_S <52> VK_KEY_D <51> VK_KEY_F <50> VK_KEY_G <49> VK_KEY_H <48> VK_KEY_J <112> VK_KEY_K <113> VK_KEY_L <114> VK_OEM_1 <115> VK_OEM_7 <116> VK_RETURN <117> VK_LSHIFT <13> VK_KEY_Z <36> VK_KEY_X <35> VK_KEY_C <34> VK_KEY_V <33> VK_KEY_B <32> VK_KEY_N <128> VK_KEY_M <120> VK_OEM_COMMA <121> VK_OEM_PERIOD <122> VK_OEM_2 <123> VK_RSHIFT <12> VK_LCONTROL <14> VK_LMENU <11> VK_SPACE <129> VK_RMENU <10> VK_SNAPSHOT <87> VK_ESCAPE <39> VK_F1 <84> VK_F2 <83> VK_F3 <82> VK_F4 <81> VK_APPS <80> VK_F5 <89> VK_F6 <90> VK_F7 <91> VK_F8 <92> VK_F9 <45> VK_F10 <41> VK_F11 <43> VK_F12 <47> VK_HOME <118> VK_PRIOR <119> VK_NEXT <127> VK_SELECT <125> VK_UP <134> VK_LEFT <132> VK_DOWN <133> VK_RIGHT <135> VK_DIVIDE <25> VK_MULTIPLY <29> VK_ADD <27> VK_SUBTRACT <31> VK_NUMPAD7 <21> VK_NUMPAD8 <17> VK_NUMPAD9 <19> VK_RETURN <23> VK_NUMPAD4 <16> VK_NUMPAD5 <18> VK_NUMPAD6 <20> VK_NUMPAD1 <24> VK_NUMPAD2 <26> VK_NUMPAD3 <28> VK_NUMPAD0 <30> VK_DECIMAL <44> }; FreeRDP-1.0.2/keymaps/ibm000066400000000000000000000002761207112532300151050ustar00rootroot00000000000000# This file was generated with xkb.pl (Wed Aug 11 09:09:10 2010) # and is based on the X Keyboard Configuration Database version 1.9 # Please use xkb.pl to re-export newer versions of XKB FreeRDP-1.0.2/keymaps/macintosh000066400000000000000000000041421207112532300163170ustar00rootroot00000000000000# This file was generated with xkb.pl (Wed Aug 11 09:09:10 2010) # and is based on the X Keyboard Configuration Database version 1.9 # Please use xkb.pl to re-export newer versions of XKB keyboard "macintosh" : extends "xfree86" { VK_F13 <182> VK_F14 <183> VK_F15 <184> }; keyboard "old" { VK_ESCAPE <61> VK_OEM_3 <58> VK_KEY_1 <26> VK_KEY_2 <27> VK_KEY_3 <28> VK_KEY_4 <29> VK_KEY_5 <31> VK_KEY_6 <30> VK_KEY_7 <34> VK_KEY_8 <36> VK_KEY_9 <33> VK_KEY_0 <37> VK_OEM_MINUS <35> VK_OEM_PLUS <32> VK_BACK <59> VK_TAB <56> VK_KEY_Q <20> VK_KEY_W <21> VK_KEY_E <22> VK_KEY_R <23> VK_KEY_T <25> VK_KEY_Y <24> VK_KEY_U <40> VK_KEY_I <42> VK_KEY_O <39> VK_KEY_P <43> VK_OEM_4 <41> VK_OEM_6 <38> VK_OEM_5 <50> VK_CAPITAL <65> VK_KEY_A <8> VK_KEY_S <9> VK_KEY_D <10> VK_KEY_F <11> VK_KEY_G <13> VK_KEY_H <12> VK_KEY_J <46> VK_KEY_K <48> VK_KEY_L <45> VK_OEM_1 <49> VK_OEM_7 <47> VK_RETURN <44> VK_OEM_102 <18> VK_KEY_Z <14> VK_KEY_X <15> VK_KEY_C <16> VK_KEY_V <17> VK_KEY_B <19> VK_KEY_N <53> VK_KEY_M <54> VK_OEM_COMMA <51> VK_OEM_PERIOD <55> VK_OEM_2 <52> VK_SPACE <57> VK_LCONTROL <62> VK_LMENU <63> VK_LSHIFT <64> VK_RMENU <66> VK_RSHIFT <131> VK_RMENU <132> VK_RCONTROL <133> VK_F1 <130> VK_F2 <128> VK_F3 <107> VK_F4 <126> VK_F5 <104> VK_F6 <105> VK_F7 <106> VK_F8 <108> VK_F9 <109> VK_F10 <117> VK_F11 <111> VK_F12 <119> VK_SNAPSHOT <113> VK_SCROLL <115> VK_PAUSE <121> VK_INSERT <122> VK_HOME <123> VK_PRIOR <124> VK_DELETE <125> VK_END <127> VK_NEXT <129> VK_UP <70> VK_LEFT <67> VK_DOWN <69> VK_RIGHT <68> VK_NUMLOCK <79> VK_DIVIDE <83> VK_MULTIPLY <75> VK_NUMPAD7 <97> VK_NUMPAD8 <99> VK_NUMPAD9 <100> VK_SUBTRACT <86> VK_NUMPAD4 <94> VK_NUMPAD5 <95> VK_NUMPAD6 <96> VK_ADD <77> VK_NUMPAD1 <91> VK_NUMPAD2 <92> VK_NUMPAD3 <93> VK_RETURN <84> VK_NUMPAD0 <90> VK_DECIMAL <73> }; keyboard "hhk" : extends "macintosh" { VK_OEM_5 <51> VK_LWIN <49> VK_RWIN <208> VK_F13 <111> VK_F14 <78> VK_F15 <110> }; keyboard "alukbd" : extends "xfree86" { VK_F18 <129> VK_F19 <130> }; keyboard "jisevdev" { }; FreeRDP-1.0.2/keymaps/macosx000066400000000000000000000033271207112532300156300ustar00rootroot00000000000000# This file is manually edited from the "macintosh" keymap # X11.app is a special case, and xfreerdp on Mac OS X uses this hard-coded keymap instead keyboard "macosx" { VK_ESCAPE <61> VK_OEM_3 <58> VK_KEY_1 <26> VK_KEY_2 <27> VK_KEY_3 <28> VK_KEY_4 <29> VK_KEY_5 <31> VK_KEY_6 <30> VK_KEY_7 <34> VK_KEY_8 <36> VK_KEY_9 <33> VK_KEY_0 <37> VK_OEM_MINUS <35> VK_OEM_PLUS <32> VK_BACK <59> VK_TAB <56> VK_KEY_Q <20> VK_KEY_W <21> VK_KEY_E <22> VK_KEY_R <23> VK_KEY_T <25> VK_KEY_Y <24> VK_KEY_U <40> VK_KEY_I <42> VK_KEY_O <39> VK_KEY_P <43> VK_OEM_4 <41> VK_OEM_6 <38> VK_OEM_5 <50> VK_CAPITAL <65> VK_KEY_A <8> VK_KEY_S <9> VK_KEY_D <10> VK_KEY_F <11> VK_KEY_G <13> VK_KEY_H <12> VK_KEY_J <46> VK_KEY_K <48> VK_KEY_L <45> VK_OEM_1 <49> VK_OEM_7 <47> VK_RETURN <44> VK_OEM_102 <18> VK_KEY_Z <14> VK_KEY_X <15> VK_KEY_C <16> VK_KEY_V <17> VK_KEY_B <19> VK_KEY_N <53> VK_KEY_M <54> VK_OEM_COMMA <51> VK_OEM_PERIOD <55> VK_OEM_2 <52> VK_SPACE <57> VK_LCONTROL <67> VK_LMENU <66> VK_LSHIFT <64> VK_RMENU <69> VK_RSHIFT <68> VK_F1 <130> VK_F2 <128> VK_F3 <107> VK_F4 <126> VK_F5 <104> VK_F6 <105> VK_F7 <106> VK_F8 <108> VK_F9 <109> VK_F10 <117> VK_F11 <111> VK_F12 <119> VK_SNAPSHOT <113> VK_SCROLL <115> VK_PAUSE <121> VK_INSERT <122> VK_HOME <123> VK_PRIOR <124> VK_DELETE <125> VK_END <127> VK_NEXT <129> VK_UP <134> VK_LEFT <131> VK_DOWN <133> VK_RIGHT <132> VK_NUMLOCK <79> VK_DIVIDE <83> VK_MULTIPLY <75> VK_NUMPAD7 <97> VK_NUMPAD8 <99> VK_NUMPAD9 <100> VK_SUBTRACT <86> VK_NUMPAD4 <94> VK_NUMPAD5 <95> VK_NUMPAD6 <96> VK_ADD <77> VK_NUMPAD1 <91> VK_NUMPAD2 <92> VK_NUMPAD3 <93> VK_RETURN <84> VK_NUMPAD0 <90> VK_DECIMAL <73> }; FreeRDP-1.0.2/keymaps/sgi_vndr/000077500000000000000000000000001207112532300162215ustar00rootroot00000000000000FreeRDP-1.0.2/keymaps/sgi_vndr/indigo000066400000000000000000000035061207112532300174210ustar00rootroot00000000000000# This file was generated with xkb.pl (Wed Aug 11 09:09:10 2010) # and is based on the X Keyboard Configuration Database version 1.9 # Please use xkb.pl to re-export newer versions of XKB keyboard "pc101" { VK_OEM_3 <62> VK_KEY_1 <15> VK_KEY_2 <21> VK_KEY_3 <22> VK_KEY_4 <29> VK_KEY_5 <30> VK_KEY_6 <37> VK_KEY_7 <38> VK_KEY_8 <45> VK_KEY_9 <46> VK_KEY_0 <53> VK_OEM_MINUS <54> VK_OEM_PLUS <61> VK_BACK <68> VK_TAB <16> VK_KEY_Q <17> VK_KEY_W <23> VK_KEY_E <24> VK_KEY_R <31> VK_KEY_T <32> VK_KEY_Y <39> VK_KEY_U <40> VK_KEY_I <47> VK_KEY_O <48> VK_KEY_P <55> VK_OEM_4 <56> VK_OEM_6 <63> VK_RETURN <58> VK_CAPITAL <11> VK_KEY_A <18> VK_KEY_S <19> VK_KEY_D <25> VK_KEY_F <26> VK_KEY_G <33> VK_KEY_H <34> VK_KEY_J <41> VK_KEY_K <42> VK_KEY_L <49> VK_OEM_1 <50> VK_OEM_7 <57> VK_LSHIFT <13> VK_KEY_Z <27> VK_KEY_X <28> VK_KEY_C <35> VK_KEY_V <36> VK_KEY_B <43> VK_KEY_N <44> VK_KEY_M <51> VK_OEM_COMMA <52> VK_OEM_PERIOD <59> VK_OEM_2 <60> VK_RSHIFT <12> VK_OEM_5 <64> VK_LMENU <91> VK_LCONTROL <10> VK_SPACE <90> VK_RCONTROL <93> VK_RMENU <92> VK_ESCAPE <14> VK_F1 <94> VK_F2 <95> VK_F3 <96> VK_F4 <97> VK_F5 <98> VK_F6 <99> VK_F7 <100> VK_F8 <101> VK_F9 <102> VK_F10 <103> VK_F11 <104> VK_F12 <105> VK_SNAPSHOT <106> VK_SCROLL <107> VK_PAUSE <108> VK_INSERT <109> VK_HOME <110> VK_PRIOR <111> VK_DELETE <69> VK_END <112> VK_NEXT <113> VK_UP <88> VK_LEFT <80> VK_DOWN <81> VK_RIGHT <87> VK_NUMLOCK <114> VK_DIVIDE <115> VK_MULTIPLY <116> VK_SUBTRACT <83> VK_NUMPAD7 <74> VK_NUMPAD8 <75> VK_NUMPAD9 <82> VK_ADD <117> VK_NUMPAD4 <70> VK_NUMPAD5 <76> VK_NUMPAD6 <77> VK_NUMPAD1 <65> VK_NUMPAD2 <71> VK_NUMPAD3 <72> VK_RETURN <89> VK_NUMPAD0 <66> VK_DECIMAL <73> }; keyboard "pc102" : extends "sgi_vndr/indigo(pc101)" { VK_OEM_102 <118> }; FreeRDP-1.0.2/keymaps/sgi_vndr/indy000066400000000000000000000041521207112532300171110ustar00rootroot00000000000000# This file was generated with xkb.pl (Wed Aug 11 09:09:10 2010) # and is based on the X Keyboard Configuration Database version 1.9 # Please use xkb.pl to re-export newer versions of XKB keyboard "universal" { VK_OEM_5 <91> VK_OEM_5 <100> VK_OEM_5 <101> }; keyboard "pc101" { VK_OEM_3 <22> VK_KEY_1 <30> VK_KEY_2 <38> VK_KEY_3 <46> VK_KEY_4 <45> VK_KEY_5 <54> VK_KEY_6 <62> VK_KEY_7 <69> VK_KEY_8 <70> VK_KEY_9 <78> VK_KEY_0 <77> VK_OEM_MINUS <86> VK_OEM_PLUS <93> VK_BACK <110> VK_TAB <21> VK_KEY_Q <29> VK_KEY_W <37> VK_KEY_E <44> VK_KEY_R <53> VK_KEY_T <52> VK_KEY_Y <61> VK_KEY_U <68> VK_KEY_I <75> VK_KEY_O <76> VK_KEY_P <85> VK_OEM_4 <92> VK_OEM_6 <99> VK_RETURN <98> VK_CAPITAL <28> VK_KEY_A <36> VK_KEY_S <35> VK_KEY_D <43> VK_KEY_F <51> VK_KEY_G <60> VK_KEY_H <59> VK_KEY_J <67> VK_KEY_K <74> VK_KEY_L <83> VK_OEM_1 <84> VK_OEM_7 <90> VK_LSHIFT <26> VK_KEY_Z <34> VK_KEY_X <42> VK_KEY_C <41> VK_KEY_V <50> VK_KEY_B <58> VK_KEY_N <57> VK_KEY_M <66> VK_OEM_COMMA <73> VK_OEM_PERIOD <81> VK_OEM_2 <82> VK_RSHIFT <97> VK_OEM_5 <100> VK_LMENU <33> VK_LCONTROL <25> VK_SPACE <49> VK_RCONTROL <96> VK_RMENU <65> VK_ESCAPE <16> VK_F1 <15> VK_F2 <23> VK_F3 <31> VK_F4 <39> VK_F5 <47> VK_F6 <55> VK_F7 <63> VK_F8 <71> VK_F9 <79> VK_F10 <87> VK_F11 <94> VK_F12 <102> VK_SNAPSHOT <95> VK_SCROLL <103> VK_PAUSE <106> VK_INSERT <111> VK_HOME <118> VK_PRIOR <119> VK_DELETE <108> VK_END <109> VK_NEXT <117> VK_UP <107> VK_LEFT <105> VK_DOWN <104> VK_RIGHT <114> VK_NUMLOCK <126> VK_DIVIDE <127> VK_MULTIPLY <134> VK_SUBTRACT <140> VK_NUMPAD7 <116> VK_NUMPAD8 <125> VK_NUMPAD9 <133> VK_ADD <132> VK_NUMPAD4 <115> VK_NUMPAD5 <123> VK_NUMPAD6 <124> VK_NUMPAD1 <113> VK_NUMPAD2 <122> VK_NUMPAD3 <130> VK_RETURN <129> VK_NUMPAD0 <120> VK_DECIMAL <121> }; keyboard "pc102" { VK_OEM_102 <27> }; keyboard "pc104" : extends "sgi_vndr/indy(pc101)" { VK_LWIN <147> VK_RWIN <148> VK_APPS <149> }; keyboard "pc105" { }; keyboard "jp106" { VK_ABNT_C1 <89> VK_OEM_5 <91> }; keyboard "overlayKeypad" { }; keyboard "shiftLock" { }; FreeRDP-1.0.2/keymaps/sgi_vndr/iris000066400000000000000000000003671207112532300171200ustar00rootroot00000000000000# This file was generated with xkb.pl (Wed Aug 11 09:09:10 2010) # and is based on the X Keyboard Configuration Database version 1.9 # Please use xkb.pl to re-export newer versions of XKB keyboard "iris" : extends "sgi_vndr/indigo(pc101)" { }; FreeRDP-1.0.2/keymaps/sony000066400000000000000000000032001207112532300153140ustar00rootroot00000000000000# This file was generated with xkb.pl (Wed Aug 11 09:09:10 2010) # and is based on the X Keyboard Configuration Database version 1.9 # Please use xkb.pl to re-export newer versions of XKB keyboard "nwp5461" { VK_ESCAPE <18> VK_KEY_1 <19> VK_KEY_2 <20> VK_KEY_3 <21> VK_KEY_4 <22> VK_KEY_5 <23> VK_KEY_6 <24> VK_KEY_7 <25> VK_KEY_8 <26> VK_KEY_9 <27> VK_KEY_0 <28> VK_OEM_MINUS <29> VK_OEM_PLUS <30> VK_OEM_5 <31> VK_BACK <32> VK_TAB <33> VK_KEY_Q <34> VK_KEY_W <35> VK_KEY_E <36> VK_KEY_R <37> VK_KEY_T <38> VK_KEY_Y <39> VK_KEY_U <40> VK_KEY_I <41> VK_KEY_O <42> VK_KEY_P <43> VK_OEM_4 <44> VK_OEM_6 <45> VK_DELETE <46> VK_LCONTROL <47> VK_KEY_A <48> VK_KEY_S <49> VK_KEY_D <50> VK_KEY_F <51> VK_KEY_G <52> VK_KEY_H <53> VK_KEY_J <54> VK_KEY_K <55> VK_KEY_L <56> VK_OEM_1 <57> VK_OEM_7 <58> VK_OEM_3 <59> VK_RETURN <60> VK_LSHIFT <61> VK_KEY_Z <62> VK_KEY_X <63> VK_KEY_C <64> VK_KEY_V <65> VK_KEY_B <66> VK_KEY_N <67> VK_KEY_M <68> VK_OEM_COMMA <69> VK_OEM_PERIOD <70> VK_OEM_2 <71> VK_ABNT_C1 <72> VK_RSHIFT <73> VK_LMENU <74> VK_CAPITAL <75> VK_SPACE <77> VK_F1 <8> VK_F2 <9> VK_F3 <10> VK_F4 <11> VK_F5 <12> VK_F6 <13> VK_F7 <14> VK_F8 <15> VK_F9 <16> VK_F10 <17> VK_F11 <111> VK_F12 <112> VK_HELP <113> VK_INSERT <114> VK_PRIOR <116> VK_NEXT <117> VK_UP <95> VK_LEFT <98> VK_DOWN <99> VK_RIGHT <100> VK_MULTIPLY <107> VK_DIVIDE <108> VK_ADD <89> VK_NUMPAD7 <82> VK_NUMPAD8 <83> VK_NUMPAD9 <84> VK_SUBTRACT <85> VK_NUMPAD4 <86> VK_NUMPAD5 <87> VK_NUMPAD6 <88> VK_NUMPAD1 <90> VK_NUMPAD2 <91> VK_NUMPAD3 <92> VK_RETURN <97> VK_NUMPAD0 <94> }; FreeRDP-1.0.2/keymaps/sun000066400000000000000000000215411207112532300151410ustar00rootroot00000000000000# This file was generated with xkb.pl (Wed Aug 11 09:09:10 2010) # and is based on the X Keyboard Configuration Database version 1.9 # Please use xkb.pl to re-export newer versions of XKB keyboard "type4" { VK_ESCAPE <36> VK_KEY_1 <37> VK_KEY_2 <38> VK_KEY_3 <39> VK_KEY_4 <40> VK_KEY_5 <41> VK_KEY_6 <42> VK_KEY_7 <43> VK_KEY_8 <44> VK_KEY_9 <45> VK_KEY_0 <46> VK_OEM_MINUS <47> VK_OEM_PLUS <48> VK_OEM_3 <49> VK_BACK <50> VK_TAB <60> VK_KEY_Q <61> VK_KEY_W <62> VK_KEY_E <63> VK_KEY_R <64> VK_KEY_T <65> VK_KEY_Y <66> VK_KEY_U <67> VK_KEY_I <68> VK_KEY_O <69> VK_KEY_P <70> VK_OEM_4 <71> VK_OEM_6 <72> VK_DELETE <73> VK_LCONTROL <83> VK_KEY_A <84> VK_KEY_S <85> VK_KEY_D <86> VK_KEY_F <87> VK_KEY_G <88> VK_KEY_H <89> VK_KEY_J <90> VK_KEY_K <91> VK_KEY_L <92> VK_OEM_1 <93> VK_OEM_7 <94> VK_OEM_5 <95> VK_RETURN <96> VK_LSHIFT <106> VK_KEY_Z <107> VK_KEY_X <108> VK_KEY_C <109> VK_KEY_V <110> VK_KEY_B <111> VK_KEY_N <112> VK_KEY_M <113> VK_OEM_COMMA <114> VK_OEM_PERIOD <115> VK_OEM_2 <116> VK_RSHIFT <117> VK_HELP <125> VK_CAPITAL <126> VK_LMENU <26> VK_SPACE <128> VK_APPS <74> VK_F1 <12> VK_F2 <13> VK_F3 <15> VK_F4 <17> VK_F5 <19> VK_F6 <21> VK_F7 <23> VK_F8 <24> VK_F9 <25> VK_F10 <14> VK_F11 <16> VK_F12 <18> VK_SNAPSHOT <29> VK_SCROLL <30> VK_PAUSE <28> VK_NUMLOCK <105> VK_DIVIDE <53> VK_MULTIPLY <54> VK_SUBTRACT <78> VK_NUMPAD7 <75> VK_NUMPAD8 <76> VK_NUMPAD9 <77> VK_ADD <132> VK_NUMPAD4 <98> VK_NUMPAD5 <99> VK_NUMPAD6 <100> VK_NUMPAD1 <119> VK_NUMPAD2 <120> VK_NUMPAD3 <121> VK_RETURN <97> VK_NUMPAD0 <101> VK_DECIMAL <57> }; keyboard "type5" { VK_ESCAPE <36> VK_KEY_1 <37> VK_KEY_2 <38> VK_KEY_3 <39> VK_KEY_4 <40> VK_KEY_5 <41> VK_KEY_6 <42> VK_KEY_7 <43> VK_KEY_8 <44> VK_KEY_9 <45> VK_KEY_0 <46> VK_OEM_MINUS <47> VK_OEM_PLUS <48> VK_OEM_3 <49> VK_BACK <50> VK_TAB <60> VK_KEY_Q <61> VK_KEY_W <62> VK_KEY_E <63> VK_KEY_R <64> VK_KEY_T <65> VK_KEY_Y <66> VK_KEY_U <67> VK_KEY_I <68> VK_KEY_O <69> VK_KEY_P <70> VK_OEM_4 <71> VK_OEM_6 <72> VK_DELETE <73> VK_APPS <74> VK_LCONTROL <83> VK_KEY_A <84> VK_KEY_S <85> VK_KEY_D <86> VK_KEY_F <87> VK_KEY_G <88> VK_KEY_H <89> VK_KEY_J <90> VK_KEY_K <91> VK_KEY_L <92> VK_OEM_1 <93> VK_OEM_7 <94> VK_OEM_5 <95> VK_RETURN <96> VK_LSHIFT <106> VK_KEY_Z <107> VK_KEY_X <108> VK_KEY_C <109> VK_KEY_V <110> VK_KEY_B <111> VK_KEY_N <112> VK_KEY_M <113> VK_OEM_COMMA <114> VK_OEM_PERIOD <115> VK_OEM_2 <116> VK_RSHIFT <117> VK_LMENU <26> VK_CAPITAL <126> VK_SPACE <128> VK_F1 <12> VK_F2 <13> VK_F3 <15> VK_F4 <17> VK_F5 <19> VK_F6 <21> VK_F7 <23> VK_F8 <24> VK_F9 <25> VK_F10 <14> VK_F11 <16> VK_F12 <18> VK_SNAPSHOT <29> VK_SCROLL <30> VK_PAUSE <28> VK_NUMLOCK <105> VK_DIVIDE <53> VK_MULTIPLY <54> VK_SUBTRACT <78> VK_NUMPAD7 <75> VK_NUMPAD8 <76> VK_NUMPAD9 <77> VK_ADD <132> VK_NUMPAD4 <98> VK_NUMPAD5 <99> VK_NUMPAD6 <100> VK_NUMPAD1 <119> VK_NUMPAD2 <120> VK_NUMPAD3 <121> VK_RETURN <97> VK_NUMPAD0 <101> VK_DECIMAL <57> VK_UP <27> VK_LEFT <31> VK_DOWN <34> VK_RIGHT <35> VK_INSERT <51> VK_HOME <59> VK_END <81> VK_PRIOR <103> VK_NEXT <130> VK_HELP <125> }; keyboard "type4tuv" : extends "sun(type4)" { VK_OEM_102 <131> }; keyboard "type4_ca" : extends "sun(type4)" { VK_OEM_102 <131> }; keyboard "type4_jp" : extends "sun(type4)" { VK_KANJI <123> }; keyboard "type4_euro" : extends "sun(type4)" { VK_OEM_102 <131> }; keyboard "type5tuv" : extends "sun(type5)" { VK_OEM_102 <131> }; keyboard "type5_jp" : extends "sun(type5)" { VK_KANJI <123> }; keyboard "type5_euro" : extends "sun(type5)" { VK_OEM_102 <131> }; keyboard "type5hobo" { VK_ESCAPE <36> VK_KEY_1 <37> VK_KEY_2 <38> VK_KEY_3 <39> VK_KEY_4 <40> VK_KEY_5 <41> VK_KEY_6 <42> VK_KEY_7 <43> VK_KEY_8 <44> VK_KEY_9 <45> VK_KEY_0 <46> VK_OEM_MINUS <47> VK_OEM_PLUS <48> VK_OEM_3 <49> VK_BACK <50> VK_TAB <60> VK_KEY_Q <61> VK_KEY_W <62> VK_KEY_E <63> VK_KEY_R <64> VK_KEY_T <65> VK_KEY_Y <66> VK_KEY_U <67> VK_KEY_I <68> VK_KEY_O <69> VK_KEY_P <70> VK_OEM_4 <71> VK_OEM_6 <72> VK_DELETE <73> VK_APPS <74> VK_LCONTROL <83> VK_KEY_A <84> VK_KEY_S <85> VK_KEY_D <86> VK_KEY_F <87> VK_KEY_G <88> VK_KEY_H <89> VK_KEY_J <90> VK_KEY_K <91> VK_KEY_L <92> VK_OEM_1 <93> VK_OEM_7 <94> VK_OEM_5 <95> VK_RETURN <96> VK_LSHIFT <106> VK_KEY_Z <107> VK_KEY_X <108> VK_KEY_C <109> VK_KEY_V <110> VK_KEY_B <111> VK_KEY_N <112> VK_KEY_M <113> VK_OEM_COMMA <114> VK_OEM_PERIOD <115> VK_OEM_2 <116> VK_RSHIFT <117> VK_LMENU <26> VK_CAPITAL <126> VK_SPACE <128> VK_F1 <12> VK_F2 <13> VK_F3 <15> VK_F4 <17> VK_F5 <19> VK_F6 <21> VK_F7 <23> VK_F8 <24> VK_F9 <25> VK_F10 <14> VK_F11 <16> VK_F12 <18> VK_SNAPSHOT <29> VK_SCROLL <30> VK_PAUSE <28> VK_NUMLOCK <105> VK_DIVIDE <53> VK_MULTIPLY <54> VK_SUBTRACT <78> VK_NUMPAD7 <75> VK_NUMPAD8 <76> VK_NUMPAD9 <77> VK_ADD <132> VK_NUMPAD4 <98> VK_NUMPAD5 <99> VK_NUMPAD6 <100> VK_NUMPAD1 <119> VK_NUMPAD2 <120> VK_NUMPAD3 <121> VK_RETURN <97> VK_NUMPAD0 <101> VK_DECIMAL <57> VK_UP <27> VK_LEFT <31> VK_DOWN <34> VK_RIGHT <35> VK_INSERT <51> VK_HOME <59> VK_END <81> VK_PRIOR <103> VK_NEXT <130> VK_HELP <125> }; keyboard "type5tuvhobo" : extends "sun(type5hobo)" { VK_OEM_102 <131> }; keyboard "type5_jphobo" : extends "sun(type5hobo)" { VK_KANJI <123> }; keyboard "type6" : extends "sun(type5)" { }; keyboard "type6tuv" : extends "sun(type5tuv)" { }; keyboard "type6unix" : extends "sun(type5)" { }; keyboard "type6_jp" : extends "sun(type5_jp)" { }; keyboard "type6_euro" : extends "sun(type5_euro)" { }; keyboard "type6_usb" : extends "xfree86" { VK_HELP <245> }; keyboard "type6tuv_usb" : extends "sun(type6_usb)" { VK_OEM_102 <94> VK_OEM_5 <51> }; keyboard "type6_jp_usb" : extends "sun(type6_usb)" { }; keyboard "type5_se" { VK_HELP <125> VK_ESCAPE <36> VK_F1 <12> VK_F2 <13> VK_F3 <15> VK_F4 <17> VK_F5 <19> VK_F6 <21> VK_F7 <23> VK_F8 <24> VK_F9 <25> VK_F10 <14> VK_F11 <16> VK_F12 <18> VK_SNAPSHOT <29> VK_SCROLL <30> VK_PAUSE <28> VK_TILDE <49> VK_KEY_1 <37> VK_KEY_2 <38> VK_KEY_3 <39> VK_KEY_4 <40> VK_KEY_5 <41> VK_KEY_6 <42> VK_KEY_7 <43> VK_KEY_8 <44> VK_KEY_9 <45> VK_KEY_0 <46> VK_OEM_MINUS <47> VK_OEM_PLUS <48> VK_BACK <50> VK_INSERT <51> VK_HOME <59> VK_PRIOR <103> VK_NUMLOCK <105> VK_DIVIDE <53> VK_MULTIPLY <54> VK_SUBTRACT <78> VK_KEY_Q <61> VK_KEY_W <62> VK_KEY_E <63> VK_KEY_R <64> VK_KEY_T <65> VK_KEY_Y <66> VK_KEY_U <67> VK_KEY_I <68> VK_KEY_O <69> VK_KEY_P <70> VK_OEM_4 <71> VK_OEM_6 <72> VK_DELETE <73> VK_END <81> VK_NEXT <130> VK_NUMPAD7 <75> VK_NUMPAD8 <76> VK_NUMPAD9 <77> VK_ADD <132> VK_KEY_A <84> VK_KEY_S <85> VK_KEY_D <86> VK_KEY_F <87> VK_KEY_G <88> VK_KEY_H <89> VK_KEY_J <90> VK_KEY_K <91> VK_KEY_L <92> VK_OEM_1 <93> VK_OEM_7 <94> VK_OEM_5 <95> VK_RETURN <96> VK_NUMPAD4 <98> VK_NUMPAD5 <99> VK_NUMPAD6 <100> VK_LSHIFT <106> VK_LSHIFT <131> VK_KEY_Z <107> VK_KEY_X <108> VK_KEY_C <109> VK_KEY_V <110> VK_KEY_B <111> VK_KEY_N <112> VK_KEY_M <113> VK_OEM_COMMA <114> VK_OEM_PERIOD <115> VK_OEM_2 <116> VK_RSHIFT <117> VK_UP <27> VK_NUMPAD1 <119> VK_NUMPAD2 <120> VK_NUMPAD3 <121> VK_RETURN <97> VK_LCONTROL <83> VK_LMENU <26> VK_SPACE <128> VK_APPS <74> VK_LEFT <31> VK_DOWN <34> VK_RIGHT <35> VK_NUMPAD0 <101> VK_DECIMAL <57> }; keyboard "type5c_se" : extends "sun(type5_se)" { }; keyboard "type4__se" { VK_F1 <12> VK_F2 <13> VK_F3 <15> VK_F4 <17> VK_F5 <19> VK_F6 <21> VK_F7 <23> VK_F8 <24> VK_F9 <25> VK_F10 <14> VK_F11 <16> VK_F12 <18> VK_DELETE <73> VK_PAUSE <28> VK_SNAPSHOT <29> VK_SCROLL <30> VK_NUMLOCK <105> VK_TILDE <36> VK_KEY_1 <37> VK_KEY_2 <38> VK_KEY_3 <39> VK_KEY_4 <40> VK_KEY_5 <41> VK_KEY_6 <42> VK_KEY_7 <43> VK_KEY_8 <44> VK_KEY_9 <45> VK_KEY_0 <46> VK_OEM_MINUS <47> VK_OEM_PLUS <48> VK_BACK <50> VK_DIVIDE <53> VK_MULTIPLY <54> VK_SUBTRACT <78> VK_KEY_Q <61> VK_KEY_W <62> VK_KEY_E <63> VK_KEY_R <64> VK_KEY_T <65> VK_KEY_Y <66> VK_KEY_U <67> VK_KEY_I <68> VK_KEY_O <69> VK_KEY_P <70> VK_OEM_4 <71> VK_OEM_6 <72> VK_NUMPAD7 <75> VK_NUMPAD8 <76> VK_NUMPAD9 <77> VK_ADD <132> VK_KEY_A <84> VK_KEY_S <85> VK_KEY_D <86> VK_KEY_F <87> VK_KEY_G <88> VK_KEY_H <89> VK_KEY_J <90> VK_KEY_K <91> VK_KEY_L <92> VK_OEM_1 <93> VK_OEM_7 <94> VK_OEM_5 <49> VK_RETURN <96> VK_NUMPAD4 <98> VK_NUMPAD5 <99> VK_NUMPAD6 <100> VK_LSHIFT <106> VK_LSHIFT <131> VK_KEY_Z <107> VK_KEY_X <108> VK_KEY_C <109> VK_KEY_V <110> VK_KEY_B <111> VK_KEY_N <112> VK_KEY_M <113> VK_OEM_COMMA <114> VK_OEM_PERIOD <115> VK_OEM_2 <116> VK_RSHIFT <117> VK_NUMPAD1 <119> VK_NUMPAD2 <120> VK_NUMPAD3 <121> VK_RETURN <97> VK_HELP <125> VK_LMENU <26> VK_SPACE <128> VK_APPS <74> VK_NUMPAD0 <101> VK_DECIMAL <57> }; keyboard "type4_se" { }; keyboard "type4_se_swapctl" { }; FreeRDP-1.0.2/keymaps/xfree86000066400000000000000000000045111207112532300156210ustar00rootroot00000000000000# This file was generated with xkb.pl (Wed Aug 11 09:09:10 2010) # and is based on the X Keyboard Configuration Database version 1.9 # Please use xkb.pl to re-export newer versions of XKB keyboard "xfree86" : extends "xfree86(basic)" { VK_OEM_5 <51> VK_OEM_102 <94> }; keyboard "basic" { VK_OEM_3 <49> VK_KEY_1 <10> VK_KEY_2 <11> VK_KEY_3 <12> VK_KEY_4 <13> VK_KEY_5 <14> VK_KEY_6 <15> VK_KEY_7 <16> VK_KEY_8 <17> VK_KEY_9 <18> VK_KEY_0 <19> VK_OEM_MINUS <20> VK_OEM_PLUS <21> VK_BACK <22> VK_TAB <23> VK_KEY_Q <24> VK_KEY_W <25> VK_KEY_E <26> VK_KEY_R <27> VK_KEY_T <28> VK_KEY_Y <29> VK_KEY_U <30> VK_KEY_I <31> VK_KEY_O <32> VK_KEY_P <33> VK_OEM_4 <34> VK_OEM_6 <35> VK_RETURN <36> VK_CAPITAL <66> VK_KEY_A <38> VK_KEY_S <39> VK_KEY_D <40> VK_KEY_F <41> VK_KEY_G <42> VK_KEY_H <43> VK_KEY_J <44> VK_KEY_K <45> VK_KEY_L <46> VK_OEM_1 <47> VK_OEM_7 <48> VK_LSHIFT <50> VK_KEY_Z <52> VK_KEY_X <53> VK_KEY_C <54> VK_KEY_V <55> VK_KEY_B <56> VK_KEY_N <57> VK_KEY_M <58> VK_OEM_COMMA <59> VK_OEM_PERIOD <60> VK_OEM_2 <61> VK_RSHIFT <62> VK_LMENU <64> VK_LCONTROL <37> VK_SPACE <65> VK_RCONTROL <109> VK_RMENU <113> VK_LWIN <115> VK_RWIN <116> VK_APPS <117> VK_ESCAPE <9> VK_F1 <67> VK_F2 <68> VK_F3 <69> VK_F4 <70> VK_F5 <71> VK_F6 <72> VK_F7 <73> VK_F8 <74> VK_F9 <75> VK_F10 <76> VK_F11 <95> VK_F12 <96> VK_SNAPSHOT <111> VK_SCROLL <78> VK_PAUSE <110> VK_INSERT <106> VK_HOME <97> VK_PRIOR <99> VK_DELETE <107> VK_END <103> VK_NEXT <105> VK_UP <98> VK_LEFT <100> VK_DOWN <104> VK_RIGHT <102> VK_NUMLOCK <77> VK_DIVIDE <112> VK_MULTIPLY <63> VK_SUBTRACT <82> VK_NUMPAD7 <79> VK_NUMPAD8 <80> VK_NUMPAD9 <81> VK_ADD <86> VK_NUMPAD4 <83> VK_NUMPAD5 <84> VK_NUMPAD6 <85> VK_NUMPAD1 <87> VK_NUMPAD2 <88> VK_NUMPAD3 <89> VK_RETURN <108> VK_NUMPAD0 <90> VK_DECIMAL <91> VK_F13 <118> VK_F14 <119> VK_F15 <120> VK_F16 <121> VK_F17 <122> VK_ABNT_C1 <211> }; keyboard "102" : extends "xfree86(xfree86)" { VK_RMENU <122> VK_RCONTROL <123> VK_SNAPSHOT <121> VK_PAUSE <118> VK_INSERT <131> VK_HOME <135> VK_PRIOR <119> VK_DELETE <129> VK_END <130> VK_NEXT <134> VK_UP <128> VK_LEFT <132> VK_DOWN <120> VK_RIGHT <133> VK_DIVIDE <125> VK_RETURN <124> }; keyboard "thinkpadz60" : extends "xfree86(xfree86)" { VK_APPS <227> }; FreeRDP-1.0.2/keymaps/xfree98000066400000000000000000000032561207112532300156310ustar00rootroot00000000000000# This file was generated with xkb.pl (Wed Aug 11 09:09:10 2010) # and is based on the X Keyboard Configuration Database version 1.9 # Please use xkb.pl to re-export newer versions of XKB keyboard "pc98" { VK_ESCAPE <8> VK_KEY_1 <9> VK_KEY_2 <10> VK_KEY_3 <11> VK_KEY_4 <12> VK_KEY_5 <13> VK_KEY_6 <14> VK_KEY_7 <15> VK_KEY_8 <16> VK_KEY_9 <17> VK_KEY_0 <18> VK_OEM_MINUS <19> VK_OEM_PLUS <20> VK_OEM_5 <21> VK_BACK <22> VK_TAB <23> VK_KEY_Q <24> VK_KEY_W <25> VK_KEY_E <26> VK_KEY_R <27> VK_KEY_T <28> VK_KEY_Y <29> VK_KEY_U <30> VK_KEY_I <31> VK_KEY_O <32> VK_KEY_P <33> VK_OEM_4 <34> VK_OEM_6 <35> VK_RETURN <36> VK_LCONTROL <124> VK_CAPITAL <121> VK_KEY_A <37> VK_KEY_S <38> VK_KEY_D <39> VK_KEY_F <40> VK_KEY_G <41> VK_KEY_H <42> VK_KEY_J <43> VK_KEY_K <44> VK_KEY_L <45> VK_OEM_1 <46> VK_OEM_7 <47> VK_OEM_5 <48> VK_LSHIFT <120> VK_KEY_Z <49> VK_KEY_X <50> VK_KEY_C <51> VK_KEY_V <52> VK_KEY_B <53> VK_KEY_N <54> VK_KEY_M <55> VK_OEM_COMMA <56> VK_OEM_PERIOD <57> VK_OEM_2 <58> VK_ABNT_C1 <59> VK_LMENU <123> VK_SPACE <60> VK_SNAPSHOT <105> VK_F1 <106> VK_F2 <107> VK_F3 <108> VK_F4 <109> VK_F5 <110> VK_F6 <111> VK_F7 <112> VK_F8 <113> VK_F9 <114> VK_F10 <115> VK_F11 <90> VK_F12 <91> VK_F13 <92> VK_F14 <93> VK_F15 <94> VK_INSERT <64> VK_DELETE <65> VK_PRIOR <63> VK_NEXT <62> VK_UP <66> VK_LEFT <67> VK_RIGHT <68> VK_DOWN <69> VK_HOME <70> VK_HELP <71> VK_SUBTRACT <72> VK_DIVIDE <73> VK_NUMPAD7 <74> VK_NUMPAD8 <75> VK_NUMPAD9 <76> VK_MULTIPLY <77> VK_NUMPAD4 <78> VK_NUMPAD5 <79> VK_NUMPAD6 <80> VK_ADD <81> VK_NUMPAD1 <82> VK_NUMPAD2 <83> VK_NUMPAD3 <84> VK_NUMPAD0 <86> }; FreeRDP-1.0.2/keymaps/xkb.pl000077500000000000000000000175451207112532300155460ustar00rootroot00000000000000#!/usr/bin/perl # FreeRDP: A Remote Desktop Protocol client. # XKB database conversion script # Copyright 2009 Marc-Andre Moreau # 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. # Description: # Script to export XKB configuration files to keycode -> virtual key code keymaps that are # easy to use in FreeRDP. This makes keymap maintenance easier to make as all bugs can # simply be reported to the XKB Configuration Database project, and then this script can # be used to export newer (and fixed) version of the XKB Configuration Database. use Cwd; my %sym2virt = ( "AE00" => "VK_TILDE", "AE01" => "VK_KEY_1", "AE02" => "VK_KEY_2", "AE03" => "VK_KEY_3", "AE04" => "VK_KEY_4", "AE05" => "VK_KEY_5", "AE06" => "VK_KEY_6", "AE07" => "VK_KEY_7", "AE08" => "VK_KEY_8", "AE09" => "VK_KEY_9", "AE10" => "VK_KEY_0", "AE11" => "VK_OEM_MINUS", "AE12" => "VK_OEM_PLUS", "AD01" => "VK_KEY_Q", "AD02" => "VK_KEY_W", "AD03" => "VK_KEY_E", "AD04" => "VK_KEY_R", "AD05" => "VK_KEY_T", "AD06" => "VK_KEY_Y", "AD07" => "VK_KEY_U", "AD08" => "VK_KEY_I", "AD09" => "VK_KEY_O", "AD10" => "VK_KEY_P", "AD11" => "VK_OEM_4", "AD12" => "VK_OEM_6", "AC01" => "VK_KEY_A", "AC02" => "VK_KEY_S", "AC03" => "VK_KEY_D", "AC04" => "VK_KEY_F", "AC05" => "VK_KEY_G", "AC06" => "VK_KEY_H", "AC07" => "VK_KEY_J", "AC08" => "VK_KEY_K", "AC09" => "VK_KEY_L", "AC10" => "VK_OEM_1", "AC11" => "VK_OEM_7", "AC12" => "VK_OEM_5", "AB00" => "VK_LSHIFT", "AB01" => "VK_KEY_Z", "AB02" => "VK_KEY_X", "AB03" => "VK_KEY_C", "AB04" => "VK_KEY_V", "AB05" => "VK_KEY_B", "AB06" => "VK_KEY_N", "AB07" => "VK_KEY_M", "AB08" => "VK_OEM_COMMA", "AB09" => "VK_OEM_PERIOD", "AB10" => "VK_OEM_2", "AB11" => "VK_ABNT_C1", "FK01" => "VK_F1", "FK02" => "VK_F2", "FK03" => "VK_F3", "FK04" => "VK_F4", "FK05" => "VK_F5", "FK06" => "VK_F6", "FK07" => "VK_F7", "FK08" => "VK_F8", "FK09" => "VK_F9", "FK10" => "VK_F10", "FK11" => "VK_F11", "FK12" => "VK_F12", "FK13" => "VK_F13", "FK14" => "VK_F14", "FK15" => "VK_F15", "FK16" => "VK_F16", "FK17" => "VK_F17", "FK18" => "VK_F18", "FK19" => "VK_F19", "FK20" => "VK_F20", "FK21" => "VK_F21", "FK22" => "VK_F22", "FK23" => "VK_F23", "FK24" => "VK_F24", "KP0" => "VK_NUMPAD0", "KP1" => "VK_NUMPAD1", "KP2" => "VK_NUMPAD2", "KP3" => "VK_NUMPAD3", "KP4" => "VK_NUMPAD4", "KP5" => "VK_NUMPAD5", "KP6" => "VK_NUMPAD6", "KP7" => "VK_NUMPAD7", "KP8" => "VK_NUMPAD8", "KP9" => "VK_NUMPAD9", "KPDV" => "VK_DIVIDE", "KPMU" => "VK_MULTIPLY", "KPSU" => "VK_SUBTRACT", "KPAD" => "VK_ADD", "KPDL" => "VK_DECIMAL", "KPEN" => "VK_RETURN", "RTRN" => "VK_RETURN", "SPCE" => "VK_SPACE", "BKSP" => "VK_BACK", "BKSL" => "VK_OEM_5", "LSGT" => "VK_OEM_102", "ESC" => "VK_ESCAPE", "TLDE" => "VK_OEM_3", "CAPS" => "VK_CAPITAL", "TAB" => "VK_TAB", "LFSH" => "VK_LSHIFT", "RTSH" => "VK_RSHIFT", "LCTL" => "VK_LCONTROL", "RCTL" => "VK_RCONTROL", "LWIN" => "VK_LWIN", "RWIN" => "VK_RWIN", "LALT" => "VK_LMENU", "RALT" => "VK_RMENU", "COMP" => "VK_APPS", "MENU" => "VK_APPS", "UP" => "VK_UP", "DOWN" => "VK_DOWN", "LEFT" => "VK_LEFT", "RGHT" => "VK_RIGHT", "INS" => "VK_INSERT", "DELE" => "VK_DELETE", "PGUP" => "VK_PRIOR", "PGDN" => "VK_NEXT", "HOME" => "VK_HOME", "END" => "VK_END", "PAUS" => "VK_PAUSE", "NMLK" => "VK_NUMLOCK", "SCLK" => "VK_SCROLL", # This page helps understanding the keys that follow: # http://www.stanford.edu/class/cs140/projects/pintos/specs/kbd/scancodes-7.html "KANJ" => "VK_KANJI", "HANJ" => "VK_HANJA", "MUHE" => "VK_NONCONVERT", "HIRA" => "VK_KANA", "PRSC" => "VK_SNAPSHOT", "KPF1" => "VK_NUMLOCK", "KPF2" => "VK_DIVIDE", "KPF3" => "VK_MULTIPLY", "KPF4" => "VK_SUBTRACT", "KPCO" => "VK_ADD", "HELP" => "VK_HELP", "SELE" => "VK_SELECT", # We can ignore LDM (Lock Down Modifier) # What are LCMP/RCMP? # DO, FIND? ); my $inDir; my $outDir; if(@ARGV < 1) { $inDir = getcwd() . "/"; $outDir = $inDir; } elsif(@ARGV == 1) { $inDir = $ARGV[0]; $outDir = getcwd() . "/"; } elsif(@ARGV == 2) { $inDir = $ARGV[0]; $outDir = $ARGV[1]; } else { print "Error: Too many arguments\n" . "Usage:\n" . "perl xkb.pl \n" . "perl xkb.pl \n\n" . "In Linux, the XKB directory usually is /usr/share/X11/xkb/\n" . "The latest version of XKB can always be downloaded at:\n" . "http://freedesktop.org/wiki/Software/XKeyboardConfig\n"; exit 0; } open("SPEC", $inDir . "xkeyboard-config.spec"); $xkbVersion = ""; while($line = ) { if($line =~ m/Version:\s+(.\..)/) { $xkbVersion = "version $1"; } } # Create directory if it does not exists if(not -e $outDir) { mkdir $outDir or die("Error: Can't create directory $outDir\n"); } open("KCD", $inDir . "keycodes/keycodes.dir") or die("Error: Can't open $inDir" . "keycodes/keycodes.dir\n"); $previousFile = ""; while($line = ) { if($line =~ m/........ -------- (.+)\((.+)\)/) { if($1 ne $previousFile) { push(@keymapFiles, $1); $previousFile = $1; } } } close("KCD"); foreach $keymapFile (@keymapFiles) { print "File $keymapFile:\n"; @directories = split(/\//, $keymapFile); splice(@directories, @directories - 1, 1); if(@directories > 0) { $directory = $outDir; for($i = 0; $i < @directories; $i++) { $directory .= $directories[$i] . "/"; if(not -e $directory) { mkdir $directory or die("Can't create directory $directory\n"); } } } open("IN", $inDir . "keycodes/" . $keymapFile); open("OUT", ">" . "$outDir" . $keymapFile); print OUT "# This file was generated with xkb.pl\n"; print OUT "# and is based on the X Keyboard Configuration Database $xkbVersion\n"; print OUT "# Please use xkb.pl to re-export newer versions of XKB\n"; print OUT "\n\n"; while($line = ) { if($line =~ m/xkb_keycodes \"(\w+)\"/) { print "Exporting \"$1\"\n"; print OUT "keyboard \"$1\""; while($line = ) { if($line =~ m/include\W+\"(.+)\"/) { print OUT "\n: extends \"$1\""; last; } else { last; } } print OUT "\n{\n"; while($line = ) { if($line =~ m/<(\w{1,4})>\W+=\W+(\w+);/) { if($sym2virt{$1} ne undef) { $vkcode = $sym2virt{$1}; print OUT "\t$vkcode"; if(length($vkcode) < 8) { print OUT "\t"; } print OUT "\t<$2>\n"; } else { # If undef, then this symbolic key code is # missing from the sym2virt hash table # print "\t$1\t$2\n"; } } elsif($line =~ m/};/) { print OUT "};\n\n"; last; } } } } close("IN"); close("OUT"); } FreeRDP-1.0.2/libfreerdp-cache/000077500000000000000000000000001207112532300161145ustar00rootroot00000000000000FreeRDP-1.0.2/libfreerdp-cache/CMakeLists.txt000066400000000000000000000023261207112532300206570ustar00rootroot00000000000000# FreeRDP: A Remote Desktop Protocol Client # libfreerdp-cache cmake build script # # Copyright 2011 O.S. Systems Software Ltda. # Copyright 2011 Otavio Salvador # Copyright 2011 Marc-Andre Moreau # # 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(FREERDP_CACHE_SRCS brush.c pointer.c bitmap.c offscreen.c palette.c glyph.c cache.c) add_library(freerdp-cache ${FREERDP_CACHE_SRCS}) set_target_properties(freerdp-cache PROPERTIES VERSION ${FREERDP_VERSION_FULL} SOVERSION ${FREERDP_VERSION} PREFIX "lib") target_link_libraries(freerdp-cache freerdp-core) target_link_libraries(freerdp-cache freerdp-utils) install(TARGETS freerdp-cache DESTINATION ${CMAKE_INSTALL_LIBDIR}) FreeRDP-1.0.2/libfreerdp-cache/bitmap.c000066400000000000000000000200031207112532300175270ustar00rootroot00000000000000/** * FreeRDP: A Remote Desktop Protocol Client * Bitmap Cache V2 * * Copyright 2011 Marc-Andre Moreau * * 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. */ #include #include #include #include void update_gdi_memblt(rdpContext* context, MEMBLT_ORDER* memblt) { rdpBitmap* bitmap; rdpCache* cache = context->cache; if (memblt->cacheId == 0xFF) bitmap = offscreen_cache_get(cache->offscreen, memblt->cacheIndex); else bitmap = bitmap_cache_get(cache->bitmap, (uint8) memblt->cacheId, memblt->cacheIndex); memblt->bitmap = bitmap; IFCALL(cache->bitmap->MemBlt, context, memblt); } void update_gdi_mem3blt(rdpContext* context, MEM3BLT_ORDER* mem3blt) { rdpBitmap* bitmap; rdpCache* cache = context->cache; if (mem3blt->cacheId == 0xFF) bitmap = offscreen_cache_get(cache->offscreen, mem3blt->cacheIndex); else bitmap = bitmap_cache_get(cache->bitmap, (uint8) mem3blt->cacheId, mem3blt->cacheIndex); mem3blt->bitmap = bitmap; IFCALL(cache->bitmap->Mem3Blt, context, mem3blt); } void update_gdi_cache_bitmap(rdpContext* context, CACHE_BITMAP_ORDER* cache_bitmap) { rdpBitmap* bitmap; rdpBitmap* prevBitmap; rdpCache* cache = context->cache; bitmap = Bitmap_Alloc(context); Bitmap_SetDimensions(context, bitmap, cache_bitmap->bitmapWidth, cache_bitmap->bitmapHeight); bitmap->Decompress(context, bitmap, cache_bitmap->bitmapDataStream, cache_bitmap->bitmapWidth, cache_bitmap->bitmapHeight, cache_bitmap->bitmapBpp, cache_bitmap->bitmapLength, cache_bitmap->compressed); bitmap->New(context, bitmap); prevBitmap = bitmap_cache_get(cache->bitmap, cache_bitmap->cacheId, cache_bitmap->cacheIndex); if (prevBitmap != NULL) Bitmap_Free(context, prevBitmap); bitmap_cache_put(cache->bitmap, cache_bitmap->cacheId, cache_bitmap->cacheIndex, bitmap); } void update_gdi_cache_bitmap_v2(rdpContext* context, CACHE_BITMAP_V2_ORDER* cache_bitmap_v2) { rdpBitmap* bitmap; rdpBitmap* prevBitmap; rdpCache* cache = context->cache; bitmap = Bitmap_Alloc(context); Bitmap_SetDimensions(context, bitmap, cache_bitmap_v2->bitmapWidth, cache_bitmap_v2->bitmapHeight); if (cache_bitmap_v2->bitmapBpp == 0) { /* Workaround for Windows 8 bug where bitmapBpp is not set */ cache_bitmap_v2->bitmapBpp = context->instance->settings->color_depth; } bitmap->Decompress(context, bitmap, cache_bitmap_v2->bitmapDataStream, cache_bitmap_v2->bitmapWidth, cache_bitmap_v2->bitmapHeight, cache_bitmap_v2->bitmapBpp, cache_bitmap_v2->bitmapLength, cache_bitmap_v2->compressed); bitmap->New(context, bitmap); prevBitmap = bitmap_cache_get(cache->bitmap, cache_bitmap_v2->cacheId, cache_bitmap_v2->cacheIndex); if (prevBitmap != NULL) Bitmap_Free(context, prevBitmap); bitmap_cache_put(cache->bitmap, cache_bitmap_v2->cacheId, cache_bitmap_v2->cacheIndex, bitmap); } void update_gdi_bitmap_update(rdpContext* context, BITMAP_UPDATE* bitmap_update) { int i; rdpBitmap* bitmap; BITMAP_DATA* bitmap_data; boolean reused = true; rdpCache* cache = context->cache; if (cache->bitmap->bitmap == NULL) { cache->bitmap->bitmap = Bitmap_Alloc(context); cache->bitmap->bitmap->ephemeral = true; reused = false; } bitmap = cache->bitmap->bitmap; for (i = 0; i < (int) bitmap_update->number; i++) { bitmap_data = &bitmap_update->rectangles[i]; bitmap->bpp = bitmap_data->bitsPerPixel; bitmap->length = bitmap_data->bitmapLength; bitmap->compressed = bitmap_data->compressed; Bitmap_SetRectangle(context, bitmap, bitmap_data->destLeft, bitmap_data->destTop, bitmap_data->destRight, bitmap_data->destBottom); Bitmap_SetDimensions(context, bitmap, bitmap_data->width, bitmap_data->height); bitmap->Decompress(context, bitmap, bitmap_data->bitmapDataStream, bitmap_data->width, bitmap_data->height, bitmap_data->bitsPerPixel, bitmap_data->bitmapLength, bitmap_data->compressed); if (reused) bitmap->Free(context, bitmap); else reused = true; bitmap->New(context, bitmap); bitmap->Paint(context, bitmap); } } rdpBitmap* bitmap_cache_get(rdpBitmapCache* bitmap_cache, uint32 id, uint32 index) { rdpBitmap* bitmap; if (id > bitmap_cache->maxCells) { printf("get invalid bitmap cell id: %d\n", id); return NULL; } if (index == BITMAP_CACHE_WAITING_LIST_INDEX) { index = bitmap_cache->cells[id].number; } else if (index > bitmap_cache->cells[id].number) { printf("get invalid bitmap index %d in cell id: %d\n", index, id); return NULL; } bitmap = bitmap_cache->cells[id].entries[index]; return bitmap; } void bitmap_cache_put(rdpBitmapCache* bitmap_cache, uint32 id, uint32 index, rdpBitmap* bitmap) { if (id > bitmap_cache->maxCells) { printf("put invalid bitmap cell id: %d\n", id); return; } if (index == BITMAP_CACHE_WAITING_LIST_INDEX) { index = bitmap_cache->cells[id].number; } else if (index > bitmap_cache->cells[id].number) { printf("put invalid bitmap index %d in cell id: %d\n", index, id); return; } bitmap_cache->cells[id].entries[index] = bitmap; } void bitmap_cache_register_callbacks(rdpUpdate* update) { rdpCache* cache = update->context->cache; cache->bitmap->MemBlt = update->primary->MemBlt; cache->bitmap->Mem3Blt = update->primary->Mem3Blt; update->primary->MemBlt = update_gdi_memblt; update->primary->Mem3Blt = update_gdi_mem3blt; update->secondary->CacheBitmap = update_gdi_cache_bitmap; update->secondary->CacheBitmapV2 = update_gdi_cache_bitmap_v2; update->BitmapUpdate = update_gdi_bitmap_update; } rdpBitmapCache* bitmap_cache_new(rdpSettings* settings) { int i; rdpBitmapCache* bitmap_cache; bitmap_cache = (rdpBitmapCache*) xzalloc(sizeof(rdpBitmapCache)); if (bitmap_cache != NULL) { bitmap_cache->settings = settings; bitmap_cache->update = ((freerdp*) settings->instance)->update; bitmap_cache->context = bitmap_cache->update->context; bitmap_cache->maxCells = 5; settings->bitmap_cache = false; settings->bitmapCacheV2NumCells = 5; settings->bitmapCacheV2CellInfo[0].numEntries = 600; settings->bitmapCacheV2CellInfo[0].persistent = false; settings->bitmapCacheV2CellInfo[1].numEntries = 600; settings->bitmapCacheV2CellInfo[1].persistent = false; settings->bitmapCacheV2CellInfo[2].numEntries = 2048; settings->bitmapCacheV2CellInfo[2].persistent = false; settings->bitmapCacheV2CellInfo[3].numEntries = 4096; settings->bitmapCacheV2CellInfo[3].persistent = false; settings->bitmapCacheV2CellInfo[4].numEntries = 2048; settings->bitmapCacheV2CellInfo[4].persistent = false; bitmap_cache->cells = (BITMAP_V2_CELL*) xzalloc(sizeof(BITMAP_V2_CELL) * bitmap_cache->maxCells); for (i = 0; i < (int) bitmap_cache->maxCells; i++) { bitmap_cache->cells[i].number = settings->bitmapCacheV2CellInfo[i].numEntries; /* allocate an extra entry for BITMAP_CACHE_WAITING_LIST_INDEX */ bitmap_cache->cells[i].entries = (rdpBitmap**) xzalloc(sizeof(rdpBitmap*) * (bitmap_cache->cells[i].number + 1)); } } return bitmap_cache; } void bitmap_cache_free(rdpBitmapCache* bitmap_cache) { int i, j; rdpBitmap* bitmap; if (bitmap_cache != NULL) { for (i = 0; i < (int) bitmap_cache->maxCells; i++) { for (j = 0; j < (int) bitmap_cache->cells[i].number + 1; j++) { bitmap = bitmap_cache->cells[i].entries[j]; if (bitmap != NULL) { Bitmap_Free(bitmap_cache->context, bitmap); } } xfree(bitmap_cache->cells[i].entries); } if (bitmap_cache->bitmap != NULL) Bitmap_Free(bitmap_cache->context, bitmap_cache->bitmap); xfree(bitmap_cache->cells); xfree(bitmap_cache); } } FreeRDP-1.0.2/libfreerdp-cache/brush.c000066400000000000000000000077421207112532300174150ustar00rootroot00000000000000/** * FreeRDP: A Remote Desktop Protocol Client * Brush Cache * * Copyright 2011 Marc-Andre Moreau * * 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. */ #include #include #include #include #include void update_gdi_patblt(rdpContext* context, PATBLT_ORDER* patblt) { uint8 style; rdpBrush* brush = &patblt->brush; rdpCache* cache = context->cache; style = brush->style; if (brush->style & CACHED_BRUSH) { brush->data = brush_cache_get(cache->brush, brush->index, &brush->bpp); brush->style = 0x03; } IFCALL(cache->brush->PatBlt, context, patblt); brush->style = style; } void update_gdi_cache_brush(rdpContext* context, CACHE_BRUSH_ORDER* cache_brush) { rdpCache* cache = context->cache; brush_cache_put(cache->brush, cache_brush->index, cache_brush->data, cache_brush->bpp); } void* brush_cache_get(rdpBrushCache* brush, uint32 index, uint32* bpp) { void* entry; if (*bpp == 1) { if (index > brush->maxMonoEntries) { printf("invalid brush (%d bpp) index: 0x%04X\n", *bpp, index); return NULL; } *bpp = brush->monoEntries[index].bpp; entry = brush->monoEntries[index].entry; } else { if (index > brush->maxEntries) { printf("invalid brush (%d bpp) index: 0x%04X\n", *bpp, index); return NULL; } *bpp = brush->entries[index].bpp; entry = brush->entries[index].entry; } if (entry == NULL) { printf("invalid brush (%d bpp) at index: 0x%04X\n", *bpp, index); return NULL; } return entry; } void brush_cache_put(rdpBrushCache* brush, uint32 index, void* entry, uint32 bpp) { void* prevEntry; if (bpp == 1) { if (index > brush->maxMonoEntries) { printf("invalid brush (%d bpp) index: 0x%04X\n", bpp, index); return; } prevEntry = brush->monoEntries[index].entry; if (prevEntry != NULL) xfree(prevEntry); brush->monoEntries[index].bpp = bpp; brush->monoEntries[index].entry = entry; } else { if (index > brush->maxEntries) { printf("invalid brush (%d bpp) index: 0x%04X\n", bpp, index); return; } prevEntry = brush->entries[index].entry; if (prevEntry != NULL) xfree(prevEntry); brush->entries[index].bpp = bpp; brush->entries[index].entry = entry; } } void brush_cache_register_callbacks(rdpUpdate* update) { rdpCache* cache = update->context->cache; cache->brush->PatBlt = update->primary->PatBlt; update->primary->PatBlt = update_gdi_patblt; update->secondary->CacheBrush = update_gdi_cache_brush; } rdpBrushCache* brush_cache_new(rdpSettings* settings) { rdpBrushCache* brush; brush = (rdpBrushCache*) xzalloc(sizeof(rdpBrushCache)); if (brush != NULL) { brush->settings = settings; brush->maxEntries = 64; brush->maxMonoEntries = 64; brush->entries = (BRUSH_ENTRY*) xzalloc(sizeof(BRUSH_ENTRY) * brush->maxEntries); brush->monoEntries = (BRUSH_ENTRY*) xzalloc(sizeof(BRUSH_ENTRY) * brush->maxMonoEntries); } return brush; } void brush_cache_free(rdpBrushCache* brush) { int i; if (brush != NULL) { if (brush->entries != NULL) { for (i = 0; i < (int) brush->maxEntries; i++) { if (brush->entries[i].entry != NULL) xfree(brush->entries[i].entry); } xfree(brush->entries); } if (brush->monoEntries != NULL) { for (i = 0; i < (int) brush->maxMonoEntries; i++) { if (brush->monoEntries[i].entry != NULL) xfree(brush->monoEntries[i].entry); } xfree(brush->monoEntries); } xfree(brush); } } FreeRDP-1.0.2/libfreerdp-cache/cache.c000066400000000000000000000030401207112532300173200ustar00rootroot00000000000000/** * FreeRDP: A Remote Desktop Protocol Client * RDP Caches * * Copyright 2011 Marc-Andre Moreau * * 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. */ #include #include #include rdpCache* cache_new(rdpSettings* settings) { rdpCache* cache; cache = (rdpCache*) xzalloc(sizeof(rdpCache)); if (cache != NULL) { cache->settings = settings; cache->glyph = glyph_cache_new(settings); cache->brush = brush_cache_new(settings); cache->pointer = pointer_cache_new(settings); cache->bitmap = bitmap_cache_new(settings); cache->offscreen = offscreen_cache_new(settings); cache->palette = palette_cache_new(settings); } return cache; } void cache_free(rdpCache* cache) { if (cache != NULL) { glyph_cache_free(cache->glyph); brush_cache_free(cache->brush); pointer_cache_free(cache->pointer); bitmap_cache_free(cache->bitmap); offscreen_cache_free(cache->offscreen); palette_cache_free(cache->palette); xfree(cache); } } FreeRDP-1.0.2/libfreerdp-cache/glyph.c000066400000000000000000000303151207112532300174050ustar00rootroot00000000000000/** * FreeRDP: A Remote Desktop Protocol Client * Glyph Cache * * Copyright 2011 Marc-Andre Moreau * * 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. */ #include #include #include #include void update_process_glyph(rdpContext* context, uint8* data, int* index, int* x, int* y, uint32 cacheId, uint32 ulCharInc, uint32 flAccel) { int offset; rdpGlyph* glyph; uint32 cacheIndex; rdpGraphics* graphics; rdpGlyphCache* glyph_cache; graphics = context->graphics; glyph_cache = context->cache->glyph; cacheIndex = data[*index]; glyph = glyph_cache_get(glyph_cache, cacheId, cacheIndex); if ((ulCharInc == 0) && (!(flAccel & SO_CHAR_INC_EQUAL_BM_BASE))) { (*index)++; offset = data[*index]; if (offset & 0x80) { offset = data[*index + 1] | (data[*index + 2] << 8); (*index)++; (*index)++; } if (flAccel & SO_VERTICAL) *y += offset; else *x += offset; } if (glyph != NULL) { Glyph_Draw(context, glyph, glyph->x + *x, glyph->y + *y); if (flAccel & SO_CHAR_INC_EQUAL_BM_BASE) *x += glyph->cx; } } void update_process_glyph_fragments(rdpContext* context, uint8* data, uint32 length, uint32 cacheId, uint32 ulCharInc, uint32 flAccel, uint32 bgcolor, uint32 fgcolor, int x, int y, int bkX, int bkY, int bkWidth, int bkHeight, int opX, int opY, int opWidth, int opHeight) { int n; uint32 id; uint32 size; int index = 0; uint8* fragments; rdpGraphics* graphics; rdpGlyphCache* glyph_cache; graphics = context->graphics; glyph_cache = context->cache->glyph; if (opWidth > 0 && opHeight > 0) Glyph_BeginDraw(context, opX, opY, opWidth, opHeight, bgcolor, fgcolor); else Glyph_BeginDraw(context, 0, 0, 0, 0, bgcolor, fgcolor); while (index < (int) length) { switch (data[index]) { case GLYPH_FRAGMENT_USE: if (index + 2 > (int) length) { /* at least one byte need to follow */ index = length = 0; break; } id = data[index + 1]; fragments = (uint8*) glyph_cache_fragment_get(glyph_cache, id, &size); if (fragments != NULL) { if ((ulCharInc == 0) && (!(flAccel & SO_CHAR_INC_EQUAL_BM_BASE))) { if (flAccel & SO_VERTICAL) y += data[index + 2]; else x += data[index + 2]; } for (n = 0; n < (int) size; n++) { update_process_glyph(context, fragments, &n, &x, &y, cacheId, ulCharInc, flAccel); } } index += (index + 2 < (int) length) ? 3 : 2; length -= index; data = &(data[index]); index = 0; break; case GLYPH_FRAGMENT_ADD: if (index + 3 > (int) length) { /* at least two bytes need to follow */ index = length = 0; break; } id = data[index + 1]; size = data[index + 2]; fragments = (uint8*) xmalloc(size); memcpy(fragments, data, size); glyph_cache_fragment_put(glyph_cache, id, size, fragments); index += 3; length -= index; data = &(data[index]); index = 0; break; default: update_process_glyph(context, data, &index, &x, &y, cacheId, ulCharInc, flAccel); index++; break; } } if (opWidth > 0 && opHeight > 0) Glyph_EndDraw(context, opX, opY, opWidth, opHeight, bgcolor, fgcolor); else Glyph_EndDraw(context, bkX, bkY, bkWidth, bkHeight, bgcolor, fgcolor); } void update_gdi_glyph_index(rdpContext* context, GLYPH_INDEX_ORDER* glyph_index) { rdpGlyphCache* glyph_cache; glyph_cache = context->cache->glyph; update_process_glyph_fragments(context, glyph_index->data, glyph_index->cbData, glyph_index->cacheId, glyph_index->ulCharInc, glyph_index->flAccel, glyph_index->backColor, glyph_index->foreColor, glyph_index->x, glyph_index->y, glyph_index->bkLeft, glyph_index->bkTop, glyph_index->bkRight - glyph_index->bkLeft, glyph_index->bkBottom - glyph_index->bkTop, glyph_index->opLeft, glyph_index->opTop, glyph_index->opRight - glyph_index->opLeft, glyph_index->opBottom - glyph_index->opTop); } void update_gdi_fast_index(rdpContext* context, FAST_INDEX_ORDER* fast_index) { sint32 opLeft, opTop, opRight, opBottom; sint32 x, y; rdpGlyphCache* glyph_cache; glyph_cache = context->cache->glyph; opLeft = fast_index->opLeft; opTop = fast_index->opTop; opRight = fast_index->opRight; opBottom = fast_index->opBottom; x = fast_index->x; y = fast_index->y; if (opBottom == -32768) { uint8 flags = (uint8) (opTop & 0x0F); if (flags & 0x01) opBottom = fast_index->bkBottom; if (flags & 0x02) opRight = fast_index->bkRight; if (flags & 0x04) opTop = fast_index->bkTop; if (flags & 0x08) opLeft = fast_index->bkLeft; } if (opLeft == 0) opLeft = fast_index->bkLeft; if (opRight == 0) opRight = fast_index->bkRight; if (x == -32768) x = fast_index->bkLeft; if (y == -32768) y = fast_index->bkTop; update_process_glyph_fragments(context, fast_index->data, fast_index->cbData, fast_index->cacheId, fast_index->ulCharInc, fast_index->flAccel, fast_index->backColor, fast_index->foreColor, x, y, fast_index->bkLeft, fast_index->bkTop, fast_index->bkRight - fast_index->bkLeft, fast_index->bkBottom - fast_index->bkTop, opLeft, opTop, opRight - opLeft, opBottom - opTop); } void update_gdi_fast_glyph(rdpContext* context, FAST_GLYPH_ORDER* fast_glyph) { sint32 opLeft, opTop, opRight, opBottom; sint32 x, y; GLYPH_DATA_V2* glyph_data; rdpGlyph* glyph; rdpCache* cache = context->cache; uint8 text_data[2]; opLeft = fast_glyph->opLeft; opTop = fast_glyph->opTop; opRight = fast_glyph->opRight; opBottom = fast_glyph->opBottom; x = fast_glyph->x; y = fast_glyph->y; if (opBottom == -32768) { uint8 flags = (uint8) (opTop & 0x0F); if (flags & 0x01) opBottom = fast_glyph->bkBottom; if (flags & 0x02) opRight = fast_glyph->bkRight; if (flags & 0x04) opTop = fast_glyph->bkTop; if (flags & 0x08) opLeft = fast_glyph->bkLeft; } if (opLeft == 0) opLeft = fast_glyph->bkLeft; if (opRight == 0) opRight = fast_glyph->bkRight; if (x == -32768) x = fast_glyph->bkLeft; if (y == -32768) y = fast_glyph->bkTop; if (fast_glyph->glyph_data != NULL) { /* got option font that needs to go into cache */ glyph_data = (GLYPH_DATA_V2*) (fast_glyph->glyph_data); glyph = Glyph_Alloc(context); glyph->x = glyph_data->x; glyph->y = glyph_data->y; glyph->cx = glyph_data->cx; glyph->cy = glyph_data->cy; glyph->aj = glyph_data->aj; glyph->cb = glyph_data->cb; Glyph_New(context, glyph); glyph_cache_put(cache->glyph, fast_glyph->cacheId, fast_glyph->data[0], glyph); xfree(fast_glyph->glyph_data); fast_glyph->glyph_data = NULL; } text_data[0] = fast_glyph->data[0]; text_data[1] = 0; update_process_glyph_fragments(context, text_data, 1, fast_glyph->cacheId, fast_glyph->ulCharInc, fast_glyph->flAccel, fast_glyph->backColor, fast_glyph->foreColor, x, y, fast_glyph->bkLeft, fast_glyph->bkTop, fast_glyph->bkRight - fast_glyph->bkLeft, fast_glyph->bkBottom - fast_glyph->bkTop, opLeft, opTop, opRight - opLeft, opBottom - opTop); } void update_gdi_cache_glyph(rdpContext* context, CACHE_GLYPH_ORDER* cache_glyph) { int i; rdpGlyph* glyph; GLYPH_DATA* glyph_data; rdpCache* cache = context->cache; for (i = 0; i < (int) cache_glyph->cGlyphs; i++) { glyph_data = cache_glyph->glyphData[i]; glyph = Glyph_Alloc(context); glyph->x = glyph_data->x; glyph->y = glyph_data->y; glyph->cx = glyph_data->cx; glyph->cy = glyph_data->cy; glyph->aj = glyph_data->aj; glyph->cb = glyph_data->cb; Glyph_New(context, glyph); glyph_cache_put(cache->glyph, cache_glyph->cacheId, glyph_data->cacheIndex, glyph); cache_glyph->glyphData[i] = NULL; xfree(glyph_data); } } void update_gdi_cache_glyph_v2(rdpContext* context, CACHE_GLYPH_V2_ORDER* cache_glyph_v2) { int i; rdpGlyph* glyph; GLYPH_DATA_V2* glyph_data; rdpCache* cache = context->cache; for (i = 0; i < (int) cache_glyph_v2->cGlyphs; i++) { glyph_data = cache_glyph_v2->glyphData[i]; glyph = Glyph_Alloc(context); glyph->x = glyph_data->x; glyph->y = glyph_data->y; glyph->cx = glyph_data->cx; glyph->cy = glyph_data->cy; glyph->aj = glyph_data->aj; glyph->cb = glyph_data->cb; Glyph_New(context, glyph); glyph_cache_put(cache->glyph, cache_glyph_v2->cacheId, glyph_data->cacheIndex, glyph); cache_glyph_v2->glyphData[i] = NULL; xfree(glyph_data); } } rdpGlyph* glyph_cache_get(rdpGlyphCache* glyph_cache, uint32 id, uint32 index) { rdpGlyph* glyph; if (id > 9) { printf("invalid glyph cache id: %d\n", id); return NULL; } if (index > glyph_cache->glyphCache[id].number) { printf("invalid glyph cache index: %d in cache id: %d\n", index, id); return NULL; } glyph = glyph_cache->glyphCache[id].entries[index]; if (glyph == NULL) { printf("invalid glyph at cache index: %d in cache id: %d\n", index, id); } return glyph; } void glyph_cache_put(rdpGlyphCache* glyph_cache, uint32 id, uint32 index, rdpGlyph* glyph) { rdpGlyph* prevGlyph; if (id > 9) { printf("invalid glyph cache id: %d\n", id); return; } if (index > glyph_cache->glyphCache[id].number) { printf("invalid glyph cache index: %d in cache id: %d\n", index, id); return; } prevGlyph = glyph_cache->glyphCache[id].entries[index]; if (prevGlyph != NULL) { Glyph_Free(glyph_cache->context, prevGlyph); xfree(prevGlyph->aj); xfree(prevGlyph); } glyph_cache->glyphCache[id].entries[index] = glyph; } void* glyph_cache_fragment_get(rdpGlyphCache* glyph_cache, uint32 index, uint32* size) { void* fragment; fragment = glyph_cache->fragCache.entries[index].fragment; *size = (uint8) glyph_cache->fragCache.entries[index].size; if (fragment == NULL) { printf("invalid glyph fragment at index:%d\n", index); } return fragment; } void glyph_cache_fragment_put(rdpGlyphCache* glyph_cache, uint32 index, uint32 size, void* fragment) { void* prevFragment; prevFragment = glyph_cache->fragCache.entries[index].fragment; glyph_cache->fragCache.entries[index].fragment = fragment; glyph_cache->fragCache.entries[index].size = size; if (prevFragment != NULL) { xfree(prevFragment); } } void glyph_cache_register_callbacks(rdpUpdate* update) { update->primary->GlyphIndex = update_gdi_glyph_index; update->primary->FastIndex = update_gdi_fast_index; update->primary->FastGlyph = update_gdi_fast_glyph; update->secondary->CacheGlyph = update_gdi_cache_glyph; update->secondary->CacheGlyphV2 = update_gdi_cache_glyph_v2; } rdpGlyphCache* glyph_cache_new(rdpSettings* settings) { rdpGlyphCache* glyph; glyph = (rdpGlyphCache*) xzalloc(sizeof(rdpGlyphCache)); if (glyph != NULL) { int i; glyph->settings = settings; glyph->context = ((freerdp*) settings->instance)->update->context; if (settings->glyph_cache) settings->glyphSupportLevel = GLYPH_SUPPORT_FULL; for (i = 0; i < 10; i++) { glyph->glyphCache[i].number = settings->glyphCache[i].cacheEntries; glyph->glyphCache[i].maxCellSize = settings->glyphCache[i].cacheMaximumCellSize; glyph->glyphCache[i].entries = (rdpGlyph**) xzalloc(sizeof(rdpGlyph*) * glyph->glyphCache[i].number); } glyph->fragCache.entries = xzalloc(sizeof(FRAGMENT_CACHE_ENTRY) * 256); } return glyph; } void glyph_cache_free(rdpGlyphCache* glyph_cache) { if (glyph_cache != NULL) { int i; void* fragment; for (i = 0; i < 10; i++) { int j; for (j = 0; j < (int) glyph_cache->glyphCache[i].number; j++) { rdpGlyph* glyph; glyph = glyph_cache->glyphCache[i].entries[j]; if (glyph != NULL) { Glyph_Free(glyph_cache->context, glyph); xfree(glyph->aj); xfree(glyph); } } xfree(glyph_cache->glyphCache[i].entries); } for (i = 0; i < 255; i++) { fragment = glyph_cache->fragCache.entries[i].fragment; xfree(fragment); } xfree(glyph_cache->fragCache.entries); xfree(glyph_cache); } } FreeRDP-1.0.2/libfreerdp-cache/offscreen.c000066400000000000000000000105601207112532300202340ustar00rootroot00000000000000/** * FreeRDP: A Remote Desktop Protocol Client * Offscreen Bitmap Cache * * Copyright 2011 Marc-Andre Moreau * * 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. */ #include #include #include void update_gdi_create_offscreen_bitmap(rdpContext* context, CREATE_OFFSCREEN_BITMAP_ORDER* create_offscreen_bitmap) { int i; uint16 index; rdpBitmap* bitmap; rdpCache* cache = context->cache; bitmap = Bitmap_Alloc(context); bitmap->width = create_offscreen_bitmap->cx; bitmap->height = create_offscreen_bitmap->cy; bitmap->New(context, bitmap); offscreen_cache_delete(cache->offscreen, create_offscreen_bitmap->id); offscreen_cache_put(cache->offscreen, create_offscreen_bitmap->id, bitmap); if(cache->offscreen->currentSurface == create_offscreen_bitmap->id) Bitmap_SetSurface(context, bitmap, false); for (i = 0; i < (int) create_offscreen_bitmap->deleteList.cIndices; i++) { index = create_offscreen_bitmap->deleteList.indices[i]; offscreen_cache_delete(cache->offscreen, index); } } void update_gdi_switch_surface(rdpContext* context, SWITCH_SURFACE_ORDER* switch_surface) { rdpCache* cache = context->cache; if (switch_surface->bitmapId == SCREEN_BITMAP_SURFACE) { Bitmap_SetSurface(context, NULL, true); } else { rdpBitmap* bitmap; bitmap = offscreen_cache_get(cache->offscreen, switch_surface->bitmapId); Bitmap_SetSurface(context, bitmap, false); } cache->offscreen->currentSurface = switch_surface->bitmapId; } rdpBitmap* offscreen_cache_get(rdpOffscreenCache* offscreen_cache, uint32 index) { rdpBitmap* bitmap; if (index > offscreen_cache->maxEntries) { printf("invalid offscreen bitmap index: 0x%04X\n", index); return NULL; } bitmap = offscreen_cache->entries[index]; if (bitmap == NULL) { printf("invalid offscreen bitmap at index: 0x%04X\n", index); return NULL; } return bitmap; } void offscreen_cache_put(rdpOffscreenCache* offscreen, uint32 index, rdpBitmap* bitmap) { if (index > offscreen->maxEntries) { printf("invalid offscreen bitmap index: 0x%04X\n", index); return; } offscreen_cache_delete(offscreen, index); offscreen->entries[index] = bitmap; } void offscreen_cache_delete(rdpOffscreenCache* offscreen, uint32 index) { rdpBitmap* prevBitmap; if (index > offscreen->maxEntries) { printf("invalid offscreen bitmap index (delete): 0x%04X\n", index); return; } prevBitmap = offscreen->entries[index]; if (prevBitmap != NULL) Bitmap_Free(offscreen->update->context, prevBitmap); offscreen->entries[index] = NULL; } void offscreen_cache_register_callbacks(rdpUpdate* update) { update->altsec->CreateOffscreenBitmap = update_gdi_create_offscreen_bitmap; update->altsec->SwitchSurface = update_gdi_switch_surface; } rdpOffscreenCache* offscreen_cache_new(rdpSettings* settings) { rdpOffscreenCache* offscreen_cache; offscreen_cache = (rdpOffscreenCache*) xzalloc(sizeof(rdpOffscreenCache)); if (offscreen_cache != NULL) { offscreen_cache->settings = settings; offscreen_cache->update = ((freerdp*) settings->instance)->update; offscreen_cache->currentSurface = SCREEN_BITMAP_SURFACE; offscreen_cache->maxSize = 7680; offscreen_cache->maxEntries = 100; settings->offscreen_bitmap_cache_size = offscreen_cache->maxSize; settings->offscreen_bitmap_cache_entries = offscreen_cache->maxEntries; offscreen_cache->entries = (rdpBitmap**) xzalloc(sizeof(rdpBitmap*) * offscreen_cache->maxEntries); } return offscreen_cache; } void offscreen_cache_free(rdpOffscreenCache* offscreen_cache) { int i; rdpBitmap* bitmap; if (offscreen_cache != NULL) { for (i = 0; i < (int) offscreen_cache->maxEntries; i++) { bitmap = offscreen_cache->entries[i]; if (bitmap != NULL) Bitmap_Free(offscreen_cache->update->context, bitmap); } xfree(offscreen_cache->entries); xfree(offscreen_cache); } } FreeRDP-1.0.2/libfreerdp-cache/palette.c000066400000000000000000000045051207112532300177220ustar00rootroot00000000000000/** * FreeRDP: A Remote Desktop Protocol Client * Palette (Color Table) Cache * * Copyright 2011 Marc-Andre Moreau * * 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. */ #include #include #include void update_gdi_cache_color_table(rdpContext* context, CACHE_COLOR_TABLE_ORDER* cache_color_table) { rdpCache* cache = context->cache; palette_cache_put(cache->palette, cache_color_table->cacheIndex, (void*) cache_color_table->colorTable); } void* palette_cache_get(rdpPaletteCache* palette_cache, uint32 index) { void* entry; if (index > palette_cache->maxEntries) { printf("invalid color table index: 0x%04X\n", index); return NULL; } entry = palette_cache->entries[index].entry; if (entry == NULL) { printf("invalid color table at index: 0x%04X\n", index); return NULL; } return entry; } void palette_cache_put(rdpPaletteCache* palette_cache, uint32 index, void* entry) { if (index > palette_cache->maxEntries) { printf("invalid color table index: 0x%04X\n", index); return; } palette_cache->entries[index].entry = entry; } void palette_cache_register_callbacks(rdpUpdate* update) { update->secondary->CacheColorTable = update_gdi_cache_color_table; } rdpPaletteCache* palette_cache_new(rdpSettings* settings) { rdpPaletteCache* palette_cache; palette_cache = (rdpPaletteCache*) xzalloc(sizeof(rdpPaletteCache)); if (palette_cache != NULL) { palette_cache->settings = settings; palette_cache->maxEntries = 6; palette_cache->entries = (PALETTE_TABLE_ENTRY*) xzalloc(sizeof(PALETTE_TABLE_ENTRY) * palette_cache->maxEntries); } return palette_cache; } void palette_cache_free(rdpPaletteCache* palette_cache) { if (palette_cache != NULL) { xfree(palette_cache->entries); xfree(palette_cache); } } FreeRDP-1.0.2/libfreerdp-cache/pointer.c000066400000000000000000000100251207112532300177360ustar00rootroot00000000000000/** * FreeRDP: A Remote Desktop Protocol Client * Glyph Cache * * Copyright 2011 Marc-Andre Moreau * * 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. */ #include #include #include void update_pointer_position(rdpContext* context, POINTER_POSITION_UPDATE* pointer_position) { } void update_pointer_system(rdpContext* context, POINTER_SYSTEM_UPDATE* pointer_system) { } void update_pointer_color(rdpContext* context, POINTER_COLOR_UPDATE* pointer_color) { } void update_pointer_new(rdpContext* context, POINTER_NEW_UPDATE* pointer_new) { rdpPointer* pointer; rdpCache* cache = context->cache; pointer = Pointer_Alloc(context); if (pointer != NULL) { pointer->xorBpp = pointer_new->xorBpp; pointer->xPos = pointer_new->colorPtrAttr.xPos; pointer->yPos = pointer_new->colorPtrAttr.yPos; pointer->width = pointer_new->colorPtrAttr.width; pointer->height = pointer_new->colorPtrAttr.height; pointer->lengthAndMask = pointer_new->colorPtrAttr.lengthAndMask; pointer->lengthXorMask = pointer_new->colorPtrAttr.lengthXorMask; pointer->xorMaskData = pointer_new->colorPtrAttr.xorMaskData; pointer->andMaskData = pointer_new->colorPtrAttr.andMaskData; pointer->New(context, pointer); pointer_cache_put(cache->pointer, pointer_new->colorPtrAttr.cacheIndex, pointer); Pointer_Set(context, pointer); } } void update_pointer_cached(rdpContext* context, POINTER_CACHED_UPDATE* pointer_cached) { rdpPointer* pointer; rdpCache* cache = context->cache; pointer = pointer_cache_get(cache->pointer, pointer_cached->cacheIndex); if (pointer != NULL) Pointer_Set(context, pointer); } rdpPointer* pointer_cache_get(rdpPointerCache* pointer_cache, uint32 index) { rdpPointer* pointer; if (index >= pointer_cache->cacheSize) { printf("invalid pointer index:%d\n", index); return NULL; } pointer = pointer_cache->entries[index]; return pointer; } void pointer_cache_put(rdpPointerCache* pointer_cache, uint32 index, rdpPointer* pointer) { rdpPointer* prevPointer; if (index >= pointer_cache->cacheSize) { printf("invalid pointer index:%d\n", index); return; } prevPointer = pointer_cache->entries[index]; if (prevPointer != NULL) Pointer_Free(pointer_cache->update->context, prevPointer); pointer_cache->entries[index] = pointer; } void pointer_cache_register_callbacks(rdpUpdate* update) { rdpPointerUpdate* pointer = update->pointer; pointer->PointerPosition = update_pointer_position; pointer->PointerSystem = update_pointer_system; pointer->PointerColor = update_pointer_color; pointer->PointerNew = update_pointer_new; pointer->PointerCached = update_pointer_cached; } rdpPointerCache* pointer_cache_new(rdpSettings* settings) { rdpPointerCache* pointer_cache; pointer_cache = (rdpPointerCache*) xzalloc(sizeof(rdpPointerCache)); if (pointer_cache != NULL) { pointer_cache->settings = settings; pointer_cache->cacheSize = settings->pointer_cache_size; pointer_cache->update = ((freerdp*) settings->instance)->update; pointer_cache->entries = (rdpPointer**) xzalloc(sizeof(rdpPointer*) * pointer_cache->cacheSize); } return pointer_cache; } void pointer_cache_free(rdpPointerCache* pointer_cache) { if (pointer_cache != NULL) { int i; rdpPointer* pointer; for (i = 0; i < (int) pointer_cache->cacheSize; i++) { pointer = pointer_cache->entries[i]; if (pointer != NULL) Pointer_Free(pointer_cache->update->context, pointer); } xfree(pointer_cache->entries); xfree(pointer_cache); } } FreeRDP-1.0.2/libfreerdp-channels/000077500000000000000000000000001207112532300166445ustar00rootroot00000000000000FreeRDP-1.0.2/libfreerdp-channels/CMakeLists.txt000066400000000000000000000022401207112532300214020ustar00rootroot00000000000000# FreeRDP: A Remote Desktop Protocol Client # libfreerdp-chanman cmake build script # # Copyright 2011 O.S. Systems Software Ltda. # Copyright 2011 Otavio Salvador # Copyright 2011 Marc-Andre Moreau # # 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(FREERDP_CHANNELS_SRCS libchannels.c libchannels.h wtsvc.c wtsvc.h) add_library(freerdp-channels ${FREERDP_CHANNELS_SRCS}) set_target_properties(freerdp-channels PROPERTIES VERSION ${FREERDP_VERSION_FULL} SOVERSION ${FREERDP_VERSION} PREFIX "lib") target_link_libraries(freerdp-channels freerdp-utils) install(TARGETS freerdp-channels DESTINATION ${CMAKE_INSTALL_LIBDIR}) FreeRDP-1.0.2/libfreerdp-channels/libchannels.c000066400000000000000000000564451207112532300213100ustar00rootroot00000000000000/** * FreeRDP: A Remote Desktop Protocol client. * Virtual Channel Manager * * Copyright 2009-2011 Jay Sorg * Copyright 2010-2011 Vic Lee * * 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. */ /** * MS compatible plugin interface * reference: * http://msdn.microsoft.com/en-us/library/aa383580.aspx * * Notes on threads: * Many virtual channel plugins are built using threads. * Non main threads may call MyVirtualChannelOpen, * MyVirtualChannelClose, or MyVirtualChannelWrite. * Since the plugin's VirtualChannelEntry function is called * from the main thread, MyVirtualChannelInit has to be called * from the main thread. */ #include "config.h" #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include "libchannels.h" #define CHANNEL_MAX_COUNT 30 struct lib_data { PVIRTUALCHANNELENTRY entry; /* the one and only exported function */ PCHANNEL_INIT_EVENT_FN init_event_proc; void* init_handle; }; struct channel_data { char name[CHANNEL_NAME_LEN + 1]; int open_handle; int options; int flags; /* 0 nothing 1 init 2 open */ PCHANNEL_OPEN_EVENT_FN open_event_proc; }; struct sync_data { void* data; uint32 data_length; void* user_data; int index; }; typedef struct rdp_init_handle rdpInitHandle; struct rdp_init_handle { rdpChannels* channels; }; struct rdp_channels { /** * Only the main thread alters these arrays, before any * library thread is allowed in(post_connect is called) * so no need to use mutex locking * After post_connect, each library thread can only access it's * own array items * ie, no two threads can access index 0, ... */ struct lib_data libs_data[CHANNEL_MAX_COUNT]; int num_libs_data; struct channel_data channels_data[CHANNEL_MAX_COUNT]; int num_channels_data; rdpInitHandle init_handles[CHANNEL_MAX_COUNT]; int num_init_handles; /* control for entry into MyVirtualChannelInit */ int can_call_init; rdpSettings* settings; /* true once freerdp_chanman_post_connect is called */ int is_connected; /* used for locating the channels for a given instance */ freerdp* instance; /* signal for incoming data or event */ struct wait_obj* signal; /* used for sync write */ freerdp_mutex sync_data_mutex; LIST* sync_data_list; /* used for sync event */ freerdp_sem event_sem; RDP_EVENT* event; }; /** * The current channel manager reference passes from VirtualChannelEntry to * VirtualChannelInit for the pInitHandle. */ static rdpChannels* g_init_channels; /* The list of all channel managers. */ typedef struct rdp_channels_list rdpChannelsList; struct rdp_channels_list { rdpChannels* channels; rdpChannelsList* next; }; static rdpChannelsList* g_channels_list; /* To generate unique sequence for all open handles */ static int g_open_handle_sequence; /* For locking the global resources */ static freerdp_mutex g_mutex_init; static freerdp_mutex g_mutex_list; /* returns the channels for the open handle passed in */ static rdpChannels* freerdp_channels_find_by_open_handle(int open_handle, int* pindex) { int lindex; rdpChannels* channels; rdpChannelsList* channels_list; freerdp_mutex_lock(g_mutex_list); for (channels_list = g_channels_list; channels_list; channels_list = channels_list->next) { channels = channels_list->channels; for (lindex = 0; lindex < channels->num_channels_data; lindex++) { if (channels->channels_data[lindex].open_handle == open_handle) { freerdp_mutex_unlock(g_mutex_list); *pindex = lindex; return channels; } } } freerdp_mutex_unlock(g_mutex_list); return NULL; } /* returns the channels for the rdp instance passed in */ static rdpChannels* freerdp_channels_find_by_instance(freerdp* instance) { rdpChannels* channels; rdpChannelsList* channels_list; freerdp_mutex_lock(g_mutex_list); for (channels_list = g_channels_list; channels_list; channels_list = channels_list->next) { channels = channels_list->channels; if (channels->instance == instance) { freerdp_mutex_unlock(g_mutex_list); return channels; } } freerdp_mutex_unlock(g_mutex_list); return NULL; } /* returns struct channel_data for the channel name passed in */ static struct channel_data* freerdp_channels_find_channel_data_by_name(rdpChannels* channels, const char* channel_name, int* pindex) { int lindex; struct channel_data* lchannel_data; for (lindex = 0; lindex < channels->num_channels_data; lindex++) { lchannel_data = channels->channels_data + lindex; if (strcmp(channel_name, lchannel_data->name) == 0) { if (pindex != 0) *pindex = lindex; return lchannel_data; } } return NULL; } /* returns rdpChannel for the channel id passed in */ static rdpChannel* freerdp_channels_find_channel_by_id(rdpChannels* channels, rdpSettings* settings, int channel_id, int* pindex) { int lindex; int lcount; rdpChannel* lrdp_channel; lcount = settings->num_channels; for (lindex = 0; lindex < lcount; lindex++) { lrdp_channel = settings->channels + lindex; if (lrdp_channel->channel_id == channel_id) { if (pindex != 0) *pindex = lindex; return lrdp_channel; } } return NULL; } /* returns rdpChannel for the channel name passed in */ static rdpChannel* freerdp_channels_find_channel_by_name(rdpChannels* channels, rdpSettings* settings, const char* channel_name, int* pindex) { int lindex; int lcount; rdpChannel* lrdp_channel; lcount = settings->num_channels; for (lindex = 0; lindex < lcount; lindex++) { lrdp_channel = settings->channels + lindex; if (strcmp(channel_name, lrdp_channel->name) == 0) { if (pindex != 0) *pindex = lindex; return lrdp_channel; } } return NULL; } /** * must be called by same thread that calls freerdp_chanman_load_plugin * according to MS docs * only called from main thread */ static uint32 FREERDP_CC MyVirtualChannelInit(void** ppInitHandle, PCHANNEL_DEF pChannel, int channelCount, uint32 versionRequested, PCHANNEL_INIT_EVENT_FN pChannelInitEventProc) { int index; rdpChannels* channels; struct lib_data* llib; rdpChannel* lrdp_channel; PCHANNEL_DEF lchannel_def; struct channel_data* lchannel_data; channels = g_init_channels; channels->init_handles[channels->num_init_handles].channels = channels; *ppInitHandle = &channels->init_handles[channels->num_init_handles]; channels->num_init_handles++; DEBUG_CHANNELS("enter"); if (!channels->can_call_init) { DEBUG_CHANNELS("error not in entry"); return CHANNEL_RC_NOT_IN_VIRTUALCHANNELENTRY; } if (ppInitHandle == 0) { DEBUG_CHANNELS("error bad pphan"); return CHANNEL_RC_BAD_INIT_HANDLE; } if (channels->num_channels_data + channelCount >= CHANNEL_MAX_COUNT) { DEBUG_CHANNELS("error too many channels"); return CHANNEL_RC_TOO_MANY_CHANNELS; } if (pChannel == 0) { DEBUG_CHANNELS("error bad pchan"); return CHANNEL_RC_BAD_CHANNEL; } if (channels->is_connected) { DEBUG_CHANNELS("error already connected"); return CHANNEL_RC_ALREADY_CONNECTED; } if (versionRequested != VIRTUAL_CHANNEL_VERSION_WIN2000) { DEBUG_CHANNELS("warning version"); } for (index = 0; index < channelCount; index++) { lchannel_def = pChannel + index; if (freerdp_channels_find_channel_data_by_name(channels, lchannel_def->name, 0) != 0) { DEBUG_CHANNELS("error channel already used"); return CHANNEL_RC_BAD_CHANNEL; } } llib = channels->libs_data + channels->num_libs_data; llib->init_event_proc = pChannelInitEventProc; llib->init_handle = *ppInitHandle; channels->num_libs_data++; for (index = 0; index < channelCount; index++) { lchannel_def = pChannel + index; lchannel_data = channels->channels_data + channels->num_channels_data; freerdp_mutex_lock(g_mutex_list); lchannel_data->open_handle = g_open_handle_sequence++; freerdp_mutex_unlock(g_mutex_list); lchannel_data->flags = 1; /* init */ strncpy(lchannel_data->name, lchannel_def->name, CHANNEL_NAME_LEN); lchannel_data->options = lchannel_def->options; if (channels->settings->num_channels < 16) { lrdp_channel = channels->settings->channels + channels->settings->num_channels; strncpy(lrdp_channel->name, lchannel_def->name, 7); lrdp_channel->options = lchannel_def->options; channels->settings->num_channels++; } else { DEBUG_CHANNELS("warning more than 16 channels"); } channels->num_channels_data++; } return CHANNEL_RC_OK; } /** * can be called from any thread * thread safe because no 2 threads can have the same channel name registered */ static uint32 FREERDP_CC MyVirtualChannelOpen(void* pInitHandle, uint32* pOpenHandle, char* pChannelName, PCHANNEL_OPEN_EVENT_FN pChannelOpenEventProc) { int index; rdpChannels* channels; struct channel_data* lchannel_data; DEBUG_CHANNELS("enter"); channels = ((rdpInitHandle*) pInitHandle)->channels; if (pOpenHandle == 0) { DEBUG_CHANNELS("error bad chanhan"); return CHANNEL_RC_BAD_CHANNEL_HANDLE; } if (pChannelOpenEventProc == 0) { DEBUG_CHANNELS("error bad proc"); return CHANNEL_RC_BAD_PROC; } if (!channels->is_connected) { DEBUG_CHANNELS("error not connected"); return CHANNEL_RC_NOT_CONNECTED; } lchannel_data = freerdp_channels_find_channel_data_by_name(channels, pChannelName, &index); if (lchannel_data == 0) { DEBUG_CHANNELS("error chan name"); return CHANNEL_RC_UNKNOWN_CHANNEL_NAME; } if (lchannel_data->flags == 2) { DEBUG_CHANNELS("error chan already open"); return CHANNEL_RC_ALREADY_OPEN; } lchannel_data->flags = 2; /* open */ lchannel_data->open_event_proc = pChannelOpenEventProc; *pOpenHandle = lchannel_data->open_handle; return CHANNEL_RC_OK; } /** * can be called from any thread * thread safe because no 2 threads can have the same openHandle */ static uint32 FREERDP_CC MyVirtualChannelClose(uint32 openHandle) { int index; rdpChannels* channels; struct channel_data* lchannel_data; DEBUG_CHANNELS("enter"); channels = freerdp_channels_find_by_open_handle(openHandle, &index); if ((channels == NULL) || (index < 0) || (index >= CHANNEL_MAX_COUNT)) { DEBUG_CHANNELS("error bad channels"); return CHANNEL_RC_BAD_CHANNEL_HANDLE; } lchannel_data = channels->channels_data + index; if (lchannel_data->flags != 2) { DEBUG_CHANNELS("error not open"); return CHANNEL_RC_NOT_OPEN; } lchannel_data->flags = 0; return CHANNEL_RC_OK; } /* can be called from any thread */ static uint32 FREERDP_CC MyVirtualChannelWrite(uint32 openHandle, void* pData, uint32 dataLength, void* pUserData) { int index; rdpChannels* channels; struct sync_data* item; struct channel_data* lchannel_data; channels = freerdp_channels_find_by_open_handle(openHandle, &index); if ((channels == NULL) || (index < 0) || (index >= CHANNEL_MAX_COUNT)) { DEBUG_CHANNELS("error bad chanhan"); return CHANNEL_RC_BAD_CHANNEL_HANDLE; } if (!channels->is_connected) { DEBUG_CHANNELS("error not connected"); return CHANNEL_RC_NOT_CONNECTED; } if (pData == 0) { DEBUG_CHANNELS("error bad pData"); return CHANNEL_RC_NULL_DATA; } if (dataLength == 0) { DEBUG_CHANNELS("error bad dataLength"); return CHANNEL_RC_ZERO_LENGTH; } lchannel_data = channels->channels_data + index; if (lchannel_data->flags != 2) { DEBUG_CHANNELS("error not open"); return CHANNEL_RC_NOT_OPEN; } freerdp_mutex_lock(channels->sync_data_mutex); /* lock channels->sync* vars */ if (!channels->is_connected) { freerdp_mutex_unlock(channels->sync_data_mutex); DEBUG_CHANNELS("error not connected"); return CHANNEL_RC_NOT_CONNECTED; } item = xnew(struct sync_data); item->data = pData; item->data_length = dataLength; item->user_data = pUserData; item->index = index; list_enqueue(channels->sync_data_list, item); freerdp_mutex_unlock(channels->sync_data_mutex); /* set the event */ wait_obj_set(channels->signal); return CHANNEL_RC_OK; } static uint32 FREERDP_CC MyVirtualChannelEventPush(uint32 openHandle, RDP_EVENT* event) { int index; rdpChannels* channels; struct channel_data* lchannel_data; channels = freerdp_channels_find_by_open_handle(openHandle, &index); if ((channels == NULL) || (index < 0) || (index >= CHANNEL_MAX_COUNT)) { DEBUG_CHANNELS("error bad chanhan"); return CHANNEL_RC_BAD_CHANNEL_HANDLE; } if (!channels->is_connected) { DEBUG_CHANNELS("error not connected"); return CHANNEL_RC_NOT_CONNECTED; } if (event == NULL) { DEBUG_CHANNELS("error bad event"); return CHANNEL_RC_NULL_DATA; } lchannel_data = channels->channels_data + index; if (lchannel_data->flags != 2) { DEBUG_CHANNELS("error not open"); return CHANNEL_RC_NOT_OPEN; } freerdp_sem_wait(channels->event_sem); /* lock channels->event */ if (!channels->is_connected) { freerdp_sem_signal(channels->event_sem); DEBUG_CHANNELS("error not connected"); return CHANNEL_RC_NOT_CONNECTED; } channels->event = event; /* set the event */ wait_obj_set(channels->signal); return CHANNEL_RC_OK; } /** * this is called shortly after the application starts and * before any other function in the file * called only from main thread */ int freerdp_channels_global_init(void) { g_init_channels = NULL; g_channels_list = NULL; g_open_handle_sequence = 1; g_mutex_init = freerdp_mutex_new(); g_mutex_list = freerdp_mutex_new(); return 0; } int freerdp_channels_global_uninit(void) { while (g_channels_list) freerdp_channels_free(g_channels_list->channels); freerdp_mutex_free(g_mutex_init); freerdp_mutex_free(g_mutex_list); return 0; } rdpChannels* freerdp_channels_new(void) { rdpChannels* channels; rdpChannelsList* channels_list; channels = xnew(rdpChannels); channels->sync_data_mutex = freerdp_mutex_new(); channels->sync_data_list = list_new(); channels->event_sem = freerdp_sem_new(1); channels->signal = wait_obj_new(); /* Add it to the global list */ channels_list = xnew(rdpChannelsList); channels_list->channels = channels; freerdp_mutex_lock(g_mutex_list); channels_list->next = g_channels_list; g_channels_list = channels_list; freerdp_mutex_unlock(g_mutex_list); return channels; } void freerdp_channels_free(rdpChannels* channels) { rdpChannelsList* list; rdpChannelsList* prev; freerdp_mutex_free(channels->sync_data_mutex); list_free(channels->sync_data_list); freerdp_sem_free(channels->event_sem); wait_obj_free(channels->signal); /* Remove from global list */ freerdp_mutex_lock(g_mutex_list); for (prev = NULL, list = g_channels_list; list; prev = list, list = list->next) { if (list->channels == channels) break; } if (list) { if (prev) prev->next = list->next; else g_channels_list = list->next; xfree(list); } freerdp_mutex_unlock(g_mutex_list); xfree(channels); } /** * this is called when processing the command line parameters * called only from main thread */ int freerdp_channels_load_plugin(rdpChannels* channels, rdpSettings* settings, const char* name, void* data) { int ok; struct lib_data* lib; CHANNEL_ENTRY_POINTS_EX ep; DEBUG_CHANNELS("%s", name); if (channels->num_libs_data + 1 >= CHANNEL_MAX_COUNT) { DEBUG_CHANNELS("too many channels"); return 1; } lib = channels->libs_data + channels->num_libs_data; lib->entry = (PVIRTUALCHANNELENTRY) freerdp_load_plugin(name, CHANNEL_EXPORT_FUNC_NAME); //lib->entry = (PVIRTUALCHANNELENTRY) freerdp_load_channel_plugin(settings, name, CHANNEL_EXPORT_FUNC_NAME); if (lib->entry == NULL) { DEBUG_CHANNELS("failed to find export function"); return 1; } ep.cbSize = sizeof(ep); ep.protocolVersion = VIRTUAL_CHANNEL_VERSION_WIN2000; ep.pVirtualChannelInit = MyVirtualChannelInit; ep.pVirtualChannelOpen = MyVirtualChannelOpen; ep.pVirtualChannelClose = MyVirtualChannelClose; ep.pVirtualChannelWrite = MyVirtualChannelWrite; ep.pExtendedData = data; ep.pVirtualChannelEventPush = MyVirtualChannelEventPush; /* enable MyVirtualChannelInit */ channels->can_call_init = 1; channels->settings = settings; freerdp_mutex_lock(g_mutex_init); g_init_channels = channels; ok = lib->entry((PCHANNEL_ENTRY_POINTS) &ep); g_init_channels = NULL; freerdp_mutex_unlock(g_mutex_init); /* disable MyVirtualChannelInit */ channels->settings = 0; channels->can_call_init = 0; if (!ok) { DEBUG_CHANNELS("export function call failed"); return 1; } return 0; } /** * go through and inform all the libraries that we are initialized * called only from main thread */ int freerdp_channels_pre_connect(rdpChannels* channels, freerdp* instance) { int index; void* dummy; struct lib_data* llib; CHANNEL_DEF lchannel_def; DEBUG_CHANNELS("enter"); channels->instance = instance; /** * If rdpsnd is registered but not rdpdr, it's necessary to register a fake * rdpdr channel to make sound work. This is a workaround for Window 7 and * Windows 2008 */ if (freerdp_channels_find_channel_data_by_name(channels, "rdpsnd", 0) != 0 && freerdp_channels_find_channel_data_by_name(channels, "rdpdr", 0) == 0) { lchannel_def.options = CHANNEL_OPTION_INITIALIZED | CHANNEL_OPTION_ENCRYPT_RDP; strcpy(lchannel_def.name, "rdpdr"); channels->can_call_init = 1; channels->settings = instance->settings; freerdp_mutex_lock(g_mutex_init); g_init_channels = channels; MyVirtualChannelInit(&dummy, &lchannel_def, 1, VIRTUAL_CHANNEL_VERSION_WIN2000, 0); g_init_channels = NULL; freerdp_mutex_unlock(g_mutex_init); channels->can_call_init = 0; channels->settings = 0; DEBUG_CHANNELS("registered fake rdpdr for rdpsnd."); } for (index = 0; index < channels->num_libs_data; index++) { llib = channels->libs_data + index; if (llib->init_event_proc != 0) llib->init_event_proc(llib->init_handle, CHANNEL_EVENT_INITIALIZED, 0, 0); } return 0; } /** * go through and inform all the libraries that we are connected * this will tell the libraries that its ok to call MyVirtualChannelOpen * called only from main thread */ int freerdp_channels_post_connect(rdpChannels* channels, freerdp* instance) { int index; char* hostname; int hostname_len; struct lib_data* llib; channels->is_connected = 1; hostname = instance->settings->hostname; hostname_len = strlen(hostname); DEBUG_CHANNELS("hostname [%s] channels->num_libs [%d]", hostname, channels->num_libs_data); for (index = 0; index < channels->num_libs_data; index++) { llib = channels->libs_data + index; if (llib->init_event_proc != 0) llib->init_event_proc(llib->init_handle, CHANNEL_EVENT_CONNECTED, hostname, hostname_len); } return 0; } /** * data comming from the server to the client * called only from main thread */ int freerdp_channels_data(freerdp* instance, int channel_id, void* data, int data_size, int flags, int total_size) { int index; rdpChannels* channels; rdpChannel* lrdp_channel; struct channel_data* lchannel_data; channels = freerdp_channels_find_by_instance(instance); if (channels == 0) { DEBUG_CHANNELS("could not find channel manager"); return 1; } lrdp_channel = freerdp_channels_find_channel_by_id(channels, instance->settings, channel_id, &index); if (lrdp_channel == 0) { DEBUG_CHANNELS("could not find channel id"); return 1; } lchannel_data = freerdp_channels_find_channel_data_by_name(channels, lrdp_channel->name, &index); if (lchannel_data == 0) { DEBUG_CHANNELS("could not find channel name"); return 1; } if (lchannel_data->open_event_proc != 0) { lchannel_data->open_event_proc(lchannel_data->open_handle, CHANNEL_EVENT_DATA_RECEIVED, data, data_size, total_size, flags); } return 0; } static const char* event_class_to_name_table[] = { "rdpdbg", /* RDP_EVENT_CLASS_DEBUG */ "cliprdr", /* RDP_EVENT_CLASS_CLIPRDR */ "tsmf", /* RDP_EVENT_CLASS_TSMF */ "rail", /* RDP_EVENT_CLASS_RAIL */ NULL }; /** * Send a plugin-defined event to the plugin. * called only from main thread * @param channels the channel manager instance * @param event an event object created by freerdp_event_new() */ FREERDP_API int freerdp_channels_send_event(rdpChannels* channels, RDP_EVENT* event) { int index; const char* name; struct channel_data* lchannel_data; name = event_class_to_name_table[event->event_class]; if (name == NULL) { DEBUG_CHANNELS("unknown event_class %d", event->event_class); freerdp_event_free(event); return 1; } lchannel_data = freerdp_channels_find_channel_data_by_name(channels, name, &index); if (lchannel_data == NULL) { DEBUG_CHANNELS("could not find channel name %s", name); freerdp_event_free(event); return 1; } if (lchannel_data->open_event_proc != NULL) { lchannel_data->open_event_proc(lchannel_data->open_handle, CHANNEL_EVENT_USER, event, sizeof(RDP_EVENT), sizeof(RDP_EVENT), 0); } return 0; } /** * called only from main thread */ static void freerdp_channels_process_sync(rdpChannels* channels, freerdp* instance) { struct sync_data* item; rdpChannel* lrdp_channel; struct channel_data* lchannel_data; while (channels->sync_data_list->head != NULL) { freerdp_mutex_lock(channels->sync_data_mutex); item = (struct sync_data*)list_dequeue(channels->sync_data_list); freerdp_mutex_unlock(channels->sync_data_mutex); lchannel_data = channels->channels_data + item->index; lrdp_channel = freerdp_channels_find_channel_by_name(channels, instance->settings, lchannel_data->name, &item->index); if (lrdp_channel != NULL) instance->SendChannelData(instance, lrdp_channel->channel_id, item->data, item->data_length); if (lchannel_data->open_event_proc != 0) { lchannel_data->open_event_proc(lchannel_data->open_handle, CHANNEL_EVENT_WRITE_COMPLETE, item->user_data, sizeof(void *), sizeof(void *), 0); } xfree(item); } } /** * called only from main thread */ boolean freerdp_channels_get_fds(rdpChannels* channels, freerdp* instance, void** read_fds, int* read_count, void** write_fds, int* write_count) { wait_obj_get_fds(channels->signal, read_fds, read_count); return true; } /** * called only from main thread */ boolean freerdp_channels_check_fds(rdpChannels* channels, freerdp* instance) { if (wait_obj_is_set(channels->signal)) { wait_obj_clear(channels->signal); freerdp_channels_process_sync(channels, instance); } return true; } RDP_EVENT* freerdp_channels_pop_event(rdpChannels* channels) { RDP_EVENT* event; if (channels->event == NULL) return NULL; event = channels->event; channels->event = NULL; freerdp_sem_signal(channels->event_sem); /* release channels->event */ return event; } void freerdp_channels_close(rdpChannels* channels, freerdp* instance) { int index; struct lib_data* llib; DEBUG_CHANNELS("closing"); channels->is_connected = 0; freerdp_channels_check_fds(channels, instance); /* tell all libraries we are shutting down */ for (index = 0; index < channels->num_libs_data; index++) { llib = channels->libs_data + index; if (llib->init_event_proc != 0) llib->init_event_proc(llib->init_handle, CHANNEL_EVENT_TERMINATED, 0, 0); } } FreeRDP-1.0.2/libfreerdp-channels/libchannels.h000066400000000000000000000017501207112532300213020ustar00rootroot00000000000000/** * FreeRDP: A Remote Desktop Protocol client. * Virtual Channel Manager * * Copyright 2009-2011 Jay Sorg * Copyright 2010-2011 Vic Lee * * 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. */ #ifndef __LIBCHANNELS_H #define __LIBCHANNELS_H #include #ifdef WITH_DEBUG_CHANNELS #define DEBUG_CHANNELS(fmt, ...) DEBUG_CLASS(CHANNELS, fmt, ## __VA_ARGS__) #else #define DEBUG_CHANNELS(fmt, ...) DEBUG_NULL(fmt, ## __VA_ARGS__) #endif #endif /* __LIBCHANNELS_H */ FreeRDP-1.0.2/libfreerdp-channels/wtsvc.c000066400000000000000000000214761207112532300201700ustar00rootroot00000000000000/** * FreeRDP: A Remote Desktop Protocol client. * Server Virtual Channel Interface * * Copyright 2011-2012 Vic Lee * * 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. */ #include "config.h" #include #include #include #include #include #include "wtsvc.h" typedef struct wts_data_item { uint16 channel_id; uint8* buffer; uint32 length; } wts_data_item; static void wts_data_item_free(wts_data_item* item) { xfree(item->buffer); xfree(item); } static void WTSProcessChannelData(rdpPeerChannel* channel, int channelId, uint8* data, int size, int flags, int total_size) { wts_data_item* item; if (flags & CHANNEL_FLAG_FIRST) { stream_set_pos(channel->receive_data, 0); } stream_check_size(channel->receive_data, size); stream_write(channel->receive_data, data, size); if (flags & CHANNEL_FLAG_LAST) { if (stream_get_length(channel->receive_data) != total_size) { printf("WTSProcessChannelData: read error\n"); } if (channel->channel_type == RDP_PEER_CHANNEL_TYPE_DVC) { /* TODO: Receive DVC channel data */ } else { item = xnew(wts_data_item); item->length = stream_get_length(channel->receive_data); item->buffer = xmalloc(item->length); memcpy(item->buffer, stream_get_head(channel->receive_data), item->length); freerdp_mutex_lock(channel->mutex); list_enqueue(channel->receive_queue, item); freerdp_mutex_unlock(channel->mutex); wait_obj_set(channel->receive_event); } stream_set_pos(channel->receive_data, 0); } } static int WTSReceiveChannelData(freerdp_peer* client, int channelId, uint8* data, int size, int flags, int total_size) { int i; boolean result = false; rdpPeerChannel* channel; for (i = 0; i < client->settings->num_channels; i++) { if (client->settings->channels[i].channel_id == channelId) break; } if (i < client->settings->num_channels) { channel = (rdpPeerChannel*) client->settings->channels[i].handle; if (channel != NULL) { WTSProcessChannelData(channel, channelId, data, size, flags, total_size); result = true; } } return result; } WTSVirtualChannelManager* WTSCreateVirtualChannelManager(freerdp_peer* client) { WTSVirtualChannelManager* vcm; vcm = xnew(WTSVirtualChannelManager); if (vcm != NULL) { vcm->client = client; vcm->send_event = wait_obj_new(); vcm->send_queue = list_new(); vcm->mutex = freerdp_mutex_new(); client->ReceiveChannelData = WTSReceiveChannelData; } return vcm; } void WTSDestroyVirtualChannelManager(WTSVirtualChannelManager* vcm) { wts_data_item* item; if (vcm != NULL) { if (vcm->drdynvc_channel != NULL) { WTSVirtualChannelClose(vcm->drdynvc_channel); vcm->drdynvc_channel = NULL; } wait_obj_free(vcm->send_event); while ((item = (wts_data_item*) list_dequeue(vcm->send_queue)) != NULL) { wts_data_item_free(item); } list_free(vcm->send_queue); freerdp_mutex_free(vcm->mutex); xfree(vcm); } } void WTSVirtualChannelManagerGetFileDescriptor(WTSVirtualChannelManager* vcm, void** fds, int* fds_count) { wait_obj_get_fds(vcm->send_event, fds, fds_count); } boolean WTSVirtualChannelManagerCheckFileDescriptor(WTSVirtualChannelManager* vcm) { boolean result = true; wts_data_item* item; wait_obj_clear(vcm->send_event); freerdp_mutex_lock(vcm->mutex); while ((item = (wts_data_item*) list_dequeue(vcm->send_queue)) != NULL) { if (vcm->client->SendChannelData(vcm->client, item->channel_id, item->buffer, item->length) == false) { result = false; } wts_data_item_free(item); if (result == false) break; } freerdp_mutex_unlock(vcm->mutex); return result; } void* WTSVirtualChannelOpenEx( /* __in */ WTSVirtualChannelManager* vcm, /* __in */ const char* pVirtualName, /* __in */ uint32 flags) { int i; int len; rdpPeerChannel* channel; const char* channel_name; freerdp_peer* client = vcm->client; channel_name = ((flags & WTS_CHANNEL_OPTION_DYNAMIC) != 0 ? "drdynvc" : pVirtualName); len = strlen(channel_name); if (len > 8) return NULL; for (i = 0; i < client->settings->num_channels; i++) { if (client->settings->channels[i].joined && strncmp(client->settings->channels[i].name, channel_name, len) == 0) { break; } } if (i >= client->settings->num_channels) return NULL; channel = (rdpPeerChannel*) client->settings->channels[i].handle; if (channel == NULL) { channel = xnew(rdpPeerChannel); channel->vcm = vcm; channel->client = client; channel->channel_id = client->settings->channels[i].channel_id; channel->index = i; channel->receive_data = stream_new(client->settings->vc_chunk_size); if ((flags & WTS_CHANNEL_OPTION_DYNAMIC) != 0) { channel->channel_type = RDP_PEER_CHANNEL_TYPE_DVC; vcm->drdynvc_channel = channel; } else { channel->channel_type = RDP_PEER_CHANNEL_TYPE_SVC; channel->receive_event = wait_obj_new(); channel->receive_queue = list_new(); channel->mutex = freerdp_mutex_new(); } client->settings->channels[i].handle = channel; } if (channel->channel_type == RDP_PEER_CHANNEL_TYPE_DVC) { /* TODO: do DVC channel initialization here using pVirtualName */ /* A sub-channel should be created and returned, instead of using the main drdynvc channel */ /* Set channel->index to num_channels */ } return channel; } boolean WTSVirtualChannelQuery( /* __in */ void* hChannelHandle, /* __in */ WTS_VIRTUAL_CLASS WtsVirtualClass, /* __out */ void** ppBuffer, /* __out */ uint32* pBytesReturned) { void* fds[10]; int fds_count = 0; boolean result = false; rdpPeerChannel* channel = (rdpPeerChannel*) hChannelHandle; switch (WtsVirtualClass) { case WTSVirtualFileHandle: wait_obj_get_fds(channel->receive_event, fds, &fds_count); *ppBuffer = xmalloc(sizeof(void*)); memcpy(*ppBuffer, &fds[0], sizeof(void*)); *pBytesReturned = sizeof(void*); result = true; break; default: break; } return result; } void WTSFreeMemory( /* __in */ void* pMemory) { xfree(pMemory); } boolean WTSVirtualChannelRead( /* __in */ void* hChannelHandle, /* __in */ uint32 TimeOut, /* __out */ uint8* Buffer, /* __in */ uint32 BufferSize, /* __out */ uint32* pBytesRead) { wts_data_item* item; rdpPeerChannel* channel = (rdpPeerChannel*) hChannelHandle; item = (wts_data_item*) list_peek(channel->receive_queue); if (item == NULL) { wait_obj_clear(channel->receive_event); *pBytesRead = 0; return true; } *pBytesRead = item->length; if (item->length > BufferSize) return false; /* remove the first element (same as what we just peek) */ freerdp_mutex_lock(channel->mutex); list_dequeue(channel->receive_queue); if (channel->receive_queue->head == NULL) wait_obj_clear(channel->receive_event); freerdp_mutex_unlock(channel->mutex); memcpy(Buffer, item->buffer, item->length); return true; } boolean WTSVirtualChannelWrite( /* __in */ void* hChannelHandle, /* __in */ uint8* Buffer, /* __in */ uint32 Length, /* __out */ uint32* pBytesWritten) { uint32 written = 0; wts_data_item* item; boolean result = false; rdpPeerChannel* channel = (rdpPeerChannel*) hChannelHandle; WTSVirtualChannelManager* vcm = channel->vcm; if (channel == NULL) return false; if (channel->channel_type == RDP_PEER_CHANNEL_TYPE_SVC) { item = xnew(wts_data_item); item->channel_id = channel->channel_id; item->buffer = xmalloc(Length); item->length = Length; memcpy(item->buffer, Buffer, Length); freerdp_mutex_lock(vcm->mutex); list_enqueue(vcm->send_queue, item); freerdp_mutex_unlock(vcm->mutex); wait_obj_set(vcm->send_event); written = Length; result = true; } else { /* TODO: Send to DVC channel */ } if (pBytesWritten != NULL) *pBytesWritten = written; return result; } boolean WTSVirtualChannelClose( /* __in */ void* hChannelHandle) { wts_data_item* item; rdpPeerChannel* channel = (rdpPeerChannel*) hChannelHandle; if (channel != NULL) { if (channel->index < channel->client->settings->num_channels) channel->client->settings->channels[channel->index].handle = NULL; stream_free(channel->receive_data); if (channel->receive_event) wait_obj_free(channel->receive_event); if (channel->receive_queue) { while ((item = (wts_data_item*) list_dequeue(channel->receive_queue)) != NULL) { wts_data_item_free(item); } list_free(channel->receive_queue); } if (channel->mutex) freerdp_mutex_free(channel->mutex); xfree(channel); } return true; } FreeRDP-1.0.2/libfreerdp-channels/wtsvc.h000066400000000000000000000027171207112532300201720ustar00rootroot00000000000000/** * FreeRDP: A Remote Desktop Protocol client. * Server Virtual Channel Interface * * Copyright 2011-2012 Vic Lee * * 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. */ #ifndef __WTSVC_H #define __WTSVC_H #include #include #include #include #include #include enum { RDP_PEER_CHANNEL_TYPE_SVC = 0, RDP_PEER_CHANNEL_TYPE_DVC = 1, RDP_PEER_CHANNEL_TYPE_DVC_SUB = 2 }; typedef struct rdp_peer_channel { WTSVirtualChannelManager* vcm; freerdp_peer* client; uint16 channel_id; uint16 channel_type; uint16 index; STREAM* receive_data; struct wait_obj* receive_event; LIST* receive_queue; freerdp_mutex mutex; } rdpPeerChannel; struct WTSVirtualChannelManager { freerdp_peer* client; struct wait_obj* send_event; LIST* send_queue; freerdp_mutex mutex; rdpPeerChannel* drdynvc_channel; }; #endif /* __WTSVC_H */ FreeRDP-1.0.2/libfreerdp-codec/000077500000000000000000000000001207112532300161265ustar00rootroot00000000000000FreeRDP-1.0.2/libfreerdp-codec/CMakeLists.txt000066400000000000000000000033221207112532300206660ustar00rootroot00000000000000# FreeRDP: A Remote Desktop Protocol Client # libfreerdp-codec cmake build script # # Copyright 2011 O.S. Systems Software Ltda. # Copyright 2011 Otavio Salvador # Copyright 2011 Marc-Andre Moreau # # 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(FREERDP_CODEC_SRCS bitmap.c color.c rfx_bitstream.h rfx_constants.h rfx_decode.c rfx_decode.h rfx_differential.c rfx_differential.h rfx_dwt.c rfx_dwt.h rfx_encode.c rfx_encode.h rfx_pool.c rfx_pool.h rfx_quantization.c rfx_quantization.h rfx_rlgr.c rfx_rlgr.h rfx_types.h rfx.c nsc.c ) if(WITH_SSE2) set(FREERDP_CODEC_SRCS ${FREERDP_CODEC_SRCS} rfx_sse2.c rfx_sse2.h ) set_property(SOURCE rfx_sse2.c PROPERTY COMPILE_FLAGS "-msse2") endif() if(WITH_NEON) set(FREERDP_CODEC_SRCS ${FREERDP_CODEC_SRCS} rfx_neon.c rfx_neon.h ) set_property(SOURCE rfx_neon.c PROPERTY COMPILE_FLAGS "-mfpu=neon -mfloat-abi=softfp") endif() add_library(freerdp-codec ${FREERDP_CODEC_SRCS}) set_target_properties(freerdp-codec PROPERTIES VERSION ${FREERDP_VERSION_FULL} SOVERSION ${FREERDP_VERSION} PREFIX "lib") target_link_libraries(freerdp-codec freerdp-utils) install(TARGETS freerdp-codec DESTINATION ${CMAKE_INSTALL_LIBDIR}) FreeRDP-1.0.2/libfreerdp-codec/bitmap.c000066400000000000000000000277401207112532300175600ustar00rootroot00000000000000/** * FreeRDP: A Remote Desktop Protocol Client * Compressed Bitmap * * Copyright 2011 Jay Sorg * * 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. */ #include #include #include #include /* RLE Compressed Bitmap Stream (RLE_BITMAP_STREAM) http://msdn.microsoft.com/en-us/library/cc240895%28v=prot.10%29.aspx pseudo-code http://msdn.microsoft.com/en-us/library/dd240593%28v=prot.10%29.aspx */ #define REGULAR_BG_RUN 0x00 #define MEGA_MEGA_BG_RUN 0xF0 #define REGULAR_FG_RUN 0x01 #define MEGA_MEGA_FG_RUN 0xF1 #define LITE_SET_FG_FG_RUN 0x0C #define MEGA_MEGA_SET_FG_RUN 0xF6 #define LITE_DITHERED_RUN 0x0E #define MEGA_MEGA_DITHERED_RUN 0xF8 #define REGULAR_COLOR_RUN 0x03 #define MEGA_MEGA_COLOR_RUN 0xF3 #define REGULAR_FGBG_IMAGE 0x02 #define MEGA_MEGA_FGBG_IMAGE 0xF2 #define LITE_SET_FG_FGBG_IMAGE 0x0D #define MEGA_MEGA_SET_FGBG_IMAGE 0xF7 #define REGULAR_COLOR_IMAGE 0x04 #define MEGA_MEGA_COLOR_IMAGE 0xF4 #define SPECIAL_FGBG_1 0xF9 #define SPECIAL_FGBG_2 0xFA #define SPECIAL_WHITE 0xFD #define SPECIAL_BLACK 0xFE #define BLACK_PIXEL 0x000000 #define WHITE_PIXEL 0xFFFFFF typedef uint32 PIXEL; static const uint8 g_MaskBit0 = 0x01; /* Least significant bit */ static const uint8 g_MaskBit1 = 0x02; static const uint8 g_MaskBit2 = 0x04; static const uint8 g_MaskBit3 = 0x08; static const uint8 g_MaskBit4 = 0x10; static const uint8 g_MaskBit5 = 0x20; static const uint8 g_MaskBit6 = 0x40; static const uint8 g_MaskBit7 = 0x80; /* Most significant bit */ static const uint8 g_MaskSpecialFgBg1 = 0x03; static const uint8 g_MaskSpecialFgBg2 = 0x05; static const uint8 g_MaskRegularRunLength = 0x1F; static const uint8 g_MaskLiteRunLength = 0x0F; /** * Reads the supplied order header and extracts the compression * order code ID. */ static uint32 ExtractCodeId(uint8 bOrderHdr) { int code; switch (bOrderHdr) { case MEGA_MEGA_BG_RUN: case MEGA_MEGA_FG_RUN: case MEGA_MEGA_SET_FG_RUN: case MEGA_MEGA_DITHERED_RUN: case MEGA_MEGA_COLOR_RUN: case MEGA_MEGA_FGBG_IMAGE: case MEGA_MEGA_SET_FGBG_IMAGE: case MEGA_MEGA_COLOR_IMAGE: case SPECIAL_FGBG_1: case SPECIAL_FGBG_2: case SPECIAL_WHITE: case SPECIAL_BLACK: return bOrderHdr; } code = bOrderHdr >> 5; switch (code) { case REGULAR_BG_RUN: case REGULAR_FG_RUN: case REGULAR_COLOR_RUN: case REGULAR_FGBG_IMAGE: case REGULAR_COLOR_IMAGE: return code; } return bOrderHdr >> 4; } /** * Extract the run length of a compression order. */ static uint32 ExtractRunLength(uint32 code, uint8* pbOrderHdr, uint32* advance) { uint32 runLength; uint32 ladvance; ladvance = 1; runLength = 0; switch (code) { case REGULAR_FGBG_IMAGE: runLength = (*pbOrderHdr) & g_MaskRegularRunLength; if (runLength == 0) { runLength = (*(pbOrderHdr + 1)) + 1; ladvance += 1; } else { runLength = runLength * 8; } break; case LITE_SET_FG_FGBG_IMAGE: runLength = (*pbOrderHdr) & g_MaskLiteRunLength; if (runLength == 0) { runLength = (*(pbOrderHdr + 1)) + 1; ladvance += 1; } else { runLength = runLength * 8; } break; case REGULAR_BG_RUN: case REGULAR_FG_RUN: case REGULAR_COLOR_RUN: case REGULAR_COLOR_IMAGE: runLength = (*pbOrderHdr) & g_MaskRegularRunLength; if (runLength == 0) { /* An extended (MEGA) run. */ runLength = (*(pbOrderHdr + 1)) + 32; ladvance += 1; } break; case LITE_SET_FG_FG_RUN: case LITE_DITHERED_RUN: runLength = (*pbOrderHdr) & g_MaskLiteRunLength; if (runLength == 0) { /* An extended (MEGA) run. */ runLength = (*(pbOrderHdr + 1)) + 16; ladvance += 1; } break; case MEGA_MEGA_BG_RUN: case MEGA_MEGA_FG_RUN: case MEGA_MEGA_SET_FG_RUN: case MEGA_MEGA_DITHERED_RUN: case MEGA_MEGA_COLOR_RUN: case MEGA_MEGA_FGBG_IMAGE: case MEGA_MEGA_SET_FGBG_IMAGE: case MEGA_MEGA_COLOR_IMAGE: runLength = ((uint16) pbOrderHdr[1]) | ((uint16) (pbOrderHdr[2] << 8)); ladvance += 2; break; } *advance = ladvance; return runLength; } #define UNROLL_COUNT 4 #define UNROLL(_exp) do { _exp _exp _exp _exp } while (0) #undef DESTWRITEPIXEL #undef DESTREADPIXEL #undef SRCREADPIXEL #undef DESTNEXTPIXEL #undef SRCNEXTPIXEL #undef WRITEFGBGIMAGE #undef WRITEFIRSTLINEFGBGIMAGE #undef RLEDECOMPRESS #undef RLEEXTRA #define DESTWRITEPIXEL(_buf, _pix) (_buf)[0] = (uint8)(_pix) #define DESTREADPIXEL(_pix, _buf) _pix = (_buf)[0] #define SRCREADPIXEL(_pix, _buf) _pix = (_buf)[0] #define DESTNEXTPIXEL(_buf) _buf += 1 #define SRCNEXTPIXEL(_buf) _buf += 1 #define WRITEFGBGIMAGE WriteFgBgImage8to8 #define WRITEFIRSTLINEFGBGIMAGE WriteFirstLineFgBgImage8to8 #define RLEDECOMPRESS RleDecompress8to8 #define RLEEXTRA #include "include/bitmap.c" #undef DESTWRITEPIXEL #undef DESTREADPIXEL #undef SRCREADPIXEL #undef DESTNEXTPIXEL #undef SRCNEXTPIXEL #undef WRITEFGBGIMAGE #undef WRITEFIRSTLINEFGBGIMAGE #undef RLEDECOMPRESS #undef RLEEXTRA #define DESTWRITEPIXEL(_buf, _pix) ((uint16*)(_buf))[0] = (uint16)(_pix) #define DESTREADPIXEL(_pix, _buf) _pix = ((uint16*)(_buf))[0] #define SRCREADPIXEL(_pix, _buf) _pix = ((uint16*)(_buf))[0] #define DESTNEXTPIXEL(_buf) _buf += 2 #define SRCNEXTPIXEL(_buf) _buf += 2 #define WRITEFGBGIMAGE WriteFgBgImage16to16 #define WRITEFIRSTLINEFGBGIMAGE WriteFirstLineFgBgImage16to16 #define RLEDECOMPRESS RleDecompress16to16 #define RLEEXTRA #include "include/bitmap.c" #undef DESTWRITEPIXEL #undef DESTREADPIXEL #undef SRCREADPIXEL #undef DESTNEXTPIXEL #undef SRCNEXTPIXEL #undef WRITEFGBGIMAGE #undef WRITEFIRSTLINEFGBGIMAGE #undef RLEDECOMPRESS #undef RLEEXTRA #define DESTWRITEPIXEL(_buf, _pix) do { (_buf)[0] = (uint8)(_pix); \ (_buf)[1] = (uint8)((_pix) >> 8); (_buf)[2] = (uint8)((_pix) >> 16); } while (0) #define DESTREADPIXEL(_pix, _buf) _pix = (_buf)[0] | ((_buf)[1] << 8) | \ ((_buf)[2] << 16) #define SRCREADPIXEL(_pix, _buf) _pix = (_buf)[0] | ((_buf)[1] << 8) | \ ((_buf)[2] << 16) #define DESTNEXTPIXEL(_buf) _buf += 3 #define SRCNEXTPIXEL(_buf) _buf += 3 #define WRITEFGBGIMAGE WriteFgBgImage24to24 #define WRITEFIRSTLINEFGBGIMAGE WriteFirstLineFgBgImage24to24 #define RLEDECOMPRESS RleDecompress24to24 #define RLEEXTRA #include "include/bitmap.c" #define IN_UINT8_MV(_p) (*((_p)++)) /** * decompress an RLE color plane * RDP6_BITMAP_STREAM */ static int process_rle_plane(uint8* in, int width, int height, uint8* out, int size) { int indexw; int indexh; int code; int collen; int replen; int color; int x; int revcode; uint8* last_line; uint8* this_line; uint8* org_in; uint8* org_out; org_in = in; org_out = out; last_line = 0; indexh = 0; while (indexh < height) { out = (org_out + width * height * 4) - ((indexh + 1) * width * 4); color = 0; this_line = out; indexw = 0; if (last_line == 0) { while (indexw < width) { code = IN_UINT8_MV(in); replen = code & 0xf; collen = (code >> 4) & 0xf; revcode = (replen << 4) | collen; if ((revcode <= 47) && (revcode >= 16)) { replen = revcode; collen = 0; } while (collen > 0) { color = IN_UINT8_MV(in); *out = color; out += 4; indexw++; collen--; } while (replen > 0) { *out = color; out += 4; indexw++; replen--; } } } else { while (indexw < width) { code = IN_UINT8_MV(in); replen = code & 0xf; collen = (code >> 4) & 0xf; revcode = (replen << 4) | collen; if ((revcode <= 47) && (revcode >= 16)) { replen = revcode; collen = 0; } while (collen > 0) { x = IN_UINT8_MV(in); if (x & 1) { x = x >> 1; x = x + 1; color = -x; } else { x = x >> 1; color = x; } x = last_line[indexw * 4] + color; *out = x; out += 4; indexw++; collen--; } while (replen > 0) { x = last_line[indexw * 4] + color; *out = x; out += 4; indexw++; replen--; } } } indexh++; last_line = this_line; } return (int) (in - org_in); } /** * process a raw color plane */ static int process_raw_plane(uint8* srcData, int width, int height, uint8* dstData, int size) { int x, y; for (y = 0; y < height; y++) { for (x = 0; x < width; x++) { dstData[(((height - y - 1) * width) + x) * 4] = srcData[((y * width) + x)]; } } return (width * height); } /** * 4 byte bitmap decompress * RDP6_BITMAP_STREAM */ static boolean bitmap_decompress4(uint8* srcData, uint8* dstData, int width, int height, int size) { int RLE; int code; int NoAlpha; int bytes_processed; int total_processed; code = IN_UINT8_MV(srcData); RLE = code & 0x10; total_processed = 1; NoAlpha = code & 0x20; if (NoAlpha == 0) { bytes_processed = process_rle_plane(srcData, width, height, dstData + 3, size - total_processed); total_processed += bytes_processed; srcData += bytes_processed; } if (RLE != 0) { bytes_processed = process_rle_plane(srcData, width, height, dstData + 2, size - total_processed); total_processed += bytes_processed; srcData += bytes_processed; bytes_processed = process_rle_plane(srcData, width, height, dstData + 1, size - total_processed); total_processed += bytes_processed; srcData += bytes_processed; bytes_processed = process_rle_plane(srcData, width, height, dstData + 0, size - total_processed); total_processed += bytes_processed; } else { bytes_processed = process_raw_plane(srcData, width, height, dstData + 2, size - total_processed); total_processed += bytes_processed; srcData += bytes_processed; bytes_processed = process_raw_plane(srcData, width, height, dstData + 1, size - total_processed); total_processed += bytes_processed; srcData += bytes_processed; bytes_processed = process_raw_plane(srcData, width, height, dstData + 0, size - total_processed); total_processed += bytes_processed + 1; } return (size == total_processed) ? true : false; } /** * bitmap decompression routine */ boolean bitmap_decompress(uint8* srcData, uint8* dstData, int width, int height, int size, int srcBpp, int dstBpp) { uint8 * TmpBfr; if (srcBpp == 16 && dstBpp == 16) { TmpBfr = (uint8*) xmalloc(width * height * 2); RleDecompress16to16(srcData, size, TmpBfr, width * 2, width, height); freerdp_bitmap_flip(TmpBfr, dstData, width * 2, height); xfree(TmpBfr); } else if (srcBpp == 32 && dstBpp == 32) { if (!bitmap_decompress4(srcData, dstData, width, height, size)) return false; } else if (srcBpp == 15 && dstBpp == 15) { TmpBfr = (uint8*) xmalloc(width * height * 2); RleDecompress16to16(srcData, size, TmpBfr, width * 2, width, height); freerdp_bitmap_flip(TmpBfr, dstData, width * 2, height); xfree(TmpBfr); } else if (srcBpp == 8 && dstBpp == 8) { TmpBfr = (uint8*) xmalloc(width * height); RleDecompress8to8(srcData, size, TmpBfr, width, width, height); freerdp_bitmap_flip(TmpBfr, dstData, width, height); xfree(TmpBfr); } else if (srcBpp == 24 && dstBpp == 24) { TmpBfr = (uint8*) xmalloc(width * height * 3); RleDecompress24to24(srcData, size, TmpBfr, width * 3, width, height); freerdp_bitmap_flip(TmpBfr, dstData, width * 3, height); xfree(TmpBfr); } else { return false; } return true; } FreeRDP-1.0.2/libfreerdp-codec/color.c000066400000000000000000000542301207112532300174140ustar00rootroot00000000000000/** * FreeRDP: A Remote Desktop Protocol Client * Color Conversion Routines * * Copyright 2010 Marc-Andre Moreau * * 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. */ #include #include #include #include #include #include #include int freerdp_get_pixel(uint8 * data, int x, int y, int width, int height, int bpp) { int start; int shift; uint16 *src16; uint32 *src32; int red, green, blue; switch (bpp) { case 1: width = (width + 7) / 8; start = (y * width) + x / 8; shift = x % 8; return (data[start] & (0x80 >> shift)) != 0; case 8: return data[y * width + x]; case 15: case 16: src16 = (uint16*) data; return src16[y * width + x]; case 24: data += y * width * 3; data += x * 3; red = data[0]; green = data[1]; blue = data[2]; return RGB24(red, green, blue); case 32: src32 = (uint32*) data; return src32[y * width + x]; default: break; } return 0; } void freerdp_set_pixel(uint8* data, int x, int y, int width, int height, int bpp, int pixel) { int start; int shift; int *dst32; if (bpp == 1) { width = (width + 7) / 8; start = (y * width) + x / 8; shift = x % 8; if (pixel) data[start] = data[start] | (0x80 >> shift); else data[start] = data[start] & ~(0x80 >> shift); } else if (bpp == 32) { dst32 = (int*) data; dst32[y * width + x] = pixel; } } INLINE void freerdp_color_split_rgb(uint32* color, int bpp, uint8* red, uint8* green, uint8* blue, uint8* alpha, HCLRCONV clrconv) { *red = *green = *blue = 0; *alpha = (clrconv->alpha) ? 0xFF : 0x00; switch (bpp) { case 32: if (clrconv->alpha) { GetARGB32(*alpha, *red, *green, *blue, *color); } else { GetRGB32(*red, *green, *blue, *color); } break; case 24: GetRGB24(*red, *green, *blue, *color); break; case 16: GetRGB16(*red, *green, *blue, *color); break; case 15: GetRGB15(*red, *green, *blue, *color); break; case 8: *color &= 0xFF; *red = clrconv->palette->entries[*color].red; *green = clrconv->palette->entries[*color].green; *blue = clrconv->palette->entries[*color].blue; break; case 1: if (*color != 0) { *red = 0xFF; *green = 0xFF; *blue = 0xFF; } break; default: break; } } INLINE void freerdp_color_split_bgr(uint32* color, int bpp, uint8* red, uint8* green, uint8* blue, uint8* alpha, HCLRCONV clrconv) { *red = *green = *blue = 0; *alpha = (clrconv->alpha) ? 0xFF : 0x00; switch (bpp) { case 32: if (clrconv->alpha) { GetABGR32(*alpha, *red, *green, *blue, *color); } else { GetBGR32(*red, *green, *blue, *color); } break; case 24: GetBGR24(*red, *green, *blue, *color); break; case 16: GetBGR16(*red, *green, *blue, *color); break; case 15: GetBGR15(*red, *green, *blue, *color); break; case 8: *color &= 0xFF; *red = clrconv->palette->entries[*color].red; *green = clrconv->palette->entries[*color].green; *blue = clrconv->palette->entries[*color].blue; break; case 1: if (*color != 0) { *red = 0xFF; *green = 0xFF; *blue = 0xFF; } break; default: break; } } INLINE void freerdp_color_make_rgb(uint32* color, int bpp, uint8* red, uint8* green, uint8* blue, uint8* alpha, HCLRCONV clrconv) { switch (bpp) { case 32: *color = ARGB32(*alpha, *red, *green, *blue); break; case 24: *color = RGB24(*red, *green, *blue); break; case 16: if (clrconv->rgb555) { *color = RGB15(*red, *green, *blue); } else { *color = RGB16(*red, *green, *blue); } break; case 15: *color = RGB15(*red, *green, *blue); break; case 8: *color = RGB24(*red, *green, *blue); break; case 1: if ((*red != 0) || (*green != 0) || (*blue != 0)) *color = 1; break; default: break; } } INLINE void freerdp_color_make_bgr(uint32* color, int bpp, uint8* red, uint8* green, uint8* blue, uint8* alpha, HCLRCONV clrconv) { switch (bpp) { case 32: *color = ABGR32(*alpha, *red, *green, *blue); break; case 24: *color = BGR24(*red, *green, *blue); break; case 16: if (clrconv->rgb555) { *color = BGR15(*red, *green, *blue); } else { *color = BGR16(*red, *green, *blue); } break; case 15: *color = BGR15(*red, *green, *blue); break; case 8: *color = BGR24(*red, *green, *blue); break; case 1: if ((*red != 0) || (*green != 0) || (*blue != 0)) *color = 1; break; default: break; } } uint32 freerdp_color_convert_rgb(uint32 srcColor, int srcBpp, int dstBpp, HCLRCONV clrconv) { uint8 red = 0; uint8 green = 0; uint8 blue = 0; uint8 alpha = 0xFF; uint32 dstColor = 0; freerdp_color_split_rgb(&srcColor, srcBpp, &red, &green, &blue, &alpha, clrconv); freerdp_color_make_rgb(&dstColor, dstBpp, &red, &green, &blue, &alpha, clrconv); return dstColor; } uint32 freerdp_color_convert_bgr(uint32 srcColor, int srcBpp, int dstBpp, HCLRCONV clrconv) { uint8 red = 0; uint8 green = 0; uint8 blue = 0; uint8 alpha = 0xFF; uint32 dstColor = 0; freerdp_color_split_bgr(&srcColor, srcBpp, &red, &green, &blue, &alpha, clrconv); freerdp_color_make_bgr(&dstColor, dstBpp, &red, &green, &blue, &alpha, clrconv); return dstColor; } uint32 freerdp_color_convert_rgb_bgr(uint32 srcColor, int srcBpp, int dstBpp, HCLRCONV clrconv) { uint8 red = 0; uint8 green = 0; uint8 blue = 0; uint8 alpha = 0xFF; uint32 dstColor = 0; freerdp_color_split_rgb(&srcColor, srcBpp, &red, &green, &blue, &alpha, clrconv); freerdp_color_make_bgr(&dstColor, dstBpp, &red, &green, &blue, &alpha, clrconv); return dstColor; } uint32 freerdp_color_convert_bgr_rgb(uint32 srcColor, int srcBpp, int dstBpp, HCLRCONV clrconv) { uint8 red = 0; uint8 green = 0; uint8 blue = 0; uint8 alpha = 0xFF; uint32 dstColor = 0; freerdp_color_split_bgr(&srcColor, srcBpp, &red, &green, &blue, &alpha, clrconv); freerdp_color_make_rgb(&dstColor, dstBpp, &red, &green, &blue, &alpha, clrconv); return dstColor; } uint32 freerdp_color_convert_var(uint32 srcColor, int srcBpp, int dstBpp, HCLRCONV clrconv) { if (clrconv->invert) return freerdp_color_convert_var_bgr(srcColor, srcBpp, dstBpp, clrconv); else return freerdp_color_convert_var_rgb(srcColor, srcBpp, dstBpp, clrconv); } uint32 freerdp_color_convert_var_rgb(uint32 srcColor, int srcBpp, int dstBpp, HCLRCONV clrconv) { if (srcBpp > 16) return freerdp_color_convert_bgr_rgb(srcColor, srcBpp, dstBpp, clrconv); else return freerdp_color_convert_rgb(srcColor, srcBpp, dstBpp, clrconv); } uint32 freerdp_color_convert_var_bgr(uint32 srcColor, int srcBpp, int dstBpp, HCLRCONV clrconv) { if (srcBpp > 16) return freerdp_color_convert_bgr(srcColor, srcBpp, dstBpp, clrconv); else return freerdp_color_convert_rgb_bgr(srcColor, srcBpp, dstBpp, clrconv); } uint8* freerdp_image_convert_8bpp(uint8* srcData, uint8* dstData, int width, int height, int srcBpp, int dstBpp, HCLRCONV clrconv) { int i; uint8 red; uint8 green; uint8 blue; uint32 pixel; uint8 *src8; uint16 *dst16; uint32 *dst32; if (dstBpp == 8) { if (dstData == NULL) dstData = (uint8*) malloc(width * height); memcpy(dstData, srcData, width * height); return dstData; } else if (dstBpp == 15 || (dstBpp == 16 && clrconv->rgb555)) { if (dstData == NULL) dstData = (uint8*) malloc(width * height * 2); dst16 = (uint16 *) dstData; for (i = width * height; i > 0; i--) { pixel = *srcData; srcData++; red = clrconv->palette->entries[pixel].red; green = clrconv->palette->entries[pixel].green; blue = clrconv->palette->entries[pixel].blue; pixel = (clrconv->invert) ? BGR15(red, green, blue) : RGB15(red, green, blue); *dst16 = pixel; dst16++; } return dstData; } else if (dstBpp == 16) { if (dstData == NULL) dstData = (uint8*) malloc(width * height * 2); dst16 = (uint16 *) dstData; for (i = width * height; i > 0; i--) { pixel = *srcData; srcData++; red = clrconv->palette->entries[pixel].red; green = clrconv->palette->entries[pixel].green; blue = clrconv->palette->entries[pixel].blue; pixel = (clrconv->invert) ? BGR16(red, green, blue) : RGB16(red, green, blue); *dst16 = pixel; dst16++; } return dstData; } else if (dstBpp == 32) { if (dstData == NULL) dstData = (uint8*) malloc(width * height * 4); src8 = (uint8*) srcData; dst32 = (uint32*) dstData; for (i = width * height; i > 0; i--) { pixel = *src8; src8++; red = clrconv->palette->entries[pixel].red; green = clrconv->palette->entries[pixel].green; blue = clrconv->palette->entries[pixel].blue; pixel = (clrconv->invert) ? RGB32(red, green, blue) : BGR32(red, green, blue); *dst32 = pixel; dst32++; } return dstData; } return srcData; } uint8* freerdp_image_convert_15bpp(uint8* srcData, uint8* dstData, int width, int height, int srcBpp, int dstBpp, HCLRCONV clrconv) { int i; uint8 red; uint8 green; uint8 blue; uint32 pixel; uint16 *src16; uint16 *dst16; uint32 *dst32; if (dstBpp == 15 || (dstBpp == 16 && clrconv->rgb555)) { if (dstData == NULL) dstData = (uint8*) malloc(width * height * 2); memcpy(dstData, srcData, width * height * 2); return dstData; } else if (dstBpp == 32) { if (dstData == NULL) dstData = (uint8*) malloc(width * height * 4); src16 = (uint16 *) srcData; dst32 = (uint32 *) dstData; for (i = width * height; i > 0; i--) { pixel = *src16; src16++; GetBGR15(red, green, blue, pixel); pixel = (clrconv->invert) ? RGB32(red, green, blue) : BGR32(red, green, blue); *dst32 = pixel; dst32++; } return dstData; } else if (dstBpp == 16) { if (dstData == NULL) dstData = (uint8*) malloc(width * height * 2); src16 = (uint16 *) srcData; dst16 = (uint16 *) dstData; for (i = width * height; i > 0; i--) { pixel = *src16; src16++; GetRGB_555(red, green, blue, pixel); RGB_555_565(red, green, blue); pixel = (clrconv->invert) ? BGR565(red, green, blue) : RGB565(red, green, blue); *dst16 = pixel; dst16++; } return dstData; } return srcData; } uint8* freerdp_image_convert_16bpp(uint8* srcData, uint8* dstData, int width, int height, int srcBpp, int dstBpp, HCLRCONV clrconv) { if (srcBpp == 15) return freerdp_image_convert_15bpp(srcData, dstData, width, height, srcBpp, dstBpp, clrconv); if (dstBpp == 16) { if (dstData == NULL) dstData = (uint8*) malloc(width * height * 2); if (clrconv->rgb555) { int i; uint8 red, green, blue; uint16* src16 = (uint16 *) srcData; uint16* dst16 = (uint16 *) dstData; for (i = width * height; i > 0; i--) { GetRGB_565(red, green, blue, (*src16)); RGB_565_555(red, green, blue); (*dst16) = (clrconv->invert) ? BGR555(red, green, blue) : RGB555(red, green, blue); src16++; dst16++; } } else { memcpy(dstData, srcData, width * height * 2); } return dstData; } else if (dstBpp == 24) { int i; uint8 *dst8; uint16 *src16; uint8 red, green, blue; if (dstData == NULL) dstData = (uint8*) malloc(width * height * 3); dst8 = (uint8*) dstData; src16 = (uint16*) srcData; for (i = width * height; i > 0; i--) { GetBGR16(red, green, blue, *src16); src16++; if (clrconv->invert) { *dst8++ = blue; *dst8++ = green; *dst8++ = red; } else { *dst8++ = red; *dst8++ = green; *dst8++ = blue; } } return dstData; } else if (dstBpp == 32) { int i; uint32 pixel; uint16* src16; uint32* dst32; uint8 red, green, blue; if (dstData == NULL) dstData = (uint8*) malloc(width * height * 4); src16 = (uint16*) srcData; dst32 = (uint32*) dstData; for (i = width * height; i > 0; i--) { pixel = *src16; src16++; GetBGR16(red, green, blue, pixel); pixel = (clrconv->invert) ? RGB32(red, green, blue) : BGR32(red, green, blue); *dst32 = pixel; dst32++; } return dstData; } return srcData; } uint8* freerdp_image_convert_24bpp(uint8* srcData, uint8* dstData, int width, int height, int srcBpp, int dstBpp, HCLRCONV clrconv) { int i; if (dstBpp == 32) { uint8 *dstp; if (dstData == NULL) dstData = (uint8*) malloc(width * height * 4); dstp = dstData; for (i = width * height; i > 0; i--) { *(dstp++) = *(srcData++); *(dstp++) = *(srcData++); *(dstp++) = *(srcData++); *(dstp++) = 0xFF; } return dstData; } return srcData; } uint8* freerdp_image_convert_32bpp(uint8* srcData, uint8* dstData, int width, int height, int srcBpp, int dstBpp, HCLRCONV clrconv) { if (dstBpp == 16) { int index; uint16 *dst16; uint32 *src32; uint8 red, green, blue; if (dstData == NULL) dstData = (uint8*) malloc(width * height * 2); dst16 = (uint16*) dstData; src32 = (uint32*) srcData; for (index = 0; index < width * height; index++) { GetBGR32(blue, green, red, *src32); *dst16 = (clrconv->invert) ? BGR16(red, green, blue) : RGB16(red, green, blue); src32++; dst16++; } return dstData; } else if (dstBpp == 24) { uint8 *dstp; int index; uint8 red, green, blue; if (dstData == NULL) dstData = (uint8*) malloc(width * height * 3); dstp = dstData; for (index = 0; index < width * height; index++) { red = *(srcData++); green = *(srcData++); blue = *(srcData++); if (clrconv->invert) { *dstp++ = blue; *dstp++ = green; *dstp++ = red; } else { *dstp++ = red; *dstp++ = green; *dstp++ = blue; } srcData++; } return dstData; } else if (dstBpp == 32) { if (clrconv->alpha) { int x, y; uint8 *dstp; if (dstData == NULL) dstData = (uint8*) malloc(width * height * 4); memcpy(dstData, srcData, width * height * 4); dstp = dstData; for (y = 0; y < height; y++) { for (x = 0; x < width * 4; x += 4) { dstp += 3; *dstp = 0xFF; dstp++; } } } else { if (dstData == NULL) dstData = (uint8*) malloc(width * height * 4); memcpy(dstData, srcData, width * height * 4); } return dstData; } return srcData; } p_freerdp_image_convert freerdp_image_convert_[5] = { NULL, freerdp_image_convert_8bpp, freerdp_image_convert_16bpp, freerdp_image_convert_24bpp, freerdp_image_convert_32bpp }; uint8* freerdp_image_convert(uint8* srcData, uint8* dstData, int width, int height, int srcBpp, int dstBpp, HCLRCONV clrconv) { p_freerdp_image_convert _p_freerdp_image_convert = freerdp_image_convert_[IBPP(srcBpp)]; if (_p_freerdp_image_convert != NULL) return _p_freerdp_image_convert(srcData, dstData, width, height, srcBpp, dstBpp, clrconv); else return 0; } void freerdp_bitmap_flip(uint8 * src, uint8 * dst, int scanLineSz, int height) { int i; uint8 * bottomLine = dst + (scanLineSz * (height - 1)); uint8 * topLine = src; /* Special processing if called for flip-in-place. */ if (src == dst) { /* Allocate a scanline buffer. * (FIXME: xmalloc / xfree below should be replaced by "get/put * scanline buffer from a pool/Q of fixed buffers" to reuse * fixed size buffers (of max scanline size (or adaptative?) ) * -- would be much faster). */ uint8 * tmpBfr = xmalloc(scanLineSz); int half = height / 2; /* Flip buffer in place by line permutations through the temp * scan line buffer. * Not that if height has an odd number of line, we don't need * to move the center scanline anyway. * Also note that in place flipping takes three memcpy() calls * to process two scanlines while src to distinct dest would * only requires two memcpy() calls for two scanlines. */ height--; for (i = 0; i < half ; i++) { memcpy(tmpBfr, topLine, scanLineSz); memcpy(topLine, bottomLine, scanLineSz); memcpy(bottomLine, tmpBfr, scanLineSz); topLine += scanLineSz; bottomLine -= scanLineSz; height--; } xfree(tmpBfr); } /* Flip from source buffer to destination buffer. */ else { for (i = 0; i < height; i++) { memcpy(bottomLine, topLine, scanLineSz); topLine += scanLineSz; bottomLine -= scanLineSz; } } } uint8* freerdp_image_flip(uint8* srcData, uint8* dstData, int width, int height, int bpp) { int scanline; scanline = width * (bpp / 8); if (dstData == NULL) dstData = (uint8*) xmalloc(width * height * (bpp / 8)); freerdp_bitmap_flip(srcData, dstData, scanline, height); return dstData; } uint8* freerdp_icon_convert(uint8* srcData, uint8* dstData, uint8* mask, int width, int height, int bpp, HCLRCONV clrconv) { int x, y; int pixel; uint8* data; uint8 bmask; uint32 pmask; uint32* icon; pixel = 0; data = freerdp_image_flip(srcData, dstData, width, height, bpp); dstData = freerdp_image_convert(data, NULL, width, height, bpp, 32, clrconv); free(data); bmask = mask[pixel]; icon = (uint32*) dstData; if (bpp < 32) { for (y = 0; y < height; y++) { for (x = 0; x < width; x++) { if (pixel % 8 == 0) bmask = mask[pixel / 8]; else bmask <<= 1; pmask = (bmask & 0x80) ? 0x00000000 : 0xFF000000; *icon++ |= pmask; pixel++; } } } free(mask); return dstData; } uint8* freerdp_glyph_convert(int width, int height, uint8* data) { int x, y; uint8 *srcp; uint8 *dstp; uint8 *dstData; int scanline; /* * converts a 1-bit-per-pixel glyph to a one-byte-per-pixel glyph: * this approach uses a little more memory, but provides faster * means of accessing individual pixels in blitting operations */ scanline = (width + 7) / 8; dstData = (uint8*) malloc(width * height); memset(dstData, 0, width * height); dstp = dstData; for (y = 0; y < height; y++) { srcp = data + (y * scanline); for (x = 0; x < width; x++) { if ((*srcp & (0x80 >> (x % 8))) != 0) *dstp = 0xFF; dstp++; if (((x + 1) % 8 == 0) && x != 0) srcp++; } } return dstData; } uint8* freerdp_mono_image_convert(uint8* srcData, int width, int height, int srcBpp, int dstBpp, uint32 bgcolor, uint32 fgcolor, HCLRCONV clrconv) { int index; uint16* dst16; uint32* dst32; uint8* dstData; uint8 bitMask; int bitIndex; uint8 redBg, greenBg, blueBg; uint8 redFg, greenFg, blueFg; switch (srcBpp) { case 8: bgcolor &= 0xFF; redBg = clrconv->palette->entries[bgcolor].red; greenBg = clrconv->palette->entries[bgcolor].green; blueBg = clrconv->palette->entries[bgcolor].blue; fgcolor &= 0xFF; redFg = clrconv->palette->entries[fgcolor].red; greenFg = clrconv->palette->entries[fgcolor].green; blueFg = clrconv->palette->entries[fgcolor].blue; break; case 16: GetRGB16(redBg, greenBg, blueBg, bgcolor); GetRGB16(redFg, greenFg, blueFg, fgcolor); break; case 15: GetRGB15(redBg, greenBg, blueBg, bgcolor); GetRGB15(redFg, greenFg, blueFg, fgcolor); break; default: GetRGB32(redBg, greenBg, blueBg, bgcolor); GetRGB32(redFg, greenFg, blueFg, fgcolor); break; } if (dstBpp == 16) { if (clrconv->rgb555) { if (srcBpp == 16) { /* convert 15-bit colors to 16-bit colors */ RGB16_RGB15(redBg, greenBg, blueBg, bgcolor); RGB16_RGB15(redFg, greenFg, blueFg, fgcolor); } } else { if (srcBpp == 15) { /* convert 15-bit colors to 16-bit colors */ RGB15_RGB16(redBg, greenBg, blueBg, bgcolor); RGB15_RGB16(redFg, greenFg, blueFg, fgcolor); } } dstData = (uint8*) malloc(width * height * 2); dst16 = (uint16*) dstData; for (index = height; index > 0; index--) { /* each bit encodes a pixel */ bitMask = *srcData; for (bitIndex = 7; bitIndex >= 0; bitIndex--) { if ((bitMask >> bitIndex) & 0x01) { *dst16 = bgcolor; } else { *dst16 = fgcolor; } dst16++; } srcData++; } return dstData; } else if (dstBpp == 32) { dstData = (uint8*) malloc(width * height * 4); dst32 = (uint32*) dstData; for (index = height; index > 0; index--) { /* each bit encodes a pixel */ bitMask = *srcData; for (bitIndex = 7; bitIndex >= 0; bitIndex--) { if ((bitMask >> bitIndex) & 0x01) { *dst32 = (clrconv->invert) ? BGR32(redBg, greenBg, blueBg) : RGB32(redBg, greenBg, blueBg); } else { *dst32 = (clrconv->invert) ? BGR32(redFg, greenFg, blueFg) : RGB32(redFg, greenFg, blueFg); } dst32++; } srcData++; } return dstData; } return srcData; } void freerdp_alpha_cursor_convert(uint8* alphaData, uint8* xorMask, uint8* andMask, int width, int height, int bpp, HCLRCONV clrconv) { int xpixel; int apixel; int i, j, jj; for (j = 0; j < height; j++) { jj = (bpp == 1) ? j : (height - 1) - j; for (i = 0; i < width; i++) { xpixel = freerdp_get_pixel(xorMask, i, jj, width, height, bpp); xpixel = freerdp_color_convert_rgb(xpixel, bpp, 32, clrconv); apixel = freerdp_get_pixel(andMask, i, jj, width, height, 1); if (apixel != 0) { if ((xpixel & 0xffffff) == 0xffffff) { /* use pattern (not solid black) for xor area */ xpixel = (i & 1) == (j & 1); xpixel = xpixel ? 0xFFFFFF : 0; xpixel |= 0xFF000000; } else if (xpixel == 0xFF000000) { xpixel = 0; } } freerdp_set_pixel(alphaData, i, j, width, height, 32, xpixel); } } } void freerdp_image_swap_color_order(uint8* data, int width, int height) { int x, y; uint32* pixel; uint8 a, r, g, b; pixel = (uint32*) data; for (y = 0; y < height; y++) { for (x = 0; x < width; x++) { GetARGB32(a, r, g, b, *pixel); *pixel = ABGR32(a, r, g, b); pixel++; } } } HCLRCONV freerdp_clrconv_new(uint32 flags) { HCLRCONV clrconv = xnew(CLRCONV); clrconv->alpha = (flags & CLRCONV_ALPHA) ? true : false; clrconv->invert = (flags & CLRCONV_INVERT) ? true : false; clrconv->rgb555 = (flags & CLRCONV_RGB555) ? true : false; clrconv->palette = xnew(rdpPalette); return clrconv; } void freerdp_clrconv_free(HCLRCONV clrconv) { if (clrconv != NULL) { if (clrconv->palette != NULL) xfree(clrconv->palette); xfree(clrconv); } } FreeRDP-1.0.2/libfreerdp-codec/include/000077500000000000000000000000001207112532300175515ustar00rootroot00000000000000FreeRDP-1.0.2/libfreerdp-codec/include/bitmap.c000066400000000000000000000306401207112532300211740ustar00rootroot00000000000000/** * FreeRDP: A Remote Desktop Protocol Client * RLE Compressed Bitmap Stream * * Copyright 2011 Jay Sorg * * 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. */ /* do not compile the file directly */ /** * Write a foreground/background image to a destination buffer. */ static uint8* WRITEFGBGIMAGE(uint8* pbDest, uint32 rowDelta, uint8 bitmask, PIXEL fgPel, uint32 cBits) { PIXEL xorPixel; DESTREADPIXEL(xorPixel, pbDest - rowDelta); if (bitmask & g_MaskBit0) { DESTWRITEPIXEL(pbDest, xorPixel ^ fgPel); } else { DESTWRITEPIXEL(pbDest, xorPixel); } DESTNEXTPIXEL(pbDest); cBits = cBits - 1; if (cBits > 0) { DESTREADPIXEL(xorPixel, pbDest - rowDelta); if (bitmask & g_MaskBit1) { DESTWRITEPIXEL(pbDest, xorPixel ^ fgPel); } else { DESTWRITEPIXEL(pbDest, xorPixel); } DESTNEXTPIXEL(pbDest); cBits = cBits - 1; if (cBits > 0) { DESTREADPIXEL(xorPixel, pbDest - rowDelta); if (bitmask & g_MaskBit2) { DESTWRITEPIXEL(pbDest, xorPixel ^ fgPel); } else { DESTWRITEPIXEL(pbDest, xorPixel); } DESTNEXTPIXEL(pbDest); cBits = cBits - 1; if (cBits > 0) { DESTREADPIXEL(xorPixel, pbDest - rowDelta); if (bitmask & g_MaskBit3) { DESTWRITEPIXEL(pbDest, xorPixel ^ fgPel); } else { DESTWRITEPIXEL(pbDest, xorPixel); } DESTNEXTPIXEL(pbDest); cBits = cBits - 1; if (cBits > 0) { DESTREADPIXEL(xorPixel, pbDest - rowDelta); if (bitmask & g_MaskBit4) { DESTWRITEPIXEL(pbDest, xorPixel ^ fgPel); } else { DESTWRITEPIXEL(pbDest, xorPixel); } DESTNEXTPIXEL(pbDest); cBits = cBits - 1; if (cBits > 0) { DESTREADPIXEL(xorPixel, pbDest - rowDelta); if (bitmask & g_MaskBit5) { DESTWRITEPIXEL(pbDest, xorPixel ^ fgPel); } else { DESTWRITEPIXEL(pbDest, xorPixel); } DESTNEXTPIXEL(pbDest); cBits = cBits - 1; if (cBits > 0) { DESTREADPIXEL(xorPixel, pbDest - rowDelta); if (bitmask & g_MaskBit6) { DESTWRITEPIXEL(pbDest, xorPixel ^ fgPel); } else { DESTWRITEPIXEL(pbDest, xorPixel); } DESTNEXTPIXEL(pbDest); cBits = cBits - 1; if (cBits > 0) { DESTREADPIXEL(xorPixel, pbDest - rowDelta); if (bitmask & g_MaskBit7) { DESTWRITEPIXEL(pbDest, xorPixel ^ fgPel); } else { DESTWRITEPIXEL(pbDest, xorPixel); } DESTNEXTPIXEL(pbDest); } } } } } } } return pbDest; } /** * Write a foreground/background image to a destination buffer * for the first line of compressed data. */ static uint8* WRITEFIRSTLINEFGBGIMAGE(uint8* pbDest, uint8 bitmask, PIXEL fgPel, uint32 cBits) { if (bitmask & g_MaskBit0) { DESTWRITEPIXEL(pbDest, fgPel); } else { DESTWRITEPIXEL(pbDest, BLACK_PIXEL); } DESTNEXTPIXEL(pbDest); cBits = cBits - 1; if (cBits > 0) { if (bitmask & g_MaskBit1) { DESTWRITEPIXEL(pbDest, fgPel); } else { DESTWRITEPIXEL(pbDest, BLACK_PIXEL); } DESTNEXTPIXEL(pbDest); cBits = cBits - 1; if (cBits > 0) { if (bitmask & g_MaskBit2) { DESTWRITEPIXEL(pbDest, fgPel); } else { DESTWRITEPIXEL(pbDest, BLACK_PIXEL); } DESTNEXTPIXEL(pbDest); cBits = cBits - 1; if (cBits > 0) { if (bitmask & g_MaskBit3) { DESTWRITEPIXEL(pbDest, fgPel); } else { DESTWRITEPIXEL(pbDest, BLACK_PIXEL); } DESTNEXTPIXEL(pbDest); cBits = cBits - 1; if (cBits > 0) { if (bitmask & g_MaskBit4) { DESTWRITEPIXEL(pbDest, fgPel); } else { DESTWRITEPIXEL(pbDest, BLACK_PIXEL); } DESTNEXTPIXEL(pbDest); cBits = cBits - 1; if (cBits > 0) { if (bitmask & g_MaskBit5) { DESTWRITEPIXEL(pbDest, fgPel); } else { DESTWRITEPIXEL(pbDest, BLACK_PIXEL); } DESTNEXTPIXEL(pbDest); cBits = cBits - 1; if (cBits > 0) { if (bitmask & g_MaskBit6) { DESTWRITEPIXEL(pbDest, fgPel); } else { DESTWRITEPIXEL(pbDest, BLACK_PIXEL); } DESTNEXTPIXEL(pbDest); cBits = cBits - 1; if (cBits > 0) { if (bitmask & g_MaskBit7) { DESTWRITEPIXEL(pbDest, fgPel); } else { DESTWRITEPIXEL(pbDest, BLACK_PIXEL); } DESTNEXTPIXEL(pbDest); } } } } } } } return pbDest; } /** * Decompress an RLE compressed bitmap. */ void RLEDECOMPRESS(uint8* pbSrcBuffer, uint32 cbSrcBuffer, uint8* pbDestBuffer, uint32 rowDelta, uint32 width, uint32 height) { uint8* pbSrc = pbSrcBuffer; uint8* pbEnd = pbSrcBuffer + cbSrcBuffer; uint8* pbDest = pbDestBuffer; PIXEL temp; PIXEL fgPel = WHITE_PIXEL; boolean fInsertFgPel = false; boolean fFirstLine = true; uint8 bitmask; PIXEL pixelA, pixelB; uint32 runLength; uint32 code; uint32 advance; RLEEXTRA while (pbSrc < pbEnd) { /* Watch out for the end of the first scanline. */ if (fFirstLine) { if ((uint32)(pbDest - pbDestBuffer) >= rowDelta) { fFirstLine = false; fInsertFgPel = false; } } /* Extract the compression order code ID from the compression order header. */ code = ExtractCodeId(*pbSrc); /* Handle Background Run Orders. */ if (code == REGULAR_BG_RUN || code == MEGA_MEGA_BG_RUN) { runLength = ExtractRunLength(code, pbSrc, &advance); pbSrc = pbSrc + advance; if (fFirstLine) { if (fInsertFgPel) { DESTWRITEPIXEL(pbDest, fgPel); DESTNEXTPIXEL(pbDest); runLength = runLength - 1; } while (runLength >= UNROLL_COUNT) { UNROLL( DESTWRITEPIXEL(pbDest, BLACK_PIXEL); DESTNEXTPIXEL(pbDest); ); runLength = runLength - UNROLL_COUNT; } while (runLength > 0) { DESTWRITEPIXEL(pbDest, BLACK_PIXEL); DESTNEXTPIXEL(pbDest); runLength = runLength - 1; } } else { if (fInsertFgPel) { DESTREADPIXEL(temp, pbDest - rowDelta); DESTWRITEPIXEL(pbDest, temp ^ fgPel); DESTNEXTPIXEL(pbDest); runLength = runLength - 1; } while (runLength >= UNROLL_COUNT) { UNROLL( DESTREADPIXEL(temp, pbDest - rowDelta); DESTWRITEPIXEL(pbDest, temp); DESTNEXTPIXEL(pbDest); ); runLength = runLength - UNROLL_COUNT; } while (runLength > 0) { DESTREADPIXEL(temp, pbDest - rowDelta); DESTWRITEPIXEL(pbDest, temp); DESTNEXTPIXEL(pbDest); runLength = runLength - 1; } } /* A follow-on background run order will need a foreground pel inserted. */ fInsertFgPel = true; continue; } /* For any of the other run-types a follow-on background run order does not need a foreground pel inserted. */ fInsertFgPel = false; switch (code) { /* Handle Foreground Run Orders. */ case REGULAR_FG_RUN: case MEGA_MEGA_FG_RUN: case LITE_SET_FG_FG_RUN: case MEGA_MEGA_SET_FG_RUN: runLength = ExtractRunLength(code, pbSrc, &advance); pbSrc = pbSrc + advance; if (code == LITE_SET_FG_FG_RUN || code == MEGA_MEGA_SET_FG_RUN) { SRCREADPIXEL(fgPel, pbSrc); SRCNEXTPIXEL(pbSrc); } if (fFirstLine) { while (runLength >= UNROLL_COUNT) { UNROLL( DESTWRITEPIXEL(pbDest, fgPel); DESTNEXTPIXEL(pbDest); ); runLength = runLength - UNROLL_COUNT; } while (runLength > 0) { DESTWRITEPIXEL(pbDest, fgPel); DESTNEXTPIXEL(pbDest); runLength = runLength - 1; } } else { while (runLength >= UNROLL_COUNT) { UNROLL( DESTREADPIXEL(temp, pbDest - rowDelta); DESTWRITEPIXEL(pbDest, temp ^ fgPel); DESTNEXTPIXEL(pbDest); ); runLength = runLength - UNROLL_COUNT; } while (runLength > 0) { DESTREADPIXEL(temp, pbDest - rowDelta); DESTWRITEPIXEL(pbDest, temp ^ fgPel); DESTNEXTPIXEL(pbDest); runLength = runLength - 1; } } break; /* Handle Dithered Run Orders. */ case LITE_DITHERED_RUN: case MEGA_MEGA_DITHERED_RUN: runLength = ExtractRunLength(code, pbSrc, &advance); pbSrc = pbSrc + advance; SRCREADPIXEL(pixelA, pbSrc); SRCNEXTPIXEL(pbSrc); SRCREADPIXEL(pixelB, pbSrc); SRCNEXTPIXEL(pbSrc); while (runLength >= UNROLL_COUNT) { UNROLL( DESTWRITEPIXEL(pbDest, pixelA); DESTNEXTPIXEL(pbDest); DESTWRITEPIXEL(pbDest, pixelB); DESTNEXTPIXEL(pbDest); ); runLength = runLength - UNROLL_COUNT; } while (runLength > 0) { DESTWRITEPIXEL(pbDest, pixelA); DESTNEXTPIXEL(pbDest); DESTWRITEPIXEL(pbDest, pixelB); DESTNEXTPIXEL(pbDest); runLength = runLength - 1; } break; /* Handle Color Run Orders. */ case REGULAR_COLOR_RUN: case MEGA_MEGA_COLOR_RUN: runLength = ExtractRunLength(code, pbSrc, &advance); pbSrc = pbSrc + advance; SRCREADPIXEL(pixelA, pbSrc); SRCNEXTPIXEL(pbSrc); while (runLength >= UNROLL_COUNT) { UNROLL( DESTWRITEPIXEL(pbDest, pixelA); DESTNEXTPIXEL(pbDest); ); runLength = runLength - UNROLL_COUNT; } while (runLength > 0) { DESTWRITEPIXEL(pbDest, pixelA); DESTNEXTPIXEL(pbDest); runLength = runLength - 1; } break; /* Handle Foreground/Background Image Orders. */ case REGULAR_FGBG_IMAGE: case MEGA_MEGA_FGBG_IMAGE: case LITE_SET_FG_FGBG_IMAGE: case MEGA_MEGA_SET_FGBG_IMAGE: runLength = ExtractRunLength(code, pbSrc, &advance); pbSrc = pbSrc + advance; if (code == LITE_SET_FG_FGBG_IMAGE || code == MEGA_MEGA_SET_FGBG_IMAGE) { SRCREADPIXEL(fgPel, pbSrc); SRCNEXTPIXEL(pbSrc); } if (fFirstLine) { while (runLength > 8) { bitmask = *pbSrc; pbSrc = pbSrc + 1; pbDest = WRITEFIRSTLINEFGBGIMAGE(pbDest, bitmask, fgPel, 8); runLength = runLength - 8; } } else { while (runLength > 8) { bitmask = *pbSrc; pbSrc = pbSrc + 1; pbDest = WRITEFGBGIMAGE(pbDest, rowDelta, bitmask, fgPel, 8); runLength = runLength - 8; } } if (runLength > 0) { bitmask = *pbSrc; pbSrc = pbSrc + 1; if (fFirstLine) { pbDest = WRITEFIRSTLINEFGBGIMAGE(pbDest, bitmask, fgPel, runLength); } else { pbDest = WRITEFGBGIMAGE(pbDest, rowDelta, bitmask, fgPel, runLength); } } break; /* Handle Color Image Orders. */ case REGULAR_COLOR_IMAGE: case MEGA_MEGA_COLOR_IMAGE: runLength = ExtractRunLength(code, pbSrc, &advance); pbSrc = pbSrc + advance; while (runLength >= UNROLL_COUNT) { UNROLL( SRCREADPIXEL(temp, pbSrc); SRCNEXTPIXEL(pbSrc); DESTWRITEPIXEL(pbDest, temp); DESTNEXTPIXEL(pbDest); ); runLength = runLength - UNROLL_COUNT; } while (runLength > 0) { SRCREADPIXEL(temp, pbSrc); SRCNEXTPIXEL(pbSrc); DESTWRITEPIXEL(pbDest, temp); DESTNEXTPIXEL(pbDest); runLength = runLength - 1; } break; /* Handle Special Order 1. */ case SPECIAL_FGBG_1: pbSrc = pbSrc + 1; if (fFirstLine) { pbDest = WRITEFIRSTLINEFGBGIMAGE(pbDest, g_MaskSpecialFgBg1, fgPel, 8); } else { pbDest = WRITEFGBGIMAGE(pbDest, rowDelta, g_MaskSpecialFgBg1, fgPel, 8); } break; /* Handle Special Order 2. */ case SPECIAL_FGBG_2: pbSrc = pbSrc + 1; if (fFirstLine) { pbDest = WRITEFIRSTLINEFGBGIMAGE(pbDest, g_MaskSpecialFgBg2, fgPel, 8); } else { pbDest = WRITEFGBGIMAGE(pbDest, rowDelta, g_MaskSpecialFgBg2, fgPel, 8); } break; /* Handle White Order. */ case SPECIAL_WHITE: pbSrc = pbSrc + 1; DESTWRITEPIXEL(pbDest, WHITE_PIXEL); DESTNEXTPIXEL(pbDest); break; /* Handle Black Order. */ case SPECIAL_BLACK: pbSrc = pbSrc + 1; DESTWRITEPIXEL(pbDest, BLACK_PIXEL); DESTNEXTPIXEL(pbDest); break; } } } FreeRDP-1.0.2/libfreerdp-codec/nsc.c000066400000000000000000000211331207112532300170550ustar00rootroot00000000000000/** * FreeRDP: A Remote Desktop Protocol client. * NSCodec Codec * * Copyright 2011 Samsung, Author Jiten Pathy * * 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. */ #include #include #include #include #include #include /* we store the 9th bits at the end of stream as bitstream */ void nsc_cl_expand(STREAM* stream, uint8 shiftcount, uint32 origsz) { uint8* sbitstream; uint8* temptr; uint8 sign,bitoff; uint32 bitno; sbitstream = stream->data + origsz; do { sign = (*(stream->p) << (shiftcount - 1)) & 0x80; bitno = stream->p - stream->data; *(stream->p++) <<= shiftcount; temptr = sbitstream + ((bitno) >> 3); bitoff = bitno % 0x8; (*temptr) |= (sign >> bitoff); } while (((uint32)(stream->p - stream->data)) < origsz); stream->p = stream->data; } void nsc_chroma_supersample(NSC_CONTEXT* context) { int i; uint8* cur; uint8* tptr; uint8* nbitstream; uint8* sbitstream; uint8 val, bitoff, sign; uint16 w, h, pw, row; uint32 alloclen, orglen, bytno; STREAM* new_s; STREAM* temp; w = context->width; h = context->height; alloclen = orglen = w * h; pw = ROUND_UP_TO(context->width, 8); temp = stream_new(0); for (i = 0; i < 3; i++) { if (i != 0) alloclen = orglen + ((orglen & 0x7) ? (orglen >> 3) + 0x1 : (orglen >> 3)); new_s = stream_new(alloclen); stream_attach(temp, context->org_buf[i]->data, context->org_buf[i]->size); sbitstream = temp->data + context->OrgByteCount[i]; nbitstream = new_s->data + orglen; cur = new_s->p; if (i == 1) pw >>= 1; while (((uint32)(temp->p - temp->data)) < context->OrgByteCount[i]) { bytno = temp->p - temp->data; bitoff = bytno % 0x8; stream_read_uint8(temp, val); *cur = val; row = (temp->p - temp->data) % pw; if (i == 0) { cur++; if (row >= w) stream_seek(temp, pw-row); } else { tptr = sbitstream + ((bytno) >> 3); sign = ((*tptr) << bitoff) & 0x80; bytno = cur - new_s->data; bitoff = bytno % 8; *(nbitstream + (bytno >> 3)) |= (sign >> bitoff); if ((bytno+w) < orglen) { *(cur + w) = val; bitoff = (bytno + w) % 8; *(nbitstream + ((bytno + w) >> 3)) |= (sign >> bitoff); } if ((bytno+1) % w) { *(cur+1) = val; bitoff = (bytno + 1) % 8; *(nbitstream + ((bytno + 1) >> 3)) |= (sign >> bitoff); if ((bytno+w) < orglen) { *(cur+w+1) = val; bitoff = (bytno + w + 1) % 8; *(nbitstream + ((bytno + w + 1) >> 3)) |= (sign >> bitoff); } } cur += 2; bytno = cur - new_s->data; if (((bytno/w) < h) && ((bytno) % w) < 2 ) { if (w % 2) cur += w-1; else cur += w; } if ((row*2) >= w) stream_seek(temp, pw-row); } } xfree(temp->data); stream_detach(temp); stream_attach(context->org_buf[i], new_s->data, new_s->size); context->OrgByteCount[i] = orglen; } } void nsc_ycocg_rgb(NSC_CONTEXT* context) { uint8* sbitstream[2]; uint8 bitoff, sign[2], i, val, tmp; sint16 rgb[3], ycocg[3]; uint32 bytno, size; size = context->OrgByteCount[0]; for (i = 1; i < 3; i++) sbitstream[i-1] = context->org_buf[i]->data + context->OrgByteCount[i]; do { for (i = 0; i < 3; i++) ycocg[i] = *(context->org_buf[i]->p); for (i = 1; i < 3; i++) { bytno = context->OrgByteCount[i] - size; bitoff = bytno % 8; sign[i-1] = (*(sbitstream[i-1] + (bytno >> 3)) >> (7 - bitoff)) & 0x1; ycocg[i] = (((sint16)(0 - sign[i-1])) << 8) | ycocg[i]; } rgb[0] = ycocg[0] + (ycocg[1] >> 1) - (ycocg[2] >> 1); rgb[1] = ycocg[0] + (ycocg[2] >> 1); rgb[2] = ycocg[0] - (ycocg[1] >> 1) - (ycocg[2] >> 1); for (i = 0; i < 3; i++) { tmp = (rgb[i] >> 8) & 0xff; if (tmp == 0xff) val = 0x00; else if (tmp == 0x1) val = 0xff; else val = (uint8) rgb[i]; stream_write_uint8(context->org_buf[i], val); } size--; } while (size); for (i = 0; i < 3; i++) context->org_buf[i]->p = context->org_buf[i]->data; } void nsc_colorloss_recover(NSC_CONTEXT* context) { int i; uint8 cllvl; cllvl = context->nsc_stream->colorLossLevel; for (i = 1; i < 3; i++) nsc_cl_expand(context->org_buf[i], cllvl, context->OrgByteCount[i]); } void nsc_rle_decode(STREAM* in, STREAM* out, uint32 origsz) { uint32 i; uint8 value; i = origsz; while (i > 4) { stream_read_uint8(in, value); if (i == 5) { stream_write_uint8(out,value); i-=1; } else if (value == *(in->p)) { stream_seek(in, 1); if (*(in->p) < 0xFF) { uint8 len; stream_read_uint8(in, len); stream_set_byte(out, value, len+2); i -= (len+2); } else { uint32 len; stream_seek(in, 1); stream_read_uint32(in, len); stream_set_byte(out, value, len); i -= len; } } else { stream_write_uint8(out, value); i -= 1; } } stream_copy(out, in, 4); } void nsc_rle_decompress_data(NSC_CONTEXT* context) { STREAM* rles; uint16 i; uint32 origsize; rles = stream_new(0); rles->p = rles->data = context->nsc_stream->pdata->p; rles->size = context->nsc_stream->pdata->size; for (i = 0; i < 4; i++) { origsize = context->OrgByteCount[i]; if (i == 3 && context->nsc_stream->PlaneByteCount[i] == 0) stream_set_byte(context->org_buf[i], 0xff, origsize); else if (context->nsc_stream->PlaneByteCount[i] < origsize) nsc_rle_decode(rles, context->org_buf[i], origsize); else stream_copy(context->org_buf[i], rles, origsize); context->org_buf[i]->p = context->org_buf[i]->data; } } void nsc_combine_argb(NSC_CONTEXT* context) { int i; uint8* bmp; bmp = context->bmpdata; for (i = 0; i < (context->width * context->height); i++) { stream_read_uint8(context->org_buf[2], *bmp++); stream_read_uint8(context->org_buf[1], *bmp++); stream_read_uint8(context->org_buf[0], *bmp++); stream_read_uint8(context->org_buf[3], *bmp++); } } void nsc_stream_initialize(NSC_CONTEXT* context, STREAM* s) { int i; for (i = 0; i < 4; i++) stream_read_uint32(s, context->nsc_stream->PlaneByteCount[i]); stream_read_uint8(s, context->nsc_stream->colorLossLevel); stream_read_uint8(s, context->nsc_stream->ChromaSubSamplingLevel); stream_seek(s, 2); context->nsc_stream->pdata = stream_new(0); stream_attach(context->nsc_stream->pdata, s->p, BYTESUM(context->nsc_stream->PlaneByteCount)); } void nsc_context_initialize(NSC_CONTEXT* context, STREAM* s) { int i; uint32 tempsz; nsc_stream_initialize(context, s); context->bmpdata = xzalloc(context->width * context->height * 4); for (i = 0; i < 4; i++) context->OrgByteCount[i]=context->width * context->height; if (context->nsc_stream->ChromaSubSamplingLevel > 0) /* [MS-RDPNSC] 2.2 */ { uint32 tempWidth,tempHeight; tempWidth = ROUND_UP_TO(context->width, 8); context->OrgByteCount[0] = tempWidth * context->height; tempWidth = tempWidth >> 1 ; tempHeight = ROUND_UP_TO(context->height, 2); tempHeight = tempHeight >> 1; context->OrgByteCount[1] = tempWidth * tempHeight; context->OrgByteCount[2] = tempWidth * tempHeight; } for (i = 0; i < 4; i++) { tempsz = context->OrgByteCount[i]; if (i == 1 || i == 2) tempsz += (tempsz & 0x7) ? (tempsz >> 3) + 0x1 : (tempsz >> 3); /* extra bytes/8 bytes for bitstream to store the 9th bit after colorloss recover */ context->org_buf[i] = stream_new(tempsz); } } void nsc_context_destroy(NSC_CONTEXT* context) { int i; for (i = 0;i < 4; i++) stream_free(context->org_buf[i]); stream_detach(context->nsc_stream->pdata); xfree(context->bmpdata); } NSC_CONTEXT* nsc_context_new(void) { NSC_CONTEXT* nsc_context; nsc_context = xnew(NSC_CONTEXT); nsc_context->nsc_stream = xnew(NSC_STREAM); return nsc_context; } void nsc_process_message(NSC_CONTEXT* context, uint8* data, uint32 length) { STREAM* s; s = stream_new(0); stream_attach(s, data, length); nsc_context_initialize(context, s); /* RLE decode */ nsc_rle_decompress_data(context); /* colorloss recover */ nsc_colorloss_recover(context); /* Chroma supersample */ if (context->nsc_stream->ChromaSubSamplingLevel > 0) nsc_chroma_supersample(context); /* YCoCg to RGB Convert */ nsc_ycocg_rgb(context); /* Combine ARGB planes */ nsc_combine_argb(context); } FreeRDP-1.0.2/libfreerdp-codec/rfx.c000066400000000000000000000645531207112532300171060ustar00rootroot00000000000000/** * FreeRDP: A Remote Desktop Protocol client. * RemoteFX Codec Library * * Copyright 2011 Vic Lee * * 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. */ #include #include #include #include #include #include #include #include "rfx_constants.h" #include "rfx_types.h" #include "rfx_pool.h" #include "rfx_decode.h" #include "rfx_encode.h" #include "rfx_quantization.h" #include "rfx_dwt.h" #ifdef WITH_SSE2 #include "rfx_sse2.h" #endif #ifdef WITH_NEON #include "rfx_neon.h" #endif #ifndef RFX_INIT_SIMD #define RFX_INIT_SIMD(_rfx_context) do { } while (0) #endif /** * The quantization values control the compression rate and quality. The value * range is between 6 and 15. The higher value, the higher compression rate * and lower quality. * * This is the default values being use by the MS RDP server, and we will also * use it as our default values for the encoder. It can be overrided by setting * the context->num_quants and context->quants member. * * The order of the values are: * LL3, LH3, HL3, HH3, LH2, HL2, HH2, LH1, HL1, HH1 */ static const uint32 rfx_default_quantization_values[] = { 6, 6, 6, 6, 7, 7, 8, 8, 8, 9 }; static void rfx_profiler_create(RFX_CONTEXT* context) { PROFILER_CREATE(context->priv->prof_rfx_decode_rgb, "rfx_decode_rgb"); PROFILER_CREATE(context->priv->prof_rfx_decode_component, "rfx_decode_component"); PROFILER_CREATE(context->priv->prof_rfx_rlgr_decode, "rfx_rlgr_decode"); PROFILER_CREATE(context->priv->prof_rfx_differential_decode, "rfx_differential_decode"); PROFILER_CREATE(context->priv->prof_rfx_quantization_decode, "rfx_quantization_decode"); PROFILER_CREATE(context->priv->prof_rfx_dwt_2d_decode, "rfx_dwt_2d_decode"); PROFILER_CREATE(context->priv->prof_rfx_decode_ycbcr_to_rgb, "rfx_decode_ycbcr_to_rgb"); PROFILER_CREATE(context->priv->prof_rfx_decode_format_rgb, "rfx_decode_format_rgb"); PROFILER_CREATE(context->priv->prof_rfx_encode_rgb, "rfx_encode_rgb"); PROFILER_CREATE(context->priv->prof_rfx_encode_component, "rfx_encode_component"); PROFILER_CREATE(context->priv->prof_rfx_rlgr_encode, "rfx_rlgr_encode"); PROFILER_CREATE(context->priv->prof_rfx_differential_encode, "rfx_differential_encode"); PROFILER_CREATE(context->priv->prof_rfx_quantization_encode, "rfx_quantization_encode"); PROFILER_CREATE(context->priv->prof_rfx_dwt_2d_encode, "rfx_dwt_2d_encode"); PROFILER_CREATE(context->priv->prof_rfx_encode_rgb_to_ycbcr, "rfx_encode_rgb_to_ycbcr"); PROFILER_CREATE(context->priv->prof_rfx_encode_format_rgb, "rfx_encode_format_rgb"); } static void rfx_profiler_free(RFX_CONTEXT* context) { PROFILER_FREE(context->priv->prof_rfx_decode_rgb); PROFILER_FREE(context->priv->prof_rfx_decode_component); PROFILER_FREE(context->priv->prof_rfx_rlgr_decode); PROFILER_FREE(context->priv->prof_rfx_differential_decode); PROFILER_FREE(context->priv->prof_rfx_quantization_decode); PROFILER_FREE(context->priv->prof_rfx_dwt_2d_decode); PROFILER_FREE(context->priv->prof_rfx_decode_ycbcr_to_rgb); PROFILER_FREE(context->priv->prof_rfx_decode_format_rgb); PROFILER_FREE(context->priv->prof_rfx_encode_rgb); PROFILER_FREE(context->priv->prof_rfx_encode_component); PROFILER_FREE(context->priv->prof_rfx_rlgr_encode); PROFILER_FREE(context->priv->prof_rfx_differential_encode); PROFILER_FREE(context->priv->prof_rfx_quantization_encode); PROFILER_FREE(context->priv->prof_rfx_dwt_2d_encode); PROFILER_FREE(context->priv->prof_rfx_encode_rgb_to_ycbcr); PROFILER_FREE(context->priv->prof_rfx_encode_format_rgb); } static void rfx_profiler_print(RFX_CONTEXT* context) { PROFILER_PRINT_HEADER; PROFILER_PRINT(context->priv->prof_rfx_decode_rgb); PROFILER_PRINT(context->priv->prof_rfx_decode_component); PROFILER_PRINT(context->priv->prof_rfx_rlgr_decode); PROFILER_PRINT(context->priv->prof_rfx_differential_decode); PROFILER_PRINT(context->priv->prof_rfx_quantization_decode); PROFILER_PRINT(context->priv->prof_rfx_dwt_2d_decode); PROFILER_PRINT(context->priv->prof_rfx_decode_ycbcr_to_rgb); PROFILER_PRINT(context->priv->prof_rfx_decode_format_rgb); PROFILER_PRINT(context->priv->prof_rfx_encode_rgb); PROFILER_PRINT(context->priv->prof_rfx_encode_component); PROFILER_PRINT(context->priv->prof_rfx_rlgr_encode); PROFILER_PRINT(context->priv->prof_rfx_differential_encode); PROFILER_PRINT(context->priv->prof_rfx_quantization_encode); PROFILER_PRINT(context->priv->prof_rfx_dwt_2d_encode); PROFILER_PRINT(context->priv->prof_rfx_encode_rgb_to_ycbcr); PROFILER_PRINT(context->priv->prof_rfx_encode_format_rgb); PROFILER_PRINT_FOOTER; } RFX_CONTEXT* rfx_context_new(void) { RFX_CONTEXT* context; context = xnew(RFX_CONTEXT); context->priv = xnew(RFX_CONTEXT_PRIV); context->priv->pool = rfx_pool_new(); /* initialize the default pixel format */ rfx_context_set_pixel_format(context, RFX_PIXEL_FORMAT_BGRA); /* align buffers to 16 byte boundary (needed for SSE/SSE2 instructions) */ context->priv->y_r_buffer = (sint16*)(((uintptr_t)context->priv->y_r_mem + 16) & ~ 0x0F); context->priv->cb_g_buffer = (sint16*)(((uintptr_t)context->priv->cb_g_mem + 16) & ~ 0x0F); context->priv->cr_b_buffer = (sint16*)(((uintptr_t)context->priv->cr_b_mem + 16) & ~ 0x0F); context->priv->dwt_buffer = (sint16*)(((uintptr_t)context->priv->dwt_mem + 16) & ~ 0x0F); /* create profilers for default decoding routines */ rfx_profiler_create(context); /* set up default routines */ context->decode_ycbcr_to_rgb = rfx_decode_ycbcr_to_rgb; context->encode_rgb_to_ycbcr = rfx_encode_rgb_to_ycbcr; context->quantization_decode = rfx_quantization_decode; context->quantization_encode = rfx_quantization_encode; context->dwt_2d_decode = rfx_dwt_2d_decode; context->dwt_2d_encode = rfx_dwt_2d_encode; return context; } void rfx_context_set_cpu_opt(RFX_CONTEXT* context, uint32 cpu_opt) { /* enable SIMD CPU acceleration if detected */ if (cpu_opt & CPU_SSE2) RFX_INIT_SIMD(context); } void rfx_context_free(RFX_CONTEXT* context) { xfree(context->quants); rfx_pool_free(context->priv->pool); rfx_profiler_print(context); rfx_profiler_free(context); xfree(context->priv); xfree(context); } void rfx_context_set_pixel_format(RFX_CONTEXT* context, RFX_PIXEL_FORMAT pixel_format) { context->pixel_format = pixel_format; switch (pixel_format) { case RFX_PIXEL_FORMAT_BGRA: case RFX_PIXEL_FORMAT_RGBA: context->bits_per_pixel = 32; break; case RFX_PIXEL_FORMAT_BGR: case RFX_PIXEL_FORMAT_RGB: context->bits_per_pixel = 24; break; case RFX_PIXEL_FORMAT_BGR565_LE: case RFX_PIXEL_FORMAT_RGB565_LE: context->bits_per_pixel = 16; break; case RFX_PIXEL_FORMAT_PALETTE4_PLANER: context->bits_per_pixel = 4; break; case RFX_PIXEL_FORMAT_PALETTE8: context->bits_per_pixel = 8; break; default: context->bits_per_pixel = 0; break; } } void rfx_context_reset(RFX_CONTEXT* context) { context->header_processed = false; context->frame_idx = 0; } static void rfx_process_message_sync(RFX_CONTEXT* context, STREAM* s) { uint32 magic; /* RFX_SYNC */ stream_read_uint32(s, magic); /* magic (4 bytes), 0xCACCACCA */ if (magic != WF_MAGIC) { DEBUG_WARN("invalid magic number 0x%X", magic); return; } stream_read_uint16(s, context->version); /* version (2 bytes), WF_VERSION_1_0 (0x0100) */ if (context->version != WF_VERSION_1_0) { DEBUG_WARN("unknown version number 0x%X", context->version); return; } DEBUG_RFX("version 0x%X", context->version); } static void rfx_process_message_codec_versions(RFX_CONTEXT* context, STREAM* s) { uint8 numCodecs; stream_read_uint8(s, numCodecs); /* numCodecs (1 byte), must be set to 0x01 */ if (numCodecs != 1) { DEBUG_WARN("numCodecs: %d, expected:1", numCodecs); return; } /* RFX_CODEC_VERSIONT */ stream_read_uint8(s, context->codec_id); /* codecId (1 byte) */ stream_read_uint8(s, context->codec_version); /* version (2 bytes) */ DEBUG_RFX("id %d version 0x%X.", context->codec_id, context->codec_version); } static void rfx_process_message_channels(RFX_CONTEXT* context, STREAM* s) { uint8 channelId; uint8 numChannels; stream_read_uint8(s, numChannels); /* numChannels (1 byte), must bet set to 0x01 */ /* In RDVH sessions, numChannels will represent the number of virtual monitors * configured and does not always be set to 0x01 as [MS-RDPRFX] said. */ if (numChannels < 1) { DEBUG_WARN("numChannels:%d, expected:1", numChannels); return; } /* RFX_CHANNELT */ stream_read_uint8(s, channelId); /* channelId (1 byte) */ stream_read_uint16(s, context->width); /* width (2 bytes) */ stream_read_uint16(s, context->height); /* height (2 bytes) */ /* Now, only the first monitor can be used, therefore the other channels will be ignored. */ stream_seek(s, 5 * (numChannels - 1)); DEBUG_RFX("numChannels %d id %d, %dx%d.", numChannels, channelId, context->width, context->height); } static void rfx_process_message_context(RFX_CONTEXT* context, STREAM* s) { uint8 ctxId; uint16 tileSize; uint16 properties; stream_read_uint8(s, ctxId); /* ctxId (1 byte), must be set to 0x00 */ stream_read_uint16(s, tileSize); /* tileSize (2 bytes), must be set to CT_TILE_64x64 (0x0040) */ stream_read_uint16(s, properties); /* properties (2 bytes) */ DEBUG_RFX("ctxId %d tileSize %d properties 0x%X.", ctxId, tileSize, properties); context->properties = properties; context->flags = (properties & 0x0007); if (context->flags == CODEC_MODE) DEBUG_RFX("codec is in image mode."); else DEBUG_RFX("codec is in video mode."); switch ((properties & 0x1E00) >> 9) { case CLW_ENTROPY_RLGR1: context->mode = RLGR1; DEBUG_RFX("RLGR1."); break; case CLW_ENTROPY_RLGR3: context->mode = RLGR3; DEBUG_RFX("RLGR3."); break; default: DEBUG_WARN("unknown RLGR algorithm."); break; } } static void rfx_process_message_frame_begin(RFX_CONTEXT* context, RFX_MESSAGE* message, STREAM* s) { uint32 frameIdx; uint16 numRegions; stream_read_uint32(s, frameIdx); /* frameIdx (4 bytes), if codec is in video mode, must be ignored */ stream_read_uint16(s, numRegions); /* numRegions (2 bytes) */ DEBUG_RFX("RFX_FRAME_BEGIN: frameIdx:%d numRegions:%d", frameIdx, numRegions); } static void rfx_process_message_frame_end(RFX_CONTEXT* context, RFX_MESSAGE* message, STREAM* s) { DEBUG_RFX("RFX_FRAME_END"); } static void rfx_process_message_region(RFX_CONTEXT* context, RFX_MESSAGE* message, STREAM* s) { int i; stream_seek_uint8(s); /* regionFlags (1 byte) */ stream_read_uint16(s, message->num_rects); /* numRects (2 bytes) */ if (message->num_rects < 1) { DEBUG_WARN("no rects."); return; } if (message->rects != NULL) message->rects = (RFX_RECT*) xrealloc(message->rects, message->num_rects * sizeof(RFX_RECT)); else message->rects = (RFX_RECT*) xmalloc(message->num_rects * sizeof(RFX_RECT)); /* rects */ for (i = 0; i < message->num_rects; i++) { /* RFX_RECT */ stream_read_uint16(s, message->rects[i].x); /* x (2 bytes) */ stream_read_uint16(s, message->rects[i].y); /* y (2 bytes) */ stream_read_uint16(s, message->rects[i].width); /* width (2 bytes) */ stream_read_uint16(s, message->rects[i].height); /* height (2 bytes) */ DEBUG_RFX("rect %d (%d %d %d %d).", i, message->rects[i].x, message->rects[i].y, message->rects[i].width, message->rects[i].height); } } static void rfx_process_message_tile(RFX_CONTEXT* context, RFX_TILE* tile, STREAM* s) { uint8 quantIdxY; uint8 quantIdxCb; uint8 quantIdxCr; uint16 xIdx, yIdx; uint16 YLen, CbLen, CrLen; /* RFX_TILE */ stream_read_uint8(s, quantIdxY); /* quantIdxY (1 byte) */ stream_read_uint8(s, quantIdxCb); /* quantIdxCb (1 byte) */ stream_read_uint8(s, quantIdxCr); /* quantIdxCr (1 byte) */ stream_read_uint16(s, xIdx); /* xIdx (2 bytes) */ stream_read_uint16(s, yIdx); /* yIdx (2 bytes) */ stream_read_uint16(s, YLen); /* YLen (2 bytes) */ stream_read_uint16(s, CbLen); /* CbLen (2 bytes) */ stream_read_uint16(s, CrLen); /* CrLen (2 bytes) */ DEBUG_RFX("quantIdxY:%d quantIdxCb:%d quantIdxCr:%d xIdx:%d yIdx:%d YLen:%d CbLen:%d CrLen:%d", quantIdxY, quantIdxCb, quantIdxCr, xIdx, yIdx, YLen, CbLen, CrLen); tile->x = xIdx * 64; tile->y = yIdx * 64; rfx_decode_rgb(context, s, YLen, context->quants + (quantIdxY * 10), CbLen, context->quants + (quantIdxCb * 10), CrLen, context->quants + (quantIdxCr * 10), tile->data); } static void rfx_process_message_tileset(RFX_CONTEXT* context, RFX_MESSAGE* message, STREAM* s) { int i; uint16 subtype; uint32 blockLen; uint32 blockType; uint32 tilesDataSize; uint32* quants; uint8 quant; int pos; stream_read_uint16(s, subtype); /* subtype (2 bytes) must be set to CBT_TILESET (0xCAC2) */ if (subtype != CBT_TILESET) { DEBUG_WARN("invalid subtype, expected CBT_TILESET."); return; } stream_seek_uint16(s); /* idx (2 bytes), must be set to 0x0000 */ stream_seek_uint16(s); /* properties (2 bytes) */ stream_read_uint8(s, context->num_quants); /* numQuant (1 byte) */ stream_seek_uint8(s); /* tileSize (1 byte), must be set to 0x40 */ if (context->num_quants < 1) { DEBUG_WARN("no quantization value."); return; } stream_read_uint16(s, message->num_tiles); /* numTiles (2 bytes) */ if (message->num_tiles < 1) { DEBUG_WARN("no tiles."); return; } stream_read_uint32(s, tilesDataSize); /* tilesDataSize (4 bytes) */ if (context->quants != NULL) context->quants = (uint32*) xrealloc((void*) context->quants, context->num_quants * 10 * sizeof(uint32)); else context->quants = (uint32*) xmalloc(context->num_quants * 10 * sizeof(uint32)); quants = context->quants; /* quantVals */ for (i = 0; i < context->num_quants; i++) { /* RFX_CODEC_QUANT */ stream_read_uint8(s, quant); *quants++ = (quant & 0x0F); *quants++ = (quant >> 4); stream_read_uint8(s, quant); *quants++ = (quant & 0x0F); *quants++ = (quant >> 4); stream_read_uint8(s, quant); *quants++ = (quant & 0x0F); *quants++ = (quant >> 4); stream_read_uint8(s, quant); *quants++ = (quant & 0x0F); *quants++ = (quant >> 4); stream_read_uint8(s, quant); *quants++ = (quant & 0x0F); *quants++ = (quant >> 4); DEBUG_RFX("quant %d (%d %d %d %d %d %d %d %d %d %d).", i, context->quants[i * 10], context->quants[i * 10 + 1], context->quants[i * 10 + 2], context->quants[i * 10 + 3], context->quants[i * 10 + 4], context->quants[i * 10 + 5], context->quants[i * 10 + 6], context->quants[i * 10 + 7], context->quants[i * 10 + 8], context->quants[i * 10 + 9]); } message->tiles = rfx_pool_get_tiles(context->priv->pool, message->num_tiles); /* tiles */ for (i = 0; i < message->num_tiles; i++) { /* RFX_TILE */ stream_read_uint16(s, blockType); /* blockType (2 bytes), must be set to CBT_TILE (0xCAC3) */ stream_read_uint32(s, blockLen); /* blockLen (4 bytes) */ pos = stream_get_pos(s) - 6 + blockLen; if (blockType != CBT_TILE) { DEBUG_WARN("unknown block type 0x%X, expected CBT_TILE (0xCAC3).", blockType); break; } rfx_process_message_tile(context, message->tiles[i], s); stream_set_pos(s, pos); } } RFX_MESSAGE* rfx_process_message(RFX_CONTEXT* context, uint8* data, uint32 length) { int pos; STREAM* s; uint32 blockLen; uint32 blockType; RFX_MESSAGE* message; s = stream_new(0); message = xnew(RFX_MESSAGE); stream_attach(s, data, length); while (stream_get_left(s) > 6) { /* RFX_BLOCKT */ stream_read_uint16(s, blockType); /* blockType (2 bytes) */ stream_read_uint32(s, blockLen); /* blockLen (4 bytes) */ DEBUG_RFX("blockType 0x%X blockLen %d", blockType, blockLen); if (blockLen == 0) { DEBUG_WARN("zero blockLen"); break; } pos = stream_get_pos(s) - 6 + blockLen; if (blockType >= WBT_CONTEXT && blockType <= WBT_EXTENSION) { /* RFX_CODEC_CHANNELT */ /* codecId (1 byte) must be set to 0x01 */ /* channelId (1 byte) must be set to 0x00 */ stream_seek(s, 2); } switch (blockType) { case WBT_SYNC: rfx_process_message_sync(context, s); break; case WBT_CODEC_VERSIONS: rfx_process_message_codec_versions(context, s); break; case WBT_CHANNELS: rfx_process_message_channels(context, s); break; case WBT_CONTEXT: rfx_process_message_context(context, s); break; case WBT_FRAME_BEGIN: rfx_process_message_frame_begin(context, message, s); break; case WBT_FRAME_END: rfx_process_message_frame_end(context, message, s); break; case WBT_REGION: rfx_process_message_region(context, message, s); break; case WBT_EXTENSION: rfx_process_message_tileset(context, message, s); break; default: DEBUG_WARN("unknown blockType 0x%X", blockType); break; } stream_set_pos(s, pos); } stream_detach(s); stream_free(s); return message; } uint16 rfx_message_get_tile_count(RFX_MESSAGE* message) { return message->num_tiles; } RFX_TILE* rfx_message_get_tile(RFX_MESSAGE* message, int index) { return message->tiles[index]; } uint16 rfx_message_get_rect_count(RFX_MESSAGE* message) { return message->num_rects; } RFX_RECT* rfx_message_get_rect(RFX_MESSAGE* message, int index) { return &message->rects[index]; } void rfx_message_free(RFX_CONTEXT* context, RFX_MESSAGE* message) { if (message != NULL) { xfree(message->rects); if (message->tiles != NULL) { rfx_pool_put_tiles(context->priv->pool, message->tiles, message->num_tiles); xfree(message->tiles); } xfree(message); } } static void rfx_compose_message_sync(RFX_CONTEXT* context, STREAM* s) { stream_write_uint16(s, WBT_SYNC); /* BlockT.blockType */ stream_write_uint32(s, 12); /* BlockT.blockLen */ stream_write_uint32(s, WF_MAGIC); /* magic */ stream_write_uint16(s, WF_VERSION_1_0); /* version */ } static void rfx_compose_message_codec_versions(RFX_CONTEXT* context, STREAM* s) { stream_write_uint16(s, WBT_CODEC_VERSIONS); /* BlockT.blockType */ stream_write_uint32(s, 10); /* BlockT.blockLen */ stream_write_uint8(s, 1); /* numCodecs */ stream_write_uint8(s, 1); /* codecs.codecId */ stream_write_uint16(s, WF_VERSION_1_0); /* codecs.version */ } static void rfx_compose_message_channels(RFX_CONTEXT* context, STREAM* s) { stream_write_uint16(s, WBT_CHANNELS); /* BlockT.blockType */ stream_write_uint32(s, 12); /* BlockT.blockLen */ stream_write_uint8(s, 1); /* numChannels */ stream_write_uint8(s, 0); /* Channel.channelId */ stream_write_uint16(s, context->width); /* Channel.width */ stream_write_uint16(s, context->height); /* Channel.height */ } static void rfx_compose_message_context(RFX_CONTEXT* context, STREAM* s) { uint16 properties; stream_write_uint16(s, WBT_CONTEXT); /* CodecChannelT.blockType */ stream_write_uint32(s, 13); /* CodecChannelT.blockLen */ stream_write_uint8(s, 1); /* CodecChannelT.codecId */ stream_write_uint8(s, 0); /* CodecChannelT.channelId */ stream_write_uint8(s, 0); /* ctxId */ stream_write_uint16(s, CT_TILE_64x64); /* tileSize */ /* properties */ properties = context->flags; /* flags */ properties |= (COL_CONV_ICT << 3); /* cct */ properties |= (CLW_XFORM_DWT_53_A << 5); /* xft */ properties |= ((context->mode == RLGR1 ? CLW_ENTROPY_RLGR1 : CLW_ENTROPY_RLGR3) << 9); /* et */ properties |= (SCALAR_QUANTIZATION << 13); /* qt */ stream_write_uint16(s, properties); /* properties in tilesets: note that this has different format from the one in TS_RFX_CONTEXT */ properties = 1; /* lt */ properties |= (context->flags << 1); /* flags */ properties |= (COL_CONV_ICT << 4); /* cct */ properties |= (CLW_XFORM_DWT_53_A << 6); /* xft */ properties |= ((context->mode == RLGR1 ? CLW_ENTROPY_RLGR1 : CLW_ENTROPY_RLGR3) << 10); /* et */ properties |= (SCALAR_QUANTIZATION << 14); /* qt */ context->properties = properties; } void rfx_compose_message_header(RFX_CONTEXT* context, STREAM* s) { stream_check_size(s, 12 + 10 + 12 + 13); rfx_compose_message_sync(context, s); rfx_compose_message_context(context, s); rfx_compose_message_codec_versions(context, s); rfx_compose_message_channels(context, s); context->header_processed = true; } static void rfx_compose_message_frame_begin(RFX_CONTEXT* context, STREAM* s) { stream_check_size(s, 14); stream_write_uint16(s, WBT_FRAME_BEGIN); /* CodecChannelT.blockType */ stream_write_uint32(s, 14); /* CodecChannelT.blockLen */ stream_write_uint8(s, 1); /* CodecChannelT.codecId */ stream_write_uint8(s, 0); /* CodecChannelT.channelId */ stream_write_uint32(s, context->frame_idx); /* frameIdx */ stream_write_uint16(s, 1); /* numRegions */ context->frame_idx++; } static void rfx_compose_message_region(RFX_CONTEXT* context, STREAM* s, const RFX_RECT* rects, int num_rects) { int size; int i; size = 15 + num_rects * 8; stream_check_size(s, size); stream_write_uint16(s, WBT_REGION); /* CodecChannelT.blockType */ stream_write_uint32(s, size); /* set CodecChannelT.blockLen later */ stream_write_uint8(s, 1); /* CodecChannelT.codecId */ stream_write_uint8(s, 0); /* CodecChannelT.channelId */ stream_write_uint8(s, 1); /* regionFlags */ stream_write_uint16(s, num_rects); /* numRects */ for (i = 0; i < num_rects; i++) { stream_write_uint16(s, rects[i].x); stream_write_uint16(s, rects[i].y); stream_write_uint16(s, rects[i].width); stream_write_uint16(s, rects[i].height); } stream_write_uint16(s, CBT_REGION); /* regionType */ stream_write_uint16(s, 1); /* numTilesets */ } static void rfx_compose_message_tile(RFX_CONTEXT* context, STREAM* s, uint8* tile_data, int tile_width, int tile_height, int rowstride, const uint32* quantVals, int quantIdxY, int quantIdxCb, int quantIdxCr, int xIdx, int yIdx) { int YLen = 0; int CbLen = 0; int CrLen = 0; int start_pos, end_pos; stream_check_size(s, 19); start_pos = stream_get_pos(s); stream_write_uint16(s, CBT_TILE); /* BlockT.blockType */ stream_seek_uint32(s); /* set BlockT.blockLen later */ stream_write_uint8(s, quantIdxY); stream_write_uint8(s, quantIdxCb); stream_write_uint8(s, quantIdxCr); stream_write_uint16(s, xIdx); stream_write_uint16(s, yIdx); stream_seek(s, 6); /* YLen, CbLen, CrLen */ rfx_encode_rgb(context, tile_data, tile_width, tile_height, rowstride, quantVals + quantIdxY * 10, quantVals + quantIdxCb * 10, quantVals + quantIdxCr * 10, s, &YLen, &CbLen, &CrLen); DEBUG_RFX("xIdx=%d yIdx=%d width=%d height=%d YLen=%d CbLen=%d CrLen=%d", xIdx, yIdx, tile_width, tile_height, YLen, CbLen, CrLen); end_pos = stream_get_pos(s); stream_set_pos(s, start_pos + 2); stream_write_uint32(s, 19 + YLen + CbLen + CrLen); /* BlockT.blockLen */ stream_set_pos(s, start_pos + 13); stream_write_uint16(s, YLen); stream_write_uint16(s, CbLen); stream_write_uint16(s, CrLen); stream_set_pos(s, end_pos); } static void rfx_compose_message_tileset(RFX_CONTEXT* context, STREAM* s, uint8* image_data, int width, int height, int rowstride) { int size; int start_pos, end_pos; int i; int numQuants; const uint32* quantVals; const uint32* quantValsPtr; int quantIdxY; int quantIdxCb; int quantIdxCr; int numTiles; int numTilesX; int numTilesY; int xIdx; int yIdx; int tilesDataSize; if (context->num_quants == 0) { numQuants = 1; quantVals = rfx_default_quantization_values; quantIdxY = 0; quantIdxCb = 0; quantIdxCr = 0; } else { numQuants = context->num_quants; quantVals = context->quants; quantIdxY = context->quant_idx_y; quantIdxCb = context->quant_idx_cb; quantIdxCr = context->quant_idx_cr; } numTilesX = (width + 63) / 64; numTilesY = (height + 63) / 64; numTiles = numTilesX * numTilesY; size = 22 + numQuants * 5; stream_check_size(s, size); start_pos = stream_get_pos(s); stream_write_uint16(s, WBT_EXTENSION); /* CodecChannelT.blockType */ stream_seek_uint32(s); /* set CodecChannelT.blockLen later */ stream_write_uint8(s, 1); /* CodecChannelT.codecId */ stream_write_uint8(s, 0); /* CodecChannelT.channelId */ stream_write_uint16(s, CBT_TILESET); /* subtype */ stream_write_uint16(s, 0); /* idx */ stream_write_uint16(s, context->properties); /* properties */ stream_write_uint8(s, numQuants); /* numQuants */ stream_write_uint8(s, 0x40); /* tileSize */ stream_write_uint16(s, numTiles); /* numTiles */ stream_seek_uint32(s); /* set tilesDataSize later */ quantValsPtr = quantVals; for (i = 0; i < numQuants * 5; i++) { stream_write_uint8(s, quantValsPtr[0] + (quantValsPtr[1] << 4)); quantValsPtr += 2; } DEBUG_RFX("width:%d height:%d rowstride:%d", width, height, rowstride); end_pos = stream_get_pos(s); for (yIdx = 0; yIdx < numTilesY; yIdx++) { for (xIdx = 0; xIdx < numTilesX; xIdx++) { rfx_compose_message_tile(context, s, image_data + yIdx * 64 * rowstride + xIdx * 8 * context->bits_per_pixel, (xIdx < numTilesX - 1) ? 64 : width - xIdx * 64, (yIdx < numTilesY - 1) ? 64 : height - yIdx * 64, rowstride, quantVals, quantIdxY, quantIdxCb, quantIdxCr, xIdx, yIdx); } } tilesDataSize = stream_get_pos(s) - end_pos; size += tilesDataSize; end_pos = stream_get_pos(s); stream_set_pos(s, start_pos + 2); stream_write_uint32(s, size); /* CodecChannelT.blockLen */ stream_set_pos(s, start_pos + 18); stream_write_uint32(s, tilesDataSize); stream_set_pos(s, end_pos); } static void rfx_compose_message_frame_end(RFX_CONTEXT* context, STREAM* s) { stream_check_size(s, 8); stream_write_uint16(s, WBT_FRAME_END); /* CodecChannelT.blockType */ stream_write_uint32(s, 8); /* CodecChannelT.blockLen */ stream_write_uint8(s, 1); /* CodecChannelT.codecId */ stream_write_uint8(s, 0); /* CodecChannelT.channelId */ } static void rfx_compose_message_data(RFX_CONTEXT* context, STREAM* s, const RFX_RECT* rects, int num_rects, uint8* image_data, int width, int height, int rowstride) { rfx_compose_message_frame_begin(context, s); rfx_compose_message_region(context, s, rects, num_rects); rfx_compose_message_tileset(context, s, image_data, width, height, rowstride); rfx_compose_message_frame_end(context, s); } FREERDP_API void rfx_compose_message(RFX_CONTEXT* context, STREAM* s, const RFX_RECT* rects, int num_rects, uint8* image_data, int width, int height, int rowstride) { /* Only the first frame should send the RemoteFX header */ if (context->frame_idx == 0 && !context->header_processed) rfx_compose_message_header(context, s); rfx_compose_message_data(context, s, rects, num_rects, image_data, width, height, rowstride); } FreeRDP-1.0.2/libfreerdp-codec/rfx_bitstream.h000066400000000000000000000046161207112532300211570ustar00rootroot00000000000000/** * FreeRDP: A Remote Desktop Protocol client. * RemoteFX Codec Library - Bit Stream * * Copyright 2011 Vic Lee * * 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. */ #ifndef __RFX_BITSTREAM_H #define __RFX_BITSTREAM_H #include struct _RFX_BITSTREAM { uint8* buffer; int nbytes; int byte_pos; int bits_left; }; typedef struct _RFX_BITSTREAM RFX_BITSTREAM; #define rfx_bitstream_attach(bs, _buffer, _nbytes) do { \ bs->buffer = (uint8*) (_buffer); \ bs->nbytes = (_nbytes); \ bs->byte_pos = 0; \ bs->bits_left = 8; } while (0) #define rfx_bitstream_get_bits(bs, _nbits, _r) do { \ int nbits = _nbits; \ int b; \ uint16 n = 0; \ while (bs->byte_pos < bs->nbytes && nbits > 0) \ { \ b = nbits; \ if (b > bs->bits_left) \ b = bs->bits_left; \ if (n) \ n <<= b; \ n |= (bs->buffer[bs->byte_pos] >> (bs->bits_left - b)) & ((1 << b) - 1); \ bs->bits_left -= b; \ nbits -= b; \ if (bs->bits_left == 0) \ { \ bs->bits_left = 8; \ bs->byte_pos++; \ } \ } \ _r = n; } while (0) #define rfx_bitstream_put_bits(bs, _bits, _nbits) do { \ uint16 bits = (_bits); \ int nbits = (_nbits); \ int b; \ while (bs->byte_pos < bs->nbytes && nbits > 0) \ { \ b = nbits; \ if (b > bs->bits_left) \ b = bs->bits_left; \ bs->buffer[bs->byte_pos] &= ~(((1 << b) - 1) << (bs->bits_left - b)); \ bs->buffer[bs->byte_pos] |= ((bits >> (nbits - b)) & ((1 << b) - 1)) << (bs->bits_left - b); \ bs->bits_left -= b; \ nbits -= b; \ if (bs->bits_left == 0) \ { \ bs->bits_left = 8; \ bs->byte_pos++; \ } \ } } while (0) #define rfx_bitstream_eos(_bs) ((_bs)->byte_pos >= (_bs)->nbytes) #define rfx_bitstream_left(_bs) ((_bs)->byte_pos >= (_bs)->nbytes ? 0 : ((_bs)->nbytes - (_bs)->byte_pos - 1) * 8 + (_bs)->bits_left) #define rfx_bitstream_get_processed_bytes(_bs) ((_bs)->bits_left < 8 ? (_bs)->byte_pos + 1 : (_bs)->byte_pos) #endif /* __RFX_BITSTREAM_H */ FreeRDP-1.0.2/libfreerdp-codec/rfx_constants.h000066400000000000000000000027361207112532300212020ustar00rootroot00000000000000/** * FreeRDP: A Remote Desktop Protocol client. * RemoteFX Codec Library - API Header * * Copyright 2011 Vic Lee * * 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. */ #ifndef __RFX_CONSTANTS_H #define __RFX_CONSTANTS_H /* sync */ #define WF_MAGIC 0xCACCACCA #define WF_VERSION_1_0 0x0100 /* blockType */ #define WBT_SYNC 0xCCC0 #define WBT_CODEC_VERSIONS 0xCCC1 #define WBT_CHANNELS 0xCCC2 #define WBT_CONTEXT 0xCCC3 #define WBT_FRAME_BEGIN 0xCCC4 #define WBT_FRAME_END 0xCCC5 #define WBT_REGION 0xCCC6 #define WBT_EXTENSION 0xCCC7 #define CBT_REGION 0xCAC1 #define CBT_TILESET 0xCAC2 #define CBT_TILE 0xCAC3 /* tileSize */ #define CT_TILE_64x64 0x0040 /* properties.flags */ #define CODEC_MODE 0x02 /* properties.cct */ #define COL_CONV_ICT 0x1 /* properties.xft */ #define CLW_XFORM_DWT_53_A 0x1 /* properties.et */ #define CLW_ENTROPY_RLGR1 0x01 #define CLW_ENTROPY_RLGR3 0x04 /* properties.qt */ #define SCALAR_QUANTIZATION 0x1 #endif /* __RFX_CONSTANTS_H */ FreeRDP-1.0.2/libfreerdp-codec/rfx_decode.c000066400000000000000000000135321207112532300204000ustar00rootroot00000000000000/** * FreeRDP: A Remote Desktop Protocol client. * RemoteFX Codec Library - Decode * * Copyright 2011 Vic Lee * Copyright 2011 Norbert Federa * * 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. */ #include #include #include #include #include "rfx_types.h" #include "rfx_rlgr.h" #include "rfx_differential.h" #include "rfx_quantization.h" #include "rfx_dwt.h" #include "rfx_decode.h" static void rfx_decode_format_rgb(sint16* r_buf, sint16* g_buf, sint16* b_buf, RFX_PIXEL_FORMAT pixel_format, uint8* dst_buf) { sint16* r = r_buf; sint16* g = g_buf; sint16* b = b_buf; uint8* dst = dst_buf; int i; switch (pixel_format) { case RFX_PIXEL_FORMAT_BGRA: for (i = 0; i < 4096; i++) { *dst++ = (uint8) (*b++); *dst++ = (uint8) (*g++); *dst++ = (uint8) (*r++); *dst++ = 0xFF; } break; case RFX_PIXEL_FORMAT_RGBA: for (i = 0; i < 4096; i++) { *dst++ = (uint8) (*r++); *dst++ = (uint8) (*g++); *dst++ = (uint8) (*b++); *dst++ = 0xFF; } break; case RFX_PIXEL_FORMAT_BGR: for (i = 0; i < 4096; i++) { *dst++ = (uint8) (*b++); *dst++ = (uint8) (*g++); *dst++ = (uint8) (*r++); } break; case RFX_PIXEL_FORMAT_RGB: for (i = 0; i < 4096; i++) { *dst++ = (uint8) (*r++); *dst++ = (uint8) (*g++); *dst++ = (uint8) (*b++); } break; default: break; } } #define MINMAX(_v,_l,_h) ((_v) < (_l) ? (_l) : ((_v) > (_h) ? (_h) : (_v))) void rfx_decode_ycbcr_to_rgb(sint16* y_r_buf, sint16* cb_g_buf, sint16* cr_b_buf) { /* sint32 is used intentionally because we calculate with shifted factors! */ sint32 y, cb, cr; sint32 r, g, b; int i; /** * The decoded YCbCr coeffectients are represented as 11.5 fixed-point numbers: * * 1 sign bit + 10 integer bits + 5 fractional bits * * However only 7 integer bits will be actually used since the value range is [-128.0, 127.0]. * In other words, the decoded coeffectients is scaled by << 5 when intepreted as sint16. * It was scaled in the quantization phase, so we must scale it back here. */ for (i = 0; i < 4096; i++) { y = y_r_buf[i]; cb = cb_g_buf[i]; cr = cr_b_buf[i]; #if 0 /** * This is the slow floating point version kept here for reference */ y = y + 4096; /* 128<<5=4096 so that we can scale the sum by >> 5 */ r = y + cr*1.403f; g = y - cb*0.344f - cr*0.714f; b = y + cb*1.770f; y_r_buf[i] = MINMAX(r>>5, 0, 255); cb_g_buf[i] = MINMAX(g>>5, 0, 255); cr_b_buf[i] = MINMAX(b>>5, 0, 255); #else /** * We scale the factors by << 16 into 32-bit integers in order to avoid slower * floating point multiplications. Since the final result needs to be scaled * by >> 5 we will extract only the upper 11 bits (>> 21) from the final sum. * Hence we also have to scale the other terms of the sum by << 16. * * R: 1.403 << 16 = 91947 * G: 0.344 << 16 = 22544, 0.714 << 16 = 46792 * B: 1.770 << 16 = 115998 */ y = (y+4096)<<16; r = y + cr*91947; g = y - cb*22544 - cr*46792; b = y + cb*115998; y_r_buf[i] = MINMAX(r>>21, 0, 255); cb_g_buf[i] = MINMAX(g>>21, 0, 255); cr_b_buf[i] = MINMAX(b>>21, 0, 255); #endif } } static void rfx_decode_component(RFX_CONTEXT* context, const uint32* quantization_values, const uint8* data, int size, sint16* buffer) { PROFILER_ENTER(context->priv->prof_rfx_decode_component); PROFILER_ENTER(context->priv->prof_rfx_rlgr_decode); rfx_rlgr_decode(context->mode, data, size, buffer, 4096); PROFILER_EXIT(context->priv->prof_rfx_rlgr_decode); PROFILER_ENTER(context->priv->prof_rfx_differential_decode); rfx_differential_decode(buffer + 4032, 64); PROFILER_EXIT(context->priv->prof_rfx_differential_decode); PROFILER_ENTER(context->priv->prof_rfx_quantization_decode); context->quantization_decode(buffer, quantization_values); PROFILER_EXIT(context->priv->prof_rfx_quantization_decode); PROFILER_ENTER(context->priv->prof_rfx_dwt_2d_decode); context->dwt_2d_decode(buffer, context->priv->dwt_buffer); PROFILER_EXIT(context->priv->prof_rfx_dwt_2d_decode); PROFILER_EXIT(context->priv->prof_rfx_decode_component); } void rfx_decode_rgb(RFX_CONTEXT* context, STREAM* data_in, int y_size, const uint32 * y_quants, int cb_size, const uint32 * cb_quants, int cr_size, const uint32 * cr_quants, uint8* rgb_buffer) { PROFILER_ENTER(context->priv->prof_rfx_decode_rgb); rfx_decode_component(context, y_quants, stream_get_tail(data_in), y_size, context->priv->y_r_buffer); /* YData */ stream_seek(data_in, y_size); rfx_decode_component(context, cb_quants, stream_get_tail(data_in), cb_size, context->priv->cb_g_buffer); /* CbData */ stream_seek(data_in, cb_size); rfx_decode_component(context, cr_quants, stream_get_tail(data_in), cr_size, context->priv->cr_b_buffer); /* CrData */ stream_seek(data_in, cr_size); PROFILER_ENTER(context->priv->prof_rfx_decode_ycbcr_to_rgb); context->decode_ycbcr_to_rgb(context->priv->y_r_buffer, context->priv->cb_g_buffer, context->priv->cr_b_buffer); PROFILER_EXIT(context->priv->prof_rfx_decode_ycbcr_to_rgb); PROFILER_ENTER(context->priv->prof_rfx_decode_format_rgb); rfx_decode_format_rgb(context->priv->y_r_buffer, context->priv->cb_g_buffer, context->priv->cr_b_buffer, context->pixel_format, rgb_buffer); PROFILER_EXIT(context->priv->prof_rfx_decode_format_rgb); PROFILER_EXIT(context->priv->prof_rfx_decode_rgb); } FreeRDP-1.0.2/libfreerdp-codec/rfx_decode.h000066400000000000000000000020531207112532300204010ustar00rootroot00000000000000/** * FreeRDP: A Remote Desktop Protocol client. * RemoteFX Codec Library - Decode * * Copyright 2011 Vic Lee * * 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. */ #ifndef __RFX_DECODE_H #define __RFX_DECODE_H #include void rfx_decode_ycbcr_to_rgb(sint16* y_r_buf, sint16* cb_g_buf, sint16* cr_b_buf); void rfx_decode_rgb(RFX_CONTEXT* context, STREAM* data_in, int y_size, const uint32 * y_quants, int cb_size, const uint32 * cb_quants, int cr_size, const uint32 * cr_quants, uint8* rgb_buffer); #endif /* __RFX_DECODE_H */ FreeRDP-1.0.2/libfreerdp-codec/rfx_differential.c000066400000000000000000000022621207112532300216070ustar00rootroot00000000000000/** * FreeRDP: A Remote Desktop Protocol client. * RemoteFX Codec Library - Differential Encoding * * Copyright 2011 Vic Lee * * 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. */ #include #include #include #include "rfx_differential.h" void rfx_differential_decode(sint16* buffer, int buffer_size) { sint16* src; sint16* dst; for (src = buffer, dst = buffer + 1; buffer_size > 1; src++, dst++, buffer_size--) { *dst += *src; } } void rfx_differential_encode(sint16* buffer, int buffer_size) { sint16 n1, n2; sint16* dst; for (n1 = *buffer, dst = buffer + 1; buffer_size > 1; dst++, buffer_size--) { n2 = *dst; *dst -= n1; n1 = n2; } } FreeRDP-1.0.2/libfreerdp-codec/rfx_differential.h000066400000000000000000000016601207112532300216150ustar00rootroot00000000000000/** * FreeRDP: A Remote Desktop Protocol client. * RemoteFX Codec Library - Differential Encoding * * Copyright 2011 Vic Lee * * 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. */ #ifndef __RFX_DIFFERENTIAL_H #define __RFX_DIFFERENTIAL_H #include void rfx_differential_decode(sint16* buffer, int buffer_size); void rfx_differential_encode(sint16* buffer, int buffer_size); #endif /* __RFX_DIFFERENTIAL_H */ FreeRDP-1.0.2/libfreerdp-codec/rfx_dwt.c000066400000000000000000000123221207112532300177470ustar00rootroot00000000000000/** * FreeRDP: A Remote Desktop Protocol client. * RemoteFX Codec Library - DWT * * Copyright 2011 Vic Lee * * 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. */ #include #include #include #include "rfx_dwt.h" static void rfx_dwt_2d_decode_block(sint16* buffer, sint16* idwt, int subband_width) { sint16 *dst, *l, *h; sint16 *l_dst, *h_dst; sint16 *hl, *lh, *hh, *ll; int total_width; int x, y; int n; total_width = subband_width << 1; /* Inverse DWT in horizontal direction, results in 2 sub-bands in L, H order in tmp buffer idwt. */ /* The 4 sub-bands are stored in HL(0), LH(1), HH(2), LL(3) order. */ /* The lower part L uses LL(3) and HL(0). */ /* The higher part H uses LH(1) and HH(2). */ ll = buffer + subband_width * subband_width * 3; hl = buffer; l_dst = idwt; lh = buffer + subband_width * subband_width; hh = buffer + subband_width * subband_width * 2; h_dst = idwt + subband_width * subband_width * 2; for (y = 0; y < subband_width; y++) { /* Even coefficients */ l_dst[0] = ll[0] - ((hl[0] + hl[0] + 1) >> 1); h_dst[0] = lh[0] - ((hh[0] + hh[0] + 1) >> 1); for (n = 1; n < subband_width; n++) { x = n << 1; l_dst[x] = ll[n] - ((hl[n-1] + hl[n] + 1) >> 1); h_dst[x] = lh[n] - ((hh[n-1] + hh[n] + 1) >> 1); } /* Odd coefficients */ for (n = 0; n < subband_width-1; n++) { x = n << 1; l_dst[x + 1] = (hl[n] << 1) + ((l_dst[x] + l_dst[x + 2]) >> 1); h_dst[x + 1] = (hh[n] << 1) + ((h_dst[x] + h_dst[x + 2]) >> 1); } x = n << 1; l_dst[x + 1] = (hl[n] << 1) + (l_dst[x]); h_dst[x + 1] = (hh[n] << 1) + (h_dst[x]); ll += subband_width; hl += subband_width; l_dst += total_width; lh += subband_width; hh += subband_width; h_dst += total_width; } /* Inverse DWT in vertical direction, results are stored in original buffer. */ for (x = 0; x < total_width; x++) { /* Even coefficients */ for (n = 0; n < subband_width; n++) { y = n << 1; dst = buffer + y * total_width + x; l = idwt + n * total_width + x; h = l + subband_width * total_width; dst[0] = *l - (((n > 0 ? *(h - total_width) : *h) + (*h) + 1) >> 1); } /* Odd coefficients */ for (n = 0; n < subband_width; n++) { y = n << 1; dst = buffer + y * total_width + x; l = idwt + n * total_width + x; h = l + subband_width * total_width; dst[total_width] = (*h << 1) + ((dst[0] + dst[n < subband_width - 1 ? 2 * total_width : 0]) >> 1); } } } void rfx_dwt_2d_decode(sint16* buffer, sint16* dwt_buffer) { rfx_dwt_2d_decode_block(buffer + 3840, dwt_buffer, 8); rfx_dwt_2d_decode_block(buffer + 3072, dwt_buffer, 16); rfx_dwt_2d_decode_block(buffer, dwt_buffer, 32); } static void rfx_dwt_2d_encode_block(sint16* buffer, sint16* dwt, int subband_width) { sint16 *src, *l, *h; sint16 *l_src, *h_src; sint16 *hl, *lh, *hh, *ll; int total_width; int x, y; int n; total_width = subband_width << 1; /* DWT in vertical direction, results in 2 sub-bands in L, H order in tmp buffer dwt. */ for (x = 0; x < total_width; x++) { for (n = 0; n < subband_width; n++) { y = n << 1; l = dwt + n * total_width + x; h = l + subband_width * total_width; src = buffer + y * total_width + x; /* H */ *h = (src[total_width] - ((src[0] + src[n < subband_width - 1 ? 2 * total_width : 0]) >> 1)) >> 1; /* L */ *l = src[0] + (n == 0 ? *h : (*(h - total_width) + *h) >> 1); } } /* DWT in horizontal direction, results in 4 sub-bands in HL(0), LH(1), HH(2), LL(3) order, stored in original buffer. */ /* The lower part L generates LL(3) and HL(0). */ /* The higher part H generates LH(1) and HH(2). */ ll = buffer + subband_width * subband_width * 3; hl = buffer; l_src = dwt; lh = buffer + subband_width * subband_width; hh = buffer + subband_width * subband_width * 2; h_src = dwt + subband_width * subband_width * 2; for (y = 0; y < subband_width; y++) { /* L */ for (n = 0; n < subband_width; n++) { x = n << 1; /* HL */ hl[n] = (l_src[x + 1] - ((l_src[x] + l_src[n < subband_width - 1 ? x + 2 : x]) >> 1)) >> 1; /* LL */ ll[n] = l_src[x] + (n == 0 ? hl[n] : (hl[n - 1] + hl[n]) >> 1); } /* H */ for (n = 0; n < subband_width; n++) { x = n << 1; /* HH */ hh[n] = (h_src[x + 1] - ((h_src[x] + h_src[n < subband_width - 1 ? x + 2 : x]) >> 1)) >> 1; /* LH */ lh[n] = h_src[x] + (n == 0 ? hh[n] : (hh[n - 1] + hh[n]) >> 1); } ll += subband_width; hl += subband_width; l_src += total_width; lh += subband_width; hh += subband_width; h_src += total_width; } } void rfx_dwt_2d_encode(sint16* buffer, sint16* dwt_buffer) { rfx_dwt_2d_encode_block(buffer, dwt_buffer, 32); rfx_dwt_2d_encode_block(buffer + 3072, dwt_buffer, 16); rfx_dwt_2d_encode_block(buffer + 3840, dwt_buffer, 8); } FreeRDP-1.0.2/libfreerdp-codec/rfx_dwt.h000066400000000000000000000015751207112532300177640ustar00rootroot00000000000000/** * FreeRDP: A Remote Desktop Protocol client. * RemoteFX Codec Library - DWT * * Copyright 2011 Vic Lee * * 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. */ #ifndef __RFX_DWT_H #define __RFX_DWT_H #include void rfx_dwt_2d_decode(sint16* buffer, sint16* dwt_buffer); void rfx_dwt_2d_encode(sint16* buffer, sint16* dwt_buffer); #endif /* __RFX_DWT_H */ FreeRDP-1.0.2/libfreerdp-codec/rfx_encode.c000066400000000000000000000206271207112532300204150ustar00rootroot00000000000000/** * FreeRDP: A Remote Desktop Protocol client. * RemoteFX Codec Library - Encode * * Copyright 2011 Vic Lee * Copyright 2011 Norbert Federa * * 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. */ #include #include #include #include "rfx_types.h" #include "rfx_rlgr.h" #include "rfx_differential.h" #include "rfx_quantization.h" #include "rfx_dwt.h" #include "rfx_encode.h" #define MINMAX(_v,_l,_h) ((_v) < (_l) ? (_l) : ((_v) > (_h) ? (_h) : (_v))) static void rfx_encode_format_rgb(const uint8* rgb_data, int width, int height, int rowstride, RFX_PIXEL_FORMAT pixel_format, const uint8* palette, sint16* r_buf, sint16* g_buf, sint16* b_buf) { int x, y; int x_exceed; int y_exceed; const uint8* src; sint16 r, g, b; sint16 *r_last, *g_last, *b_last; x_exceed = 64 - width; y_exceed = 64 - height; for (y = 0; y < height; y++) { src = rgb_data + y * rowstride; switch (pixel_format) { case RFX_PIXEL_FORMAT_BGRA: for (x = 0; x < width; x++) { *b_buf++ = (sint16) (*src++); *g_buf++ = (sint16) (*src++); *r_buf++ = (sint16) (*src++); src++; } break; case RFX_PIXEL_FORMAT_RGBA: for (x = 0; x < width; x++) { *r_buf++ = (sint16) (*src++); *g_buf++ = (sint16) (*src++); *b_buf++ = (sint16) (*src++); src++; } break; case RFX_PIXEL_FORMAT_BGR: for (x = 0; x < width; x++) { *b_buf++ = (sint16) (*src++); *g_buf++ = (sint16) (*src++); *r_buf++ = (sint16) (*src++); } break; case RFX_PIXEL_FORMAT_RGB: for (x = 0; x < width; x++) { *r_buf++ = (sint16) (*src++); *g_buf++ = (sint16) (*src++); *b_buf++ = (sint16) (*src++); } break; case RFX_PIXEL_FORMAT_BGR565_LE: for (x = 0; x < width; x++) { *b_buf++ = (sint16) (((*(src + 1)) & 0xF8) | ((*(src + 1)) >> 5)); *g_buf++ = (sint16) ((((*(src + 1)) & 0x07) << 5) | (((*src) & 0xE0) >> 3)); *r_buf++ = (sint16) ((((*src) & 0x1F) << 3) | (((*src) >> 2) & 0x07)); src += 2; } break; case RFX_PIXEL_FORMAT_RGB565_LE: for (x = 0; x < width; x++) { *r_buf++ = (sint16) (((*(src + 1)) & 0xF8) | ((*(src + 1)) >> 5)); *g_buf++ = (sint16) ((((*(src + 1)) & 0x07) << 5) | (((*src) & 0xE0) >> 3)); *b_buf++ = (sint16) ((((*src) & 0x1F) << 3) | (((*src) >> 2) & 0x07)); src += 2; } break; case RFX_PIXEL_FORMAT_PALETTE4_PLANER: if (!palette) break; for (x = 0; x < width; x++) { int shift; uint8 idx; shift = (7 - (x % 8)); idx = ((*src) >> shift) & 1; idx |= (((*(src + 1)) >> shift) & 1) << 1; idx |= (((*(src + 2)) >> shift) & 1) << 2; idx |= (((*(src + 3)) >> shift) & 1) << 3; idx *= 3; *r_buf++ = (sint16) palette[idx]; *g_buf++ = (sint16) palette[idx + 1]; *b_buf++ = (sint16) palette[idx + 2]; if (shift == 0) src += 4; } break; case RFX_PIXEL_FORMAT_PALETTE8: if (!palette) break; for (x = 0; x < width; x++) { int idx = (*src) * 3; *r_buf++ = (sint16) palette[idx]; *g_buf++ = (sint16) palette[idx + 1]; *b_buf++ = (sint16) palette[idx + 2]; src++; } break; default: break; } /* Fill the horizontal region outside of 64x64 tile size with the right-most pixel for best quality */ if (x_exceed > 0) { r = *(r_buf - 1); g = *(g_buf - 1); b = *(b_buf - 1); for (x = 0; x < x_exceed; x++) { *r_buf++ = r; *g_buf++ = g; *b_buf++ = b; } } } /* Fill the vertical region outside of 64x64 tile size with the last line. */ if (y_exceed > 0) { r_last = r_buf - 64; g_last = g_buf - 64; b_last = b_buf - 64; while (y_exceed > 0) { memcpy(r_buf, r_last, 64 * sizeof(sint16)); memcpy(g_buf, g_last, 64 * sizeof(sint16)); memcpy(b_buf, b_last, 64 * sizeof(sint16)); r_buf += 64; g_buf += 64; b_buf += 64; y_exceed--; } } } void rfx_encode_rgb_to_ycbcr(sint16* y_r_buf, sint16* cb_g_buf, sint16* cr_b_buf) { /* sint32 is used intentionally because we calculate with shifted factors! */ int i; sint32 r, g, b; sint32 y, cb, cr; /** * The encoded YCbCr coefficients are represented as 11.5 fixed-point numbers: * * 1 sign bit + 10 integer bits + 5 fractional bits * * However only 7 integer bits will be actually used since the value range is [-128.0, 127.0]. * In other words, the encoded coefficients is scaled by << 5 when interpreted as sint16. * It will be scaled down to original during the quantization phase. */ for (i = 0; i < 4096; i++) { r = y_r_buf[i]; g = cb_g_buf[i]; b = cr_b_buf[i]; /* * We scale the factors by << 15 into 32-bit integers in order to avoid slower * floating point multiplications. Since the terms need to be scaled by << 5 we * simply scale the final sum by >> 10 * * Y: 0.299000 << 15 = 9798, 0.587000 << 15 = 19235, 0.114000 << 15 = 3735 * Cb: 0.168935 << 15 = 5535, 0.331665 << 15 = 10868, 0.500590 << 15 = 16403 * Cr: 0.499813 << 15 = 16377, 0.418531 << 15 = 13714, 0.081282 << 15 = 2663 */ y = (r * 9798 + g * 19235 + b * 3735) >> 10; cb = (r * -5535 + g * -10868 + b * 16403) >> 10; cr = (r * 16377 + g * -13714 + b * -2663) >> 10; y_r_buf[i] = MINMAX(y - 4096, -4096, 4095); cb_g_buf[i] = MINMAX(cb, -4096, 4095); cr_b_buf[i] = MINMAX(cr, -4096, 4095); } } static void rfx_encode_component(RFX_CONTEXT* context, const uint32* quantization_values, sint16* data, uint8* buffer, int buffer_size, int* size) { PROFILER_ENTER(context->priv->prof_rfx_encode_component); PROFILER_ENTER(context->priv->prof_rfx_dwt_2d_encode); context->dwt_2d_encode(data, context->priv->dwt_buffer); PROFILER_EXIT(context->priv->prof_rfx_dwt_2d_encode); PROFILER_ENTER(context->priv->prof_rfx_quantization_encode); context->quantization_encode(data, quantization_values); PROFILER_EXIT(context->priv->prof_rfx_quantization_encode); PROFILER_ENTER(context->priv->prof_rfx_differential_encode); rfx_differential_encode(data + 4032, 64); PROFILER_EXIT(context->priv->prof_rfx_differential_encode); PROFILER_ENTER(context->priv->prof_rfx_rlgr_encode); *size = rfx_rlgr_encode(context->mode, data, 4096, buffer, buffer_size); PROFILER_EXIT(context->priv->prof_rfx_rlgr_encode); PROFILER_EXIT(context->priv->prof_rfx_encode_component); } void rfx_encode_rgb(RFX_CONTEXT* context, const uint8* rgb_data, int width, int height, int rowstride, const uint32* y_quants, const uint32* cb_quants, const uint32* cr_quants, STREAM* data_out, int* y_size, int* cb_size, int* cr_size) { sint16* y_r_buffer = context->priv->y_r_buffer; sint16* cb_g_buffer = context->priv->cb_g_buffer; sint16* cr_b_buffer = context->priv->cr_b_buffer; PROFILER_ENTER(context->priv->prof_rfx_encode_rgb); PROFILER_ENTER(context->priv->prof_rfx_encode_format_rgb); rfx_encode_format_rgb(rgb_data, width, height, rowstride, context->pixel_format, context->palette, y_r_buffer, cb_g_buffer, cr_b_buffer); PROFILER_EXIT(context->priv->prof_rfx_encode_format_rgb); PROFILER_ENTER(context->priv->prof_rfx_encode_rgb_to_ycbcr); context->encode_rgb_to_ycbcr(context->priv->y_r_buffer, context->priv->cb_g_buffer, context->priv->cr_b_buffer); PROFILER_EXIT(context->priv->prof_rfx_encode_rgb_to_ycbcr); /* Ensure the buffer is reasonably large enough */ stream_check_size(data_out, 4096); rfx_encode_component(context, y_quants, context->priv->y_r_buffer, stream_get_tail(data_out), stream_get_left(data_out), y_size); stream_seek(data_out, *y_size); stream_check_size(data_out, 4096); rfx_encode_component(context, cb_quants, context->priv->cb_g_buffer, stream_get_tail(data_out), stream_get_left(data_out), cb_size); stream_seek(data_out, *cb_size); stream_check_size(data_out, 4096); rfx_encode_component(context, cr_quants, context->priv->cr_b_buffer, stream_get_tail(data_out), stream_get_left(data_out), cr_size); stream_seek(data_out, *cr_size); PROFILER_EXIT(context->priv->prof_rfx_encode_rgb); } FreeRDP-1.0.2/libfreerdp-codec/rfx_encode.h000066400000000000000000000021001207112532300204040ustar00rootroot00000000000000/** * FreeRDP: A Remote Desktop Protocol client. * RemoteFX Codec Library - Encode * * Copyright 2011 Vic Lee * * 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. */ #ifndef __RFX_ENCODE_H #define __RFX_ENCODE_H #include void rfx_encode_rgb_to_ycbcr(sint16* y_r_buf, sint16* cb_g_buf, sint16* cr_b_buf); void rfx_encode_rgb(RFX_CONTEXT* context, const uint8* rgb_data, int width, int height, int rowstride, const uint32* y_quants, const uint32* cb_quants, const uint32* cr_quants, STREAM* data_out, int* y_size, int* cb_size, int* cr_size); #endif FreeRDP-1.0.2/libfreerdp-codec/rfx_neon.c000066400000000000000000000231731207112532300201160ustar00rootroot00000000000000/* FreeRDP: A Remote Desktop Protocol client. RemoteFX Codec Library - NEON Optimizations Copyright 2011 Martin Fleisz 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. */ #if defined(__ARM_NEON__) #include #include #include #include #include "rfx_types.h" #include "rfx_neon.h" #if defined(ANDROID) #include #endif void rfx_decode_YCbCr_to_RGB_NEON(sint16 * y_r_buffer, sint16 * cb_g_buffer, sint16 * cr_b_buffer) { int16x8_t zero = vdupq_n_s16(0); int16x8_t max = vdupq_n_s16(255); int16x8_t y_add = vdupq_n_s16(128); int16x8_t* y_r_buf = (int16x8_t*)y_r_buffer; int16x8_t* cb_g_buf = (int16x8_t*)cb_g_buffer; int16x8_t* cr_b_buf = (int16x8_t*)cr_b_buffer; int i; for (i = 0; i < 4096 / 8; i++) { int16x8_t y = vld1q_s16((sint16*)&y_r_buf[i]); y = vaddq_s16(y, y_add); int16x8_t cr = vld1q_s16((sint16*)&cr_b_buf[i]); // r = between((y + cr + (cr >> 2) + (cr >> 3) + (cr >> 5)), 0, 255); int16x8_t r = vaddq_s16(y, cr); r = vaddq_s16(r, vshrq_n_s16(cr, 2)); r = vaddq_s16(r, vshrq_n_s16(cr, 3)); r = vaddq_s16(r, vshrq_n_s16(cr, 5)); r = vminq_s16(vmaxq_s16(r, zero), max); vst1q_s16((sint16*)&y_r_buf[i], r); // cb = cb_g_buf[i]; int16x8_t cb = vld1q_s16((sint16*)&cb_g_buf[i]); // g = between(y - (cb >> 2) - (cb >> 4) - (cb >> 5) - (cr >> 1) - (cr >> 3) - (cr >> 4) - (cr >> 5), 0, 255); int16x8_t g = vsubq_s16(y, vshrq_n_s16(cb, 2)); g = vsubq_s16(g, vshrq_n_s16(cb, 4)); g = vsubq_s16(g, vshrq_n_s16(cb, 5)); g = vsubq_s16(g, vshrq_n_s16(cr, 1)); g = vsubq_s16(g, vshrq_n_s16(cr, 3)); g = vsubq_s16(g, vshrq_n_s16(cr, 4)); g = vsubq_s16(g, vshrq_n_s16(cr, 5)); g = vminq_s16(vmaxq_s16(g, zero), max); vst1q_s16((sint16*)&cb_g_buf[i], g); // b = between((y + cb + (cb >> 1) + (cb >> 2) + (cb >> 6)), 0, 255); int16x8_t b = vaddq_s16(y, cb); b = vaddq_s16(b, vshrq_n_s16(cb, 1)); b = vaddq_s16(b, vshrq_n_s16(cb, 2)); b = vaddq_s16(b, vshrq_n_s16(cb, 6)); b = vminq_s16(vmaxq_s16(b, zero), max); vst1q_s16((sint16*)&cr_b_buf[i], b); } } static __inline void __attribute__((__gnu_inline__, __always_inline__, __artificial__)) rfx_quantization_decode_block_NEON(sint16 * buffer, const int buffer_size, const uint32 factor) { if (factor <= 6) return; int16x8_t quantFactors = vdupq_n_s16(factor - 6); int16x8_t* buf = (int16x8_t*)buffer; int16x8_t* buf_end = (int16x8_t*)(buffer + buffer_size); do { int16x8_t val = vld1q_s16((sint16*)buf); val = vshlq_s16(val, quantFactors); vst1q_s16((sint16*)buf, val); buf++; } while(buf < buf_end); } void rfx_quantization_decode_NEON(sint16 * buffer, const uint32 * quantization_values) { rfx_quantization_decode_block_NEON(buffer, 1024, quantization_values[8]); /* HL1 */ rfx_quantization_decode_block_NEON(buffer + 1024, 1024, quantization_values[7]); /* LH1 */ rfx_quantization_decode_block_NEON(buffer + 2048, 1024, quantization_values[9]); /* HH1 */ rfx_quantization_decode_block_NEON(buffer + 3072, 256, quantization_values[5]); /* HL2 */ rfx_quantization_decode_block_NEON(buffer + 3328, 256, quantization_values[4]); /* LH2 */ rfx_quantization_decode_block_NEON(buffer + 3584, 256, quantization_values[6]); /* HH2 */ rfx_quantization_decode_block_NEON(buffer + 3840, 64, quantization_values[2]); /* HL3 */ rfx_quantization_decode_block_NEON(buffer + 3904, 64, quantization_values[1]); /* LH3 */ rfx_quantization_decode_block_NEON(buffer + 3968, 64, quantization_values[3]); /* HH3 */ rfx_quantization_decode_block_NEON(buffer + 4032, 64, quantization_values[0]); /* LL3 */ } static __inline void __attribute__((__gnu_inline__, __always_inline__, __artificial__)) rfx_dwt_2d_decode_block_horiz_NEON(sint16 * l, sint16 * h, sint16 * dst, int subband_width) { int y, n; sint16 * l_ptr = l; sint16 * h_ptr = h; sint16 * dst_ptr = dst; for (y = 0; y < subband_width; y++) { /* Even coefficients */ for (n = 0; n < subband_width; n+=8) { // dst[2n] = l[n] - ((h[n-1] + h[n] + 1) >> 1); int16x8_t l_n = vld1q_s16(l_ptr); int16x8_t h_n = vld1q_s16(h_ptr); int16x8_t h_n_m = vld1q_s16(h_ptr - 1); if (n == 0) { int16_t first = vgetq_lane_s16(h_n_m, 1); h_n_m = vsetq_lane_s16(first, h_n_m, 0); } int16x8_t tmp_n = vaddq_s16(h_n, h_n_m); tmp_n = vaddq_s16(tmp_n, vdupq_n_s16(1)); tmp_n = vshrq_n_s16(tmp_n, 1); int16x8_t dst_n = vsubq_s16(l_n, tmp_n); vst1q_s16(l_ptr, dst_n); l_ptr+=8; h_ptr+=8; } l_ptr -= subband_width; h_ptr -= subband_width; /* Odd coefficients */ for (n = 0; n < subband_width; n+=8) { // dst[2n + 1] = (h[n] << 1) + ((dst[2n] + dst[2n + 2]) >> 1); int16x8_t h_n = vld1q_s16(h_ptr); h_n = vshlq_n_s16(h_n, 1); int16x8x2_t dst_n; dst_n.val[0] = vld1q_s16(l_ptr); int16x8_t dst_n_p = vld1q_s16(l_ptr + 1); if (n == subband_width - 8) { int16_t last = vgetq_lane_s16(dst_n_p, 6); dst_n_p = vsetq_lane_s16(last, dst_n_p, 7); } dst_n.val[1] = vaddq_s16(dst_n_p, dst_n.val[0]); dst_n.val[1] = vshrq_n_s16(dst_n.val[1], 1); dst_n.val[1] = vaddq_s16(dst_n.val[1], h_n); vst2q_s16(dst_ptr, dst_n); l_ptr+=8; h_ptr+=8; dst_ptr+=16; } } } static __inline void __attribute__((__gnu_inline__, __always_inline__, __artificial__)) rfx_dwt_2d_decode_block_vert_NEON(sint16 * l, sint16 * h, sint16 * dst, int subband_width) { int x, n; sint16 * l_ptr = l; sint16 * h_ptr = h; sint16 * dst_ptr = dst; int total_width = subband_width + subband_width; /* Even coefficients */ for (n = 0; n < subband_width; n++) { for (x = 0; x < total_width; x+=8) { // dst[2n] = l[n] - ((h[n-1] + h[n] + 1) >> 1); int16x8_t l_n = vld1q_s16(l_ptr); int16x8_t h_n = vld1q_s16(h_ptr); int16x8_t tmp_n = vaddq_s16(h_n, vdupq_n_s16(1));; if (n == 0) tmp_n = vaddq_s16(tmp_n, h_n); else { int16x8_t h_n_m = vld1q_s16((h_ptr - total_width)); tmp_n = vaddq_s16(tmp_n, h_n_m); } tmp_n = vshrq_n_s16(tmp_n, 1); int16x8_t dst_n = vsubq_s16(l_n, tmp_n); vst1q_s16(dst_ptr, dst_n); l_ptr+=8; h_ptr+=8; dst_ptr+=8; } dst_ptr+=total_width; } h_ptr = h; dst_ptr = dst + total_width; /* Odd coefficients */ for (n = 0; n < subband_width; n++) { for (x = 0; x < total_width; x+=8) { // dst[2n + 1] = (h[n] << 1) + ((dst[2n] + dst[2n + 2]) >> 1); int16x8_t h_n = vld1q_s16(h_ptr); int16x8_t dst_n_m = vld1q_s16(dst_ptr - total_width); h_n = vshlq_n_s16(h_n, 1); int16x8_t tmp_n = dst_n_m; if (n == subband_width - 1) tmp_n = vaddq_s16(tmp_n, dst_n_m); else { int16x8_t dst_n_p = vld1q_s16((dst_ptr + total_width)); tmp_n = vaddq_s16(tmp_n, dst_n_p); } tmp_n = vshrq_n_s16(tmp_n, 1); int16x8_t dst_n = vaddq_s16(tmp_n, h_n); vst1q_s16(dst_ptr, dst_n); h_ptr+=8; dst_ptr+=8; } dst_ptr+=total_width; } } static __inline void __attribute__((__gnu_inline__, __always_inline__, __artificial__)) rfx_dwt_2d_decode_block_NEON(sint16 * buffer, sint16 * idwt, int subband_width) { sint16 * hl, * lh, * hh, * ll; sint16 * l_dst, * h_dst; /* Inverse DWT in horizontal direction, results in 2 sub-bands in L, H order in tmp buffer idwt. */ /* The 4 sub-bands are stored in HL(0), LH(1), HH(2), LL(3) order. */ /* The lower part L uses LL(3) and HL(0). */ /* The higher part H uses LH(1) and HH(2). */ ll = buffer + subband_width * subband_width * 3; hl = buffer; l_dst = idwt; rfx_dwt_2d_decode_block_horiz_NEON(ll, hl, l_dst, subband_width); lh = buffer + subband_width * subband_width; hh = buffer + subband_width * subband_width * 2; h_dst = idwt + subband_width * subband_width * 2; rfx_dwt_2d_decode_block_horiz_NEON(lh, hh, h_dst, subband_width); /* Inverse DWT in vertical direction, results are stored in original buffer. */ rfx_dwt_2d_decode_block_vert_NEON(l_dst, h_dst, buffer, subband_width); } void rfx_dwt_2d_decode_NEON(sint16 * buffer, sint16 * dwt_buffer) { rfx_dwt_2d_decode_block_NEON(buffer + 3840, dwt_buffer, 8); rfx_dwt_2d_decode_block_NEON(buffer + 3072, dwt_buffer, 16); rfx_dwt_2d_decode_block_NEON(buffer, dwt_buffer, 32); } int isNeonSupported() { #if defined(ANDROID) if (android_getCpuFamily() != ANDROID_CPU_FAMILY_ARM) { DEBUG_RFX("NEON optimization disabled - No ARM CPU found"); return 0; } uint64_t features = android_getCpuFeatures(); if ((features & ANDROID_CPU_ARM_FEATURE_ARMv7)) { if (features & ANDROID_CPU_ARM_FEATURE_NEON) { DEBUG_RFX("NEON optimization enabled!"); return 1; } DEBUG_RFX("NEON optimization disabled - CPU not NEON capable"); } else DEBUG_RFX("NEON optimization disabled - No ARMv7 CPU found"); return 0; #else return 1; #endif } void rfx_init_neon(RFX_CONTEXT * context) { if(isNeonSupported()) { DEBUG_RFX("Using NEON optimizations"); IF_PROFILER(context->priv->prof_rfx_decode_ycbcr_to_rgb->name = "rfx_decode_YCbCr_to_RGB_NEON"); IF_PROFILER(context->priv->prof_rfx_quantization_decode->name = "rfx_quantization_decode_NEON"); IF_PROFILER(context->priv->prof_rfx_dwt_2d_decode->name = "rfx_dwt_2d_decode_NEON"); context->decode_ycbcr_to_rgb = rfx_decode_YCbCr_to_RGB_NEON; context->quantization_decode = rfx_quantization_decode_NEON; context->dwt_2d_decode = rfx_dwt_2d_decode_NEON; } } #endif // __ARM_NEON__ FreeRDP-1.0.2/libfreerdp-codec/rfx_neon.h000066400000000000000000000020121207112532300201100ustar00rootroot00000000000000/* FreeRDP: A Remote Desktop Protocol client. RemoteFX Codec Library - NEON Optimizations Copyright 2011 Martin Fleisz 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. */ #ifndef __RFX_NEON_H #define __RFX_NEON_H #include #if defined(__ARM_NEON__) void rfx_init_neon(RFX_CONTEXT * context); #ifndef RFX_INIT_SIMD #if defined(WITH_NEON) #define RFX_INIT_SIMD(_rfx_context) rfx_init_neon(_rfx_context) #endif #endif #endif // __ARM_NEON__ #endif /* __RFX_NEON_H */ FreeRDP-1.0.2/libfreerdp-codec/rfx_pool.c000066400000000000000000000041621207112532300201250ustar00rootroot00000000000000/** * FreeRDP: A Remote Desktop Protocol client. * RemoteFX Codec Library - Memory Pool * * Copyright 2011 Marc-Andre Moreau * * 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. */ #include #include #include #include #include "rfx_pool.h" RFX_POOL* rfx_pool_new() { RFX_POOL* pool; pool = xnew(RFX_POOL); pool->size = 64; pool->tiles = (RFX_TILE**) xzalloc(sizeof(RFX_TILE*) * pool->size); return pool; } void rfx_pool_free(RFX_POOL* pool) { int i; RFX_TILE* tile; for (i = 0; i < pool->count; i++) { tile = pool->tiles[i]; if (tile != NULL) { if (tile->data != NULL) xfree(tile->data); xfree(tile); } } xfree(pool->tiles); xfree(pool); } void rfx_pool_put_tile(RFX_POOL* pool, RFX_TILE* tile) { if (pool->count >= pool->size) { pool->size *= 2; pool->tiles = (RFX_TILE**) xrealloc((void*) pool->tiles, sizeof(RFX_TILE*) * pool->size); } pool->tiles[(pool->count)++] = tile; } RFX_TILE* rfx_pool_get_tile(RFX_POOL* pool) { RFX_TILE* tile; if (pool->count < 1) { tile = xnew(RFX_TILE); tile->data = (uint8*) xmalloc(4096 * 4); /* 64x64 * 4 */ } else { tile = pool->tiles[--(pool->count)]; } return tile; } void rfx_pool_put_tiles(RFX_POOL* pool, RFX_TILE** tiles, int count) { int i; for (i = 0; i < count; i++) { rfx_pool_put_tile(pool, tiles[i]); } } RFX_TILE** rfx_pool_get_tiles(RFX_POOL* pool, int count) { int i; RFX_TILE** tiles; tiles = (RFX_TILE**) xmalloc(sizeof(RFX_TILE*) * count); for (i = 0; i < count; i++) { tiles[i] = rfx_pool_get_tile(pool); } return tiles; } FreeRDP-1.0.2/libfreerdp-codec/rfx_pool.h000066400000000000000000000022761207112532300201360ustar00rootroot00000000000000/** * FreeRDP: A Remote Desktop Protocol client. * RemoteFX Codec Library - Memory Pool * * Copyright 2011 Marc-Andre Moreau * * 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. */ #ifndef __RFX_POOL_H #define __RFX_POOL_H #include struct _RFX_POOL { int size; int count; RFX_TILE** tiles; }; typedef struct _RFX_POOL RFX_POOL; RFX_POOL* rfx_pool_new(); void rfx_pool_free(RFX_POOL* pool); void rfx_pool_put_tile(RFX_POOL* pool, RFX_TILE* tile); RFX_TILE* rfx_pool_get_tile(RFX_POOL* pool); void rfx_pool_put_tiles(RFX_POOL* pool, RFX_TILE** tiles, int count); RFX_TILE** rfx_pool_get_tiles(RFX_POOL* pool, int count); #endif /* __RFX_POOL_H */ FreeRDP-1.0.2/libfreerdp-codec/rfx_quantization.c000066400000000000000000000065601207112532300217060ustar00rootroot00000000000000/** * FreeRDP: A Remote Desktop Protocol client. * RemoteFX Codec Library - Quantization * * Copyright 2011 Vic Lee * * 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. */ #include "rfx_quantization.h" static void rfx_quantization_decode_block(sint16* buffer, int buffer_size, uint32 factor) { sint16* dst; if (factor == 0) return; for (dst = buffer; buffer_size > 0; dst++, buffer_size--) { *dst <<= factor; } } void rfx_quantization_decode(sint16* buffer, const uint32* quantization_values) { /* Scale the values so that they are represented as 11.5 fixed-point number */ rfx_quantization_decode_block(buffer, 4096, 5); rfx_quantization_decode_block(buffer, 1024, quantization_values[8] - 6); /* HL1 */ rfx_quantization_decode_block(buffer + 1024, 1024, quantization_values[7] - 6); /* LH1 */ rfx_quantization_decode_block(buffer + 2048, 1024, quantization_values[9] - 6); /* HH1 */ rfx_quantization_decode_block(buffer + 3072, 256, quantization_values[5] - 6); /* HL2 */ rfx_quantization_decode_block(buffer + 3328, 256, quantization_values[4] - 6); /* LH2 */ rfx_quantization_decode_block(buffer + 3584, 256, quantization_values[6] - 6); /* HH2 */ rfx_quantization_decode_block(buffer + 3840, 64, quantization_values[2] - 6); /* HL3 */ rfx_quantization_decode_block(buffer + 3904, 64, quantization_values[1] - 6); /* LH3 */ rfx_quantization_decode_block(buffer + 3968, 64, quantization_values[3] - 6); /* HH3 */ rfx_quantization_decode_block(buffer + 4032, 64, quantization_values[0] - 6); /* LL3 */ } static void rfx_quantization_encode_block(sint16* buffer, int buffer_size, uint32 factor) { sint16* dst; sint16 half; if (factor == 0) return; half = (1 << (factor - 1)); for (dst = buffer; buffer_size > 0; dst++, buffer_size--) { *dst = (*dst + half) >> factor; } } void rfx_quantization_encode(sint16* buffer, const uint32* quantization_values) { rfx_quantization_encode_block(buffer, 1024, quantization_values[8] - 6); /* HL1 */ rfx_quantization_encode_block(buffer + 1024, 1024, quantization_values[7] - 6); /* LH1 */ rfx_quantization_encode_block(buffer + 2048, 1024, quantization_values[9] - 6); /* HH1 */ rfx_quantization_encode_block(buffer + 3072, 256, quantization_values[5] - 6); /* HL2 */ rfx_quantization_encode_block(buffer + 3328, 256, quantization_values[4] - 6); /* LH2 */ rfx_quantization_encode_block(buffer + 3584, 256, quantization_values[6] - 6); /* HH2 */ rfx_quantization_encode_block(buffer + 3840, 64, quantization_values[2] - 6); /* HL3 */ rfx_quantization_encode_block(buffer + 3904, 64, quantization_values[1] - 6); /* LH3 */ rfx_quantization_encode_block(buffer + 3968, 64, quantization_values[3] - 6); /* HH3 */ rfx_quantization_encode_block(buffer + 4032, 64, quantization_values[0] - 6); /* LL3 */ /* The coefficients are scaled by << 5 at RGB->YCbCr phase, so we round it back here */ rfx_quantization_encode_block(buffer, 4096, 5); } FreeRDP-1.0.2/libfreerdp-codec/rfx_quantization.h000066400000000000000000000017131207112532300217060ustar00rootroot00000000000000/** * FreeRDP: A Remote Desktop Protocol client. * RemoteFX Codec Library - Quantization * * Copyright 2011 Vic Lee * * 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. */ #ifndef __RFX_QUANTIZATION_H #define __RFX_QUANTIZATION_H #include void rfx_quantization_decode(sint16* buffer, const uint32* quantization_values); void rfx_quantization_encode(sint16* buffer, const uint32* quantization_values); #endif /* __RFX_QUANTIZATION_H */ FreeRDP-1.0.2/libfreerdp-codec/rfx_rlgr.c000066400000000000000000000235011207112532300201200ustar00rootroot00000000000000/** * FreeRDP: A Remote Desktop Protocol client. * RemoteFX Codec Library - RLGR * * Copyright 2011 Vic Lee * * 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. */ /** * This implementation of RLGR refers to * [MS-RDPRFX] 3.1.8.1.7.3 RLGR1/RLGR3 Pseudocode */ #include #include #include #include #include "rfx_bitstream.h" #include "rfx_rlgr.h" /* Constants used within the RLGR1/RLGR3 algorithm */ #define KPMAX (80) /* max value for kp or krp */ #define LSGR (3) /* shift count to convert kp to k */ #define UP_GR (4) /* increase in kp after a zero run in RL mode */ #define DN_GR (6) /* decrease in kp after a nonzero symbol in RL mode */ #define UQ_GR (3) /* increase in kp after nonzero symbol in GR mode */ #define DQ_GR (3) /* decrease in kp after zero symbol in GR mode */ /* Gets (returns) the next nBits from the bitstream */ #define GetBits(nBits, r) rfx_bitstream_get_bits(bs, nBits, r) /* From current output pointer, write "value", check and update buffer_size */ #define WriteValue(value) \ { \ if (buffer_size > 0) \ *dst++ = (value); \ buffer_size--; \ } /* From current output pointer, write next nZeroes terms with value 0, check and update buffer_size */ #define WriteZeroes(nZeroes) \ { \ int nZeroesWritten = (nZeroes); \ if (nZeroesWritten > buffer_size) \ nZeroesWritten = buffer_size; \ if (nZeroesWritten > 0) \ { \ memset(dst, 0, nZeroesWritten * sizeof(sint16)); \ dst += nZeroesWritten; \ } \ buffer_size -= (nZeroes); \ } /* Returns the least number of bits required to represent a given value */ #define GetMinBits(_val, _nbits) \ { \ uint32 _v = _val; \ _nbits = 0; \ while (_v) \ { \ _v >>= 1; \ _nbits++; \ } \ } /* Converts from (2 * magnitude - sign) to integer */ #define GetIntFrom2MagSign(twoMs) (((twoMs) & 1) ? -1 * (sint16)(((twoMs) + 1) >> 1) : (sint16)((twoMs) >> 1)) /* * Update the passed parameter and clamp it to the range [0, KPMAX] * Return the value of parameter right-shifted by LSGR */ #define UpdateParam(_param, _deltaP, _k) \ { \ _param += _deltaP; \ if (_param > KPMAX) \ _param = KPMAX; \ if (_param < 0) \ _param = 0; \ _k = (_param >> LSGR); \ } /* Outputs the Golomb/Rice encoding of a non-negative integer */ #define GetGRCode(krp, kr, vk, _mag) \ vk = 0; \ _mag = 0; \ /* chew up/count leading 1s and escape 0 */ \ do { \ GetBits(1, r); \ if (r == 1) \ vk++; \ else \ break; \ } while (1); \ /* get next *kr bits, and combine with leading 1s */ \ GetBits(*kr, _mag); \ _mag |= (vk << *kr); \ /* adjust krp and kr based on vk */ \ if (!vk) { \ UpdateParam(*krp, -2, *kr); \ } \ else if (vk != 1) { \ UpdateParam(*krp, vk, *kr); /* at 1, no change! */ \ } int rfx_rlgr_decode(RLGR_MODE mode, const uint8* data, int data_size, sint16* buffer, int buffer_size) { int k; int kp; int kr; int krp; uint16 r; sint16* dst; RFX_BITSTREAM* bs; int vk; uint16 mag16; bs = xnew(RFX_BITSTREAM); rfx_bitstream_attach(bs, data, data_size); dst = buffer; /* initialize the parameters */ k = 1; kp = k << LSGR; kr = 1; krp = kr << LSGR; while (!rfx_bitstream_eos(bs) && buffer_size > 0) { int run; if (k) { int mag; uint32 sign; /* RL MODE */ while (!rfx_bitstream_eos(bs)) { GetBits(1, r); if (r) break; /* we have an RL escape "0", which translates to a run (1< 0) \ { \ _n = *data++; \ data_size--; \ } \ else \ { \ _n = 0; \ } \ } /* Emit bitPattern to the output bitstream */ #define OutputBits(numBits, bitPattern) rfx_bitstream_put_bits(bs, bitPattern, numBits) /* Emit a bit (0 or 1), count number of times, to the output bitstream */ #define OutputBit(count, bit) \ { \ uint16 _b = (bit ? 0xFFFF : 0); \ int _c = (count); \ for (; _c > 0; _c -= 16) \ rfx_bitstream_put_bits(bs, _b, (_c > 16 ? 16 : _c)); \ } /* Converts the input value to (2 * abs(input) - sign(input)), where sign(input) = (input < 0 ? 1 : 0) and returns it */ #define Get2MagSign(input) ((input) >= 0 ? 2 * (input) : -2 * (input) - 1) /* Outputs the Golomb/Rice encoding of a non-negative integer */ #define CodeGR(krp, val) rfx_rlgr_code_gr(bs, krp, val) static void rfx_rlgr_code_gr(RFX_BITSTREAM* bs, int* krp, uint32 val) { int kr = *krp >> LSGR; /* unary part of GR code */ uint32 vk = (val) >> kr; OutputBit(vk, 1); OutputBit(1, 0); /* remainder part of GR code, if needed */ if (kr) { OutputBits(kr, val & ((1 << kr) - 1)); } /* update krp, only if it is not equal to 1 */ if (vk == 0) { UpdateParam(*krp, -2, kr); } else if (vk > 1) { UpdateParam(*krp, vk, kr); } } int rfx_rlgr_encode(RLGR_MODE mode, const sint16* data, int data_size, uint8* buffer, int buffer_size) { int k; int kp; int krp; RFX_BITSTREAM* bs; int processed_size; bs = xnew(RFX_BITSTREAM); rfx_bitstream_attach(bs, buffer, buffer_size); /* initialize the parameters */ k = 1; kp = 1 << LSGR; krp = 1 << LSGR; /* process all the input coefficients */ while (data_size > 0) { int input; if (k) { int numZeros; int runmax; int mag; int sign; /* RUN-LENGTH MODE */ /* collect the run of zeros in the input stream */ numZeros = 0; GetNextInput(input); while (input == 0 && data_size > 0) { numZeros++; GetNextInput(input); } // emit output zeros runmax = 1 << k; while (numZeros >= runmax) { OutputBit(1, 0); /* output a zero bit */ numZeros -= runmax; UpdateParam(kp, UP_GR, k); /* update kp, k */ runmax = 1 << k; } /* output a 1 to terminate runs */ OutputBit(1, 1); /* output the remaining run length using k bits */ OutputBits(k, numZeros); /* note: when we reach here and the last byte being encoded is 0, we still need to output the last two bits, otherwise mstsc will crash */ /* encode the nonzero value using GR coding */ mag = (input < 0 ? -input : input); /* absolute value of input coefficient */ sign = (input < 0 ? 1 : 0); /* sign of input coefficient */ OutputBit(1, sign); /* output the sign bit */ CodeGR(&krp, mag ? mag - 1 : 0); /* output GR code for (mag - 1) */ UpdateParam(kp, -DN_GR, k); } else { /* GOLOMB-RICE MODE */ if (mode == RLGR1) { uint32 twoMs; /* RLGR1 variant */ /* convert input to (2*magnitude - sign), encode using GR code */ GetNextInput(input); twoMs = Get2MagSign(input); CodeGR(&krp, twoMs); /* update k, kp */ /* NOTE: as of Aug 2011, the algorithm is still wrongly documented and the update direction is reversed */ if (twoMs) { UpdateParam(kp, -DQ_GR, k); } else { UpdateParam(kp, UQ_GR, k); } } else /* mode == RLGR3 */ { uint32 twoMs1; uint32 twoMs2; uint32 sum2Ms; uint32 nIdx; /* RLGR3 variant */ /* convert the next two input values to (2*magnitude - sign) and */ /* encode their sum using GR code */ GetNextInput(input); twoMs1 = Get2MagSign(input); GetNextInput(input); twoMs2 = Get2MagSign(input); sum2Ms = twoMs1 + twoMs2; CodeGR(&krp, sum2Ms); /* encode binary representation of the first input (twoMs1). */ GetMinBits(sum2Ms, nIdx); OutputBits(nIdx, twoMs1); /* update k,kp for the two input values */ if (twoMs1 && twoMs2) { UpdateParam(kp, -2 * DQ_GR, k); } else if (!twoMs1 && !twoMs2) { UpdateParam(kp, 2 * UQ_GR, k); } } } } processed_size = rfx_bitstream_get_processed_bytes(bs); xfree(bs); return processed_size; } FreeRDP-1.0.2/libfreerdp-codec/rfx_rlgr.h000066400000000000000000000017311207112532300201260ustar00rootroot00000000000000/** * FreeRDP: A Remote Desktop Protocol client. * RemoteFX Codec Library - RLGR * * Copyright 2011 Vic Lee * * 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. */ #ifndef __RFX_RLGR_H #define __RFX_RLGR_H #include int rfx_rlgr_decode(RLGR_MODE mode, const uint8* data, int data_size, sint16* buffer, int buffer_size); int rfx_rlgr_encode(RLGR_MODE mode, const sint16* data, int data_size, uint8* buffer, int buffer_size); #endif /* __RFX_RLGR_H */ FreeRDP-1.0.2/libfreerdp-codec/rfx_sse2.c000066400000000000000000000514341207112532300200340ustar00rootroot00000000000000/** * FreeRDP: A Remote Desktop Protocol client. * RemoteFX Codec Library - SSE2 Optimizations * * Copyright 2011 Stephen Erisman * Copyright 2011 Norbert Federa * * 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. */ #include #include #include #include #include #include "rfx_types.h" #include "rfx_sse2.h" #ifdef _MSC_VER #define __attribute__(...) #endif #define CACHE_LINE_BYTES 64 #define _mm_between_epi16(_val, _min, _max) \ do { _val = _mm_min_epi16(_max, _mm_max_epi16(_val, _min)); } while (0) static __inline void __attribute__((__gnu_inline__, __always_inline__, __artificial__)) _mm_prefetch_buffer(char * buffer, int num_bytes) { __m128i * buf = (__m128i*) buffer; int i; for (i = 0; i < (num_bytes / sizeof(__m128i)); i+=(CACHE_LINE_BYTES / sizeof(__m128i))) { _mm_prefetch((char*)(&buf[i]), _MM_HINT_NTA); } } static void rfx_decode_ycbcr_to_rgb_sse2(sint16* y_r_buffer, sint16* cb_g_buffer, sint16* cr_b_buffer) { __m128i zero = _mm_setzero_si128(); __m128i max = _mm_set1_epi16(255); __m128i* y_r_buf = (__m128i*) y_r_buffer; __m128i* cb_g_buf = (__m128i*) cb_g_buffer; __m128i* cr_b_buf = (__m128i*) cr_b_buffer; __m128i y; __m128i cr; __m128i cb; __m128i r; __m128i g; __m128i b; int i; __m128i r_cr = _mm_set1_epi16(22986); // 1.403 << 14 __m128i g_cb = _mm_set1_epi16(-5636); // -0.344 << 14 __m128i g_cr = _mm_set1_epi16(-11698); // -0.714 << 14 __m128i b_cb = _mm_set1_epi16(28999); // 1.770 << 14 __m128i c4096 = _mm_set1_epi16(4096); for (i = 0; i < (4096 * sizeof(sint16) / sizeof(__m128i)); i += (CACHE_LINE_BYTES / sizeof(__m128i))) { _mm_prefetch((char*)(&y_r_buf[i]), _MM_HINT_NTA); _mm_prefetch((char*)(&cb_g_buf[i]), _MM_HINT_NTA); _mm_prefetch((char*)(&cr_b_buf[i]), _MM_HINT_NTA); } for (i = 0; i < (4096 * sizeof(sint16) / sizeof(__m128i)); i++) { /* In order to use SSE2 signed 16-bit integer multiplication we need to convert the floating point factors to signed int without loosing information. The result of this multiplication is 32 bit and we have two SSE instructions that return either the hi or lo word. Thus we will multiply the factors by the highest possible 2^n, take the upper 16 bits of the signed 32-bit result (_mm_mulhi_epi16) and correct this result by multiplying it by 2^(16-n). For the given factors in the conversion matrix the best possible n is 14. Example for calculating r: r = (y>>5) + 128 + (cr*1.403)>>5 // our base formula r = (y>>5) + 128 + (HIWORD(cr*(1.403<<14)<<2))>>5 // see above r = (y+4096)>>5 + (HIWORD(cr*22986)<<2)>>5 // simplification r = ((y+4096)>>2 + HIWORD(cr*22986)) >> 3 */ /* y = (y_r_buf[i] + 4096) >> 2 */ y = _mm_load_si128(&y_r_buf[i]); y = _mm_add_epi16(y, c4096); y = _mm_srai_epi16(y, 2); /* cb = cb_g_buf[i]; */ cb = _mm_load_si128(&cb_g_buf[i]); /* cr = cr_b_buf[i]; */ cr = _mm_load_si128(&cr_b_buf[i]); /* (y + HIWORD(cr*22986)) >> 3 */ r = _mm_add_epi16(y, _mm_mulhi_epi16(cr, r_cr)); r = _mm_srai_epi16(r, 3); /* y_r_buf[i] = MINMAX(r, 0, 255); */ _mm_between_epi16(r, zero, max); _mm_store_si128(&y_r_buf[i], r); /* (y + HIWORD(cb*-5636) + HIWORD(cr*-11698)) >> 3 */ g = _mm_add_epi16(y, _mm_mulhi_epi16(cb, g_cb)); g = _mm_add_epi16(g, _mm_mulhi_epi16(cr, g_cr)); g = _mm_srai_epi16(g, 3); /* cb_g_buf[i] = MINMAX(g, 0, 255); */ _mm_between_epi16(g, zero, max); _mm_store_si128(&cb_g_buf[i], g); /* (y + HIWORD(cb*28999)) >> 3 */ b = _mm_add_epi16(y, _mm_mulhi_epi16(cb, b_cb)); b = _mm_srai_epi16(b, 3); /* cr_b_buf[i] = MINMAX(b, 0, 255); */ _mm_between_epi16(b, zero, max); _mm_store_si128(&cr_b_buf[i], b); } } /* The encodec YCbCr coeffectients are represented as 11.5 fixed-point numbers. See rfx_encode.c */ static void rfx_encode_rgb_to_ycbcr_sse2(sint16* y_r_buffer, sint16* cb_g_buffer, sint16* cr_b_buffer) { __m128i min = _mm_set1_epi16(-128 << 5); __m128i max = _mm_set1_epi16(127 << 5); __m128i* y_r_buf = (__m128i*) y_r_buffer; __m128i* cb_g_buf = (__m128i*) cb_g_buffer; __m128i* cr_b_buf = (__m128i*) cr_b_buffer; __m128i y; __m128i cr; __m128i cb; __m128i r; __m128i g; __m128i b; __m128i y_r = _mm_set1_epi16(9798); // 0.299000 << 15 __m128i y_g = _mm_set1_epi16(19235); // 0.587000 << 15 __m128i y_b = _mm_set1_epi16(3735); // 0.114000 << 15 __m128i cb_r = _mm_set1_epi16(-5535); // -0.168935 << 15 __m128i cb_g = _mm_set1_epi16(-10868); // -0.331665 << 15 __m128i cb_b = _mm_set1_epi16(16403); // 0.500590 << 15 __m128i cr_r = _mm_set1_epi16(16377); // 0.499813 << 15 __m128i cr_g = _mm_set1_epi16(-13714); // -0.418531 << 15 __m128i cr_b = _mm_set1_epi16(-2663); // -0.081282 << 15 int i; for (i = 0; i < (4096 * sizeof(sint16) / sizeof(__m128i)); i += (CACHE_LINE_BYTES / sizeof(__m128i))) { _mm_prefetch((char*)(&y_r_buf[i]), _MM_HINT_NTA); _mm_prefetch((char*)(&cb_g_buf[i]), _MM_HINT_NTA); _mm_prefetch((char*)(&cr_b_buf[i]), _MM_HINT_NTA); } for (i = 0; i < (4096 * sizeof(sint16) / sizeof(__m128i)); i++) { /* In order to use SSE2 signed 16-bit integer multiplication we need to convert the floating point factors to signed int without loosing information. The result of this multiplication is 32 bit and using SSE2 we get either the product's hi or lo word. Thus we will multiply the factors by the highest possible 2^n and take the upper 16 bits of the signed 32-bit result (_mm_mulhi_epi16). Since the final result needs to be scaled by << 5 and also in in order to keep the precision within the upper 16 bits we will also have to scale the RGB values used in the multiplication by << 5+(16-n). */ /* r = y_r_buf[i]; */ r = _mm_load_si128(&y_r_buf[i]); /* g = cb_g_buf[i]; */ g = _mm_load_si128(&cb_g_buf[i]); /* b = cr_b_buf[i]; */ b = _mm_load_si128(&cr_b_buf[i]); /* r<<6; g<<6; b<<6 */ r = _mm_slli_epi16(r, 6); g = _mm_slli_epi16(g, 6); b = _mm_slli_epi16(b, 6); /* y = HIWORD(r*y_r) + HIWORD(g*y_g) + HIWORD(b*y_b) + min */ y = _mm_mulhi_epi16(r, y_r); y = _mm_add_epi16(y, _mm_mulhi_epi16(g, y_g)); y = _mm_add_epi16(y, _mm_mulhi_epi16(b, y_b)); y = _mm_add_epi16(y, min); /* y_r_buf[i] = MINMAX(y, 0, (255 << 5)) - (128 << 5); */ _mm_between_epi16(y, min, max); _mm_store_si128(&y_r_buf[i], y); /* cb = HIWORD(r*cb_r) + HIWORD(g*cb_g) + HIWORD(b*cb_b) */ cb = _mm_mulhi_epi16(r, cb_r); cb = _mm_add_epi16(cb, _mm_mulhi_epi16(g, cb_g)); cb = _mm_add_epi16(cb, _mm_mulhi_epi16(b, cb_b)); /* cb_g_buf[i] = MINMAX(cb, (-128 << 5), (127 << 5)); */ _mm_between_epi16(cb, min, max); _mm_store_si128(&cb_g_buf[i], cb); /* cr = HIWORD(r*cr_r) + HIWORD(g*cr_g) + HIWORD(b*cr_b) */ cr = _mm_mulhi_epi16(r, cr_r); cr = _mm_add_epi16(cr, _mm_mulhi_epi16(g, cr_g)); cr = _mm_add_epi16(cr, _mm_mulhi_epi16(b, cr_b)); /* cr_b_buf[i] = MINMAX(cr, (-128 << 5), (127 << 5)); */ _mm_between_epi16(cr, min, max); _mm_store_si128(&cr_b_buf[i], cr); } } static __inline void __attribute__((__gnu_inline__, __always_inline__, __artificial__)) rfx_quantization_decode_block_sse2(sint16* buffer, const int buffer_size, const uint32 factor) { __m128i a; __m128i * ptr = (__m128i*) buffer; __m128i * buf_end = (__m128i*) (buffer + buffer_size); if (factor == 0) return; do { a = _mm_load_si128(ptr); a = _mm_slli_epi16(a, factor); _mm_store_si128(ptr, a); ptr++; } while(ptr < buf_end); } static void rfx_quantization_decode_sse2(sint16* buffer, const uint32* quantization_values) { _mm_prefetch_buffer((char*) buffer, 4096 * sizeof(sint16)); rfx_quantization_decode_block_sse2(buffer, 4096, 5); rfx_quantization_decode_block_sse2(buffer, 1024, quantization_values[8] - 6); /* HL1 */ rfx_quantization_decode_block_sse2(buffer + 1024, 1024, quantization_values[7] - 6); /* LH1 */ rfx_quantization_decode_block_sse2(buffer + 2048, 1024, quantization_values[9] - 6); /* HH1 */ rfx_quantization_decode_block_sse2(buffer + 3072, 256, quantization_values[5] - 6); /* HL2 */ rfx_quantization_decode_block_sse2(buffer + 3328, 256, quantization_values[4] - 6); /* LH2 */ rfx_quantization_decode_block_sse2(buffer + 3584, 256, quantization_values[6] - 6); /* HH2 */ rfx_quantization_decode_block_sse2(buffer + 3840, 64, quantization_values[2] - 6); /* HL3 */ rfx_quantization_decode_block_sse2(buffer + 3904, 64, quantization_values[1] - 6); /* LH3 */ rfx_quantization_decode_block_sse2(buffer + 3968, 64, quantization_values[3] - 6); /* HH3 */ rfx_quantization_decode_block_sse2(buffer + 4032, 64, quantization_values[0] - 6); /* LL3 */ } static __inline void __attribute__((__gnu_inline__, __always_inline__, __artificial__)) rfx_quantization_encode_block_sse2(sint16* buffer, const int buffer_size, const uint32 factor) { __m128i a; __m128i* ptr = (__m128i*) buffer; __m128i* buf_end = (__m128i*) (buffer + buffer_size); __m128i half; if (factor == 0) return; half = _mm_set1_epi16(1 << (factor - 1)); do { a = _mm_load_si128(ptr); a = _mm_add_epi16(a, half); a = _mm_srai_epi16(a, factor); _mm_store_si128(ptr, a); ptr++; } while(ptr < buf_end); } static void rfx_quantization_encode_sse2(sint16* buffer, const uint32* quantization_values) { _mm_prefetch_buffer((char*) buffer, 4096 * sizeof(sint16)); rfx_quantization_encode_block_sse2(buffer, 1024, quantization_values[8] - 6); /* HL1 */ rfx_quantization_encode_block_sse2(buffer + 1024, 1024, quantization_values[7] - 6); /* LH1 */ rfx_quantization_encode_block_sse2(buffer + 2048, 1024, quantization_values[9] - 6); /* HH1 */ rfx_quantization_encode_block_sse2(buffer + 3072, 256, quantization_values[5] - 6); /* HL2 */ rfx_quantization_encode_block_sse2(buffer + 3328, 256, quantization_values[4] - 6); /* LH2 */ rfx_quantization_encode_block_sse2(buffer + 3584, 256, quantization_values[6] - 6); /* HH2 */ rfx_quantization_encode_block_sse2(buffer + 3840, 64, quantization_values[2] - 6); /* HL3 */ rfx_quantization_encode_block_sse2(buffer + 3904, 64, quantization_values[1] - 6); /* LH3 */ rfx_quantization_encode_block_sse2(buffer + 3968, 64, quantization_values[3] - 6); /* HH3 */ rfx_quantization_encode_block_sse2(buffer + 4032, 64, quantization_values[0] - 6); /* LL3 */ rfx_quantization_encode_block_sse2(buffer, 4096, 5); } static __inline void __attribute__((__gnu_inline__, __always_inline__, __artificial__)) rfx_dwt_2d_decode_block_horiz_sse2(sint16* l, sint16* h, sint16* dst, int subband_width) { int y, n; sint16* l_ptr = l; sint16* h_ptr = h; sint16* dst_ptr = dst; int first; int last; __m128i l_n; __m128i h_n; __m128i h_n_m; __m128i tmp_n; __m128i dst_n; __m128i dst_n_p; __m128i dst1; __m128i dst2; for (y = 0; y < subband_width; y++) { /* Even coefficients */ for (n = 0; n < subband_width; n+=8) { /* dst[2n] = l[n] - ((h[n-1] + h[n] + 1) >> 1); */ l_n = _mm_load_si128((__m128i*) l_ptr); h_n = _mm_load_si128((__m128i*) h_ptr); h_n_m = _mm_loadu_si128((__m128i*) (h_ptr - 1)); if (n == 0) { first = _mm_extract_epi16(h_n_m, 1); h_n_m = _mm_insert_epi16(h_n_m, first, 0); } tmp_n = _mm_add_epi16(h_n, h_n_m); tmp_n = _mm_add_epi16(tmp_n, _mm_set1_epi16(1)); tmp_n = _mm_srai_epi16(tmp_n, 1); dst_n = _mm_sub_epi16(l_n, tmp_n); _mm_store_si128((__m128i*) l_ptr, dst_n); l_ptr+=8; h_ptr+=8; } l_ptr -= subband_width; h_ptr -= subband_width; /* Odd coefficients */ for (n = 0; n < subband_width; n+=8) { /* dst[2n + 1] = (h[n] << 1) + ((dst[2n] + dst[2n + 2]) >> 1); */ h_n = _mm_load_si128((__m128i*) h_ptr); h_n = _mm_slli_epi16(h_n, 1); dst_n = _mm_load_si128((__m128i*) (l_ptr)); dst_n_p = _mm_loadu_si128((__m128i*) (l_ptr + 1)); if (n == subband_width - 8) { last = _mm_extract_epi16(dst_n_p, 6); dst_n_p = _mm_insert_epi16(dst_n_p, last, 7); } tmp_n = _mm_add_epi16(dst_n_p, dst_n); tmp_n = _mm_srai_epi16(tmp_n, 1); tmp_n = _mm_add_epi16(tmp_n, h_n); dst1 = _mm_unpacklo_epi16(dst_n, tmp_n); dst2 = _mm_unpackhi_epi16(dst_n, tmp_n); _mm_store_si128((__m128i*) dst_ptr, dst1); _mm_store_si128((__m128i*) (dst_ptr + 8), dst2); l_ptr+=8; h_ptr+=8; dst_ptr+=16; } } } static __inline void __attribute__((__gnu_inline__, __always_inline__, __artificial__)) rfx_dwt_2d_decode_block_vert_sse2(sint16* l, sint16* h, sint16* dst, int subband_width) { int x, n; sint16* l_ptr = l; sint16* h_ptr = h; sint16* dst_ptr = dst; __m128i l_n; __m128i h_n; __m128i tmp_n; __m128i h_n_m; __m128i dst_n; __m128i dst_n_m; __m128i dst_n_p; int total_width = subband_width + subband_width; /* Even coefficients */ for (n = 0; n < subband_width; n++) { for (x = 0; x < total_width; x+=8) { /* dst[2n] = l[n] - ((h[n-1] + h[n] + 1) >> 1); */ l_n = _mm_load_si128((__m128i*) l_ptr); h_n = _mm_load_si128((__m128i*) h_ptr); tmp_n = _mm_add_epi16(h_n, _mm_set1_epi16(1));; if (n == 0) tmp_n = _mm_add_epi16(tmp_n, h_n); else { h_n_m = _mm_loadu_si128((__m128i*) (h_ptr - total_width)); tmp_n = _mm_add_epi16(tmp_n, h_n_m); } tmp_n = _mm_srai_epi16(tmp_n, 1); dst_n = _mm_sub_epi16(l_n, tmp_n); _mm_store_si128((__m128i*) dst_ptr, dst_n); l_ptr+=8; h_ptr+=8; dst_ptr+=8; } dst_ptr+=total_width; } h_ptr = h; dst_ptr = dst + total_width; /* Odd coefficients */ for (n = 0; n < subband_width; n++) { for (x = 0; x < total_width; x+=8) { /* dst[2n + 1] = (h[n] << 1) + ((dst[2n] + dst[2n + 2]) >> 1); */ h_n = _mm_load_si128((__m128i*) h_ptr); dst_n_m = _mm_load_si128((__m128i*) (dst_ptr - total_width)); h_n = _mm_slli_epi16(h_n, 1); tmp_n = dst_n_m; if (n == subband_width - 1) tmp_n = _mm_add_epi16(tmp_n, dst_n_m); else { dst_n_p = _mm_loadu_si128((__m128i*) (dst_ptr + total_width)); tmp_n = _mm_add_epi16(tmp_n, dst_n_p); } tmp_n = _mm_srai_epi16(tmp_n, 1); dst_n = _mm_add_epi16(tmp_n, h_n); _mm_store_si128((__m128i*) dst_ptr, dst_n); h_ptr+=8; dst_ptr+=8; } dst_ptr+=total_width; } } static __inline void __attribute__((__gnu_inline__, __always_inline__, __artificial__)) rfx_dwt_2d_decode_block_sse2(sint16* buffer, sint16* idwt, int subband_width) { sint16 *hl, *lh, *hh, *ll; sint16 *l_dst, *h_dst; _mm_prefetch_buffer((char*) idwt, subband_width * 4 * sizeof(sint16)); /* Inverse DWT in horizontal direction, results in 2 sub-bands in L, H order in tmp buffer idwt. */ /* The 4 sub-bands are stored in HL(0), LH(1), HH(2), LL(3) order. */ /* The lower part L uses LL(3) and HL(0). */ /* The higher part H uses LH(1) and HH(2). */ ll = buffer + subband_width * subband_width * 3; hl = buffer; l_dst = idwt; rfx_dwt_2d_decode_block_horiz_sse2(ll, hl, l_dst, subband_width); lh = buffer + subband_width * subband_width; hh = buffer + subband_width * subband_width * 2; h_dst = idwt + subband_width * subband_width * 2; rfx_dwt_2d_decode_block_horiz_sse2(lh, hh, h_dst, subband_width); /* Inverse DWT in vertical direction, results are stored in original buffer. */ rfx_dwt_2d_decode_block_vert_sse2(l_dst, h_dst, buffer, subband_width); } static void rfx_dwt_2d_decode_sse2(sint16* buffer, sint16* dwt_buffer) { _mm_prefetch_buffer((char*) buffer, 4096 * sizeof(sint16)); rfx_dwt_2d_decode_block_sse2(buffer + 3840, dwt_buffer, 8); rfx_dwt_2d_decode_block_sse2(buffer + 3072, dwt_buffer, 16); rfx_dwt_2d_decode_block_sse2(buffer, dwt_buffer, 32); } static __inline void __attribute__((__gnu_inline__, __always_inline__, __artificial__)) rfx_dwt_2d_encode_block_vert_sse2(sint16* src, sint16* l, sint16* h, int subband_width) { int total_width; int x; int n; __m128i src_2n; __m128i src_2n_1; __m128i src_2n_2; __m128i h_n; __m128i h_n_m; __m128i l_n; total_width = subband_width << 1; for (n = 0; n < subband_width; n++) { for (x = 0; x < total_width; x += 8) { src_2n = _mm_load_si128((__m128i*) src); src_2n_1 = _mm_load_si128((__m128i*) (src + total_width)); if (n < subband_width - 1) src_2n_2 = _mm_load_si128((__m128i*) (src + 2 * total_width)); else src_2n_2 = src_2n; /* h[n] = (src[2n + 1] - ((src[2n] + src[2n + 2]) >> 1)) >> 1 */ h_n = _mm_add_epi16(src_2n, src_2n_2); h_n = _mm_srai_epi16(h_n, 1); h_n = _mm_sub_epi16(src_2n_1, h_n); h_n = _mm_srai_epi16(h_n, 1); _mm_store_si128((__m128i*) h, h_n); if (n == 0) h_n_m = h_n; else h_n_m = _mm_load_si128((__m128i*) (h - total_width)); /* l[n] = src[2n] + ((h[n - 1] + h[n]) >> 1) */ l_n = _mm_add_epi16(h_n_m, h_n); l_n = _mm_srai_epi16(l_n, 1); l_n = _mm_add_epi16(l_n, src_2n); _mm_store_si128((__m128i*) l, l_n); src += 8; l += 8; h += 8; } src += total_width; } } static __inline void __attribute__((__gnu_inline__, __always_inline__, __artificial__)) rfx_dwt_2d_encode_block_horiz_sse2(sint16* src, sint16* l, sint16* h, int subband_width) { int y; int n; int first; __m128i src_2n; __m128i src_2n_1; __m128i src_2n_2; __m128i h_n; __m128i h_n_m; __m128i l_n; for (y = 0; y < subband_width; y++) { for (n = 0; n < subband_width; n += 8) { /* The following 3 Set operations consumes more than half of the total DWT processing time! */ src_2n = _mm_set_epi16(src[14], src[12], src[10], src[8], src[6], src[4], src[2], src[0]); src_2n_1 = _mm_set_epi16(src[15], src[13], src[11], src[9], src[7], src[5], src[3], src[1]); src_2n_2 = _mm_set_epi16(n == subband_width - 8 ? src[14] : src[16], src[14], src[12], src[10], src[8], src[6], src[4], src[2]); /* h[n] = (src[2n + 1] - ((src[2n] + src[2n + 2]) >> 1)) >> 1 */ h_n = _mm_add_epi16(src_2n, src_2n_2); h_n = _mm_srai_epi16(h_n, 1); h_n = _mm_sub_epi16(src_2n_1, h_n); h_n = _mm_srai_epi16(h_n, 1); _mm_store_si128((__m128i*) h, h_n); h_n_m = _mm_loadu_si128((__m128i*) (h - 1)); if (n == 0) { first = _mm_extract_epi16(h_n_m, 1); h_n_m = _mm_insert_epi16(h_n_m, first, 0); } /* l[n] = src[2n] + ((h[n - 1] + h[n]) >> 1) */ l_n = _mm_add_epi16(h_n_m, h_n); l_n = _mm_srai_epi16(l_n, 1); l_n = _mm_add_epi16(l_n, src_2n); _mm_store_si128((__m128i*) l, l_n); src += 16; l += 8; h += 8; } } } static __inline void __attribute__((__gnu_inline__, __always_inline__, __artificial__)) rfx_dwt_2d_encode_block_sse2(sint16* buffer, sint16* dwt, int subband_width) { sint16 *hl, *lh, *hh, *ll; sint16 *l_src, *h_src; _mm_prefetch_buffer((char*) dwt, subband_width * 4 * sizeof(sint16)); /* DWT in vertical direction, results in 2 sub-bands in L, H order in tmp buffer dwt. */ l_src = dwt; h_src = dwt + subband_width * subband_width * 2; rfx_dwt_2d_encode_block_vert_sse2(buffer, l_src, h_src, subband_width); /* DWT in horizontal direction, results in 4 sub-bands in HL(0), LH(1), HH(2), LL(3) order, stored in original buffer. */ /* The lower part L generates LL(3) and HL(0). */ /* The higher part H generates LH(1) and HH(2). */ ll = buffer + subband_width * subband_width * 3; hl = buffer; lh = buffer + subband_width * subband_width; hh = buffer + subband_width * subband_width * 2; rfx_dwt_2d_encode_block_horiz_sse2(l_src, ll, hl, subband_width); rfx_dwt_2d_encode_block_horiz_sse2(h_src, lh, hh, subband_width); } static void rfx_dwt_2d_encode_sse2(sint16* buffer, sint16* dwt_buffer) { _mm_prefetch_buffer((char*) buffer, 4096 * sizeof(sint16)); rfx_dwt_2d_encode_block_sse2(buffer, dwt_buffer, 32); rfx_dwt_2d_encode_block_sse2(buffer + 3072, dwt_buffer, 16); rfx_dwt_2d_encode_block_sse2(buffer + 3840, dwt_buffer, 8); } void rfx_init_sse2(RFX_CONTEXT* context) { DEBUG_RFX("Using SSE2 optimizations"); IF_PROFILER(context->priv->prof_rfx_decode_ycbcr_to_rgb->name = "rfx_decode_ycbcr_to_rgb_sse2"); IF_PROFILER(context->priv->prof_rfx_encode_rgb_to_ycbcr->name = "rfx_encode_rgb_to_ycbcr_sse2"); IF_PROFILER(context->priv->prof_rfx_quantization_decode->name = "rfx_quantization_decode_sse2"); IF_PROFILER(context->priv->prof_rfx_quantization_encode->name = "rfx_quantization_encode_sse2"); IF_PROFILER(context->priv->prof_rfx_dwt_2d_decode->name = "rfx_dwt_2d_decode_sse2"); IF_PROFILER(context->priv->prof_rfx_dwt_2d_encode->name = "rfx_dwt_2d_encode_sse2"); context->decode_ycbcr_to_rgb = rfx_decode_ycbcr_to_rgb_sse2; context->encode_rgb_to_ycbcr = rfx_encode_rgb_to_ycbcr_sse2; context->quantization_decode = rfx_quantization_decode_sse2; context->quantization_encode = rfx_quantization_encode_sse2; context->dwt_2d_decode = rfx_dwt_2d_decode_sse2; context->dwt_2d_encode = rfx_dwt_2d_encode_sse2; } FreeRDP-1.0.2/libfreerdp-codec/rfx_sse2.h000066400000000000000000000016471207112532300200420ustar00rootroot00000000000000/** * FreeRDP: A Remote Desktop Protocol client. * RemoteFX Codec Library - SSE2 Optimizations * * Copyright 2011 Stephen Erisman * * 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. */ #ifndef __RFX_SSE2_H #define __RFX_SSE2_H #include void rfx_init_sse2(RFX_CONTEXT* context); #ifndef RFX_INIT_SIMD #define RFX_INIT_SIMD(_rfx_context) rfx_init_sse2(_rfx_context) #endif #endif /* __RFX_SSE2_H */ FreeRDP-1.0.2/libfreerdp-codec/rfx_types.h000066400000000000000000000042651207112532300203310ustar00rootroot00000000000000/** * FreeRDP: A Remote Desktop Protocol client. * RemoteFX Codec Library * * Copyright 2011 Vic Lee * * 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. */ #ifndef __RFX_TYPES_H #define __RFX_TYPES_H #include "config.h" #include #include #ifdef WITH_DEBUG_RFX #define DEBUG_RFX(fmt, ...) DEBUG_CLASS(RFX, fmt, ## __VA_ARGS__) #else #define DEBUG_RFX(fmt, ...) DEBUG_NULL(fmt, ## __VA_ARGS__) #endif #include "rfx_pool.h" struct _RFX_CONTEXT_PRIV { /* pre-allocated buffers */ RFX_POOL* pool; /* memory pool */ sint16 y_r_mem[4096 + 8]; /* 4096 = 64x64 (+ 8x2 = 16 for mem align) */ sint16 cb_g_mem[4096 + 8]; /* 4096 = 64x64 (+ 8x2 = 16 for mem align) */ sint16 cr_b_mem[4096 + 8]; /* 4096 = 64x64 (+ 8x2 = 16 for mem align) */ sint16* y_r_buffer; sint16* cb_g_buffer; sint16* cr_b_buffer; sint16 dwt_mem[32 * 32 * 2 * 2 + 8]; /* maximum sub-band width is 32 */ sint16* dwt_buffer; /* profilers */ PROFILER_DEFINE(prof_rfx_decode_rgb); PROFILER_DEFINE(prof_rfx_decode_component); PROFILER_DEFINE(prof_rfx_rlgr_decode); PROFILER_DEFINE(prof_rfx_differential_decode); PROFILER_DEFINE(prof_rfx_quantization_decode); PROFILER_DEFINE(prof_rfx_dwt_2d_decode); PROFILER_DEFINE(prof_rfx_decode_ycbcr_to_rgb); PROFILER_DEFINE(prof_rfx_decode_format_rgb); PROFILER_DEFINE(prof_rfx_encode_rgb); PROFILER_DEFINE(prof_rfx_encode_component); PROFILER_DEFINE(prof_rfx_rlgr_encode); PROFILER_DEFINE(prof_rfx_differential_encode); PROFILER_DEFINE(prof_rfx_quantization_encode); PROFILER_DEFINE(prof_rfx_dwt_2d_encode); PROFILER_DEFINE(prof_rfx_encode_rgb_to_ycbcr); PROFILER_DEFINE(prof_rfx_encode_format_rgb); }; #endif /* __RFX_TYPES_H */ FreeRDP-1.0.2/libfreerdp-core/000077500000000000000000000000001207112532300160015ustar00rootroot00000000000000FreeRDP-1.0.2/libfreerdp-core/CMakeLists.txt000066400000000000000000000042541207112532300205460ustar00rootroot00000000000000# FreeRDP: A Remote Desktop Protocol Client # libfreerdp-core cmake build script # # Copyright 2011 O.S. Systems Software Ltda. # Copyright 2011 Otavio Salvador # Copyright 2011 Marc-Andre Moreau # # 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. add_definitions(-DEXT_PATH="/usr/lib/freerdp/extensions") include_directories(${OPENSSL_INCLUDE_DIR}) include_directories(${ZLIB_INCLUDE_DIRS}) set(LIBFREERDP_CORE_SRCS activation.c activation.h extension.c extension.h ber.c ber.h gcc.c gcc.h mcs.c mcs.h nego.c nego.h info.c info.h input.c input.h crypto.c crypto.h credssp.c credssp.h ntlmssp.c ntlmssp.h license.c license.h errinfo.c errinfo.h security.c security.h settings.c orders.c orders.h freerdp.c graphics.c capabilities.c capabilities.h certificate.c certificate.h connection.c connection.h redirection.c redirection.h rdp.c rdp.h per.c per.h tcp.c tcp.h tls.c tls.h tpdu.c tpdu.h tpkt.c tpkt.h fastpath.c fastpath.h surface.c surface.h transport.c transport.h update.c update.h channel.c channel.h window.c window.h listener.c listener.h peer.c peer.h mppc.c ) add_library(freerdp-core ${LIBFREERDP_CORE_SRCS}) set_target_properties(freerdp-core PROPERTIES VERSION ${FREERDP_VERSION_FULL} SOVERSION ${FREERDP_VERSION} PREFIX "lib") if(WIN32) target_link_libraries(freerdp-core ws2_32) else() target_link_libraries(freerdp-core ${ZLIB_LIBRARIES}) endif() target_link_libraries(freerdp-core ${OPENSSL_LIBRARIES}) target_link_libraries(freerdp-core freerdp-utils) target_link_libraries(freerdp-core freerdp-codec) install(TARGETS freerdp-core DESTINATION ${CMAKE_INSTALL_LIBDIR}) FreeRDP-1.0.2/libfreerdp-core/activation.c000066400000000000000000000211201207112532300203020ustar00rootroot00000000000000/** * FreeRDP: A Remote Desktop Protocol Client * Activation Sequence * * Copyright 2011 Marc-Andre Moreau * * 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. */ #include "activation.h" /* static const char* const CTRLACTION_STRINGS[] = { "", "CTRLACTION_REQUEST_CONTROL", "CTRLACTION_GRANTED_CONTROL", "CTRLACTION_DETACH", "CTRLACTION_COOPERATE" }; */ void rdp_write_synchronize_pdu(STREAM* s, rdpSettings* settings) { stream_write_uint16(s, SYNCMSGTYPE_SYNC); /* messageType (2 bytes) */ stream_write_uint16(s, settings->pdu_source); /* targetUser (2 bytes) */ } boolean rdp_recv_synchronize_pdu(rdpRdp* rdp, STREAM* s) { if (rdp->settings->server_mode) return rdp_recv_server_synchronize_pdu(rdp, s); else return rdp_recv_client_synchronize_pdu(rdp, s); } boolean rdp_recv_server_synchronize_pdu(rdpRdp* rdp, STREAM* s) { rdp->finalize_sc_pdus |= FINALIZE_SC_SYNCHRONIZE_PDU; return true; } boolean rdp_send_server_synchronize_pdu(rdpRdp* rdp) { STREAM* s; s = rdp_data_pdu_init(rdp); rdp_write_synchronize_pdu(s, rdp->settings); rdp_send_data_pdu(rdp, s, DATA_PDU_TYPE_SYNCHRONIZE, rdp->mcs->user_id); return true; } boolean rdp_recv_client_synchronize_pdu(rdpRdp* rdp, STREAM* s) { uint16 messageType; rdp->finalize_sc_pdus |= FINALIZE_SC_SYNCHRONIZE_PDU; if (stream_get_left(s) < 4) return false; stream_read_uint16(s, messageType); /* messageType (2 bytes) */ if (messageType != SYNCMSGTYPE_SYNC) return false; /* targetUser (2 bytes) */ stream_seek_uint16(s); return true; } boolean rdp_send_client_synchronize_pdu(rdpRdp* rdp) { STREAM* s; s = rdp_data_pdu_init(rdp); rdp_write_synchronize_pdu(s, rdp->settings); return rdp_send_data_pdu(rdp, s, DATA_PDU_TYPE_SYNCHRONIZE, rdp->mcs->user_id); } boolean rdp_recv_control_pdu(STREAM* s, uint16* action) { if (stream_get_left(s) < 8) return false; stream_read_uint16(s, *action); /* action (2 bytes) */ stream_seek_uint16(s); /* grantId (2 bytes) */ stream_seek_uint32(s); /* controlId (4 bytes) */ return true; } void rdp_write_client_control_pdu(STREAM* s, uint16 action) { stream_write_uint16(s, action); /* action (2 bytes) */ stream_write_uint16(s, 0); /* grantId (2 bytes) */ stream_write_uint32(s, 0); /* controlId (4 bytes) */ } boolean rdp_recv_server_control_pdu(rdpRdp* rdp, STREAM* s) { uint16 action; rdp_recv_control_pdu(s, &action); switch (action) { case CTRLACTION_COOPERATE: rdp->finalize_sc_pdus |= FINALIZE_SC_CONTROL_COOPERATE_PDU; break; case CTRLACTION_GRANTED_CONTROL: rdp->finalize_sc_pdus |= FINALIZE_SC_CONTROL_GRANTED_PDU; break; } return true; } boolean rdp_send_server_control_cooperate_pdu(rdpRdp* rdp) { STREAM* s; s = rdp_data_pdu_init(rdp); stream_write_uint16(s, CTRLACTION_COOPERATE); /* action (2 bytes) */ stream_write_uint16(s, 0); /* grantId (2 bytes) */ stream_write_uint32(s, 0); /* controlId (4 bytes) */ rdp_send_data_pdu(rdp, s, DATA_PDU_TYPE_CONTROL, rdp->mcs->user_id); return true; } boolean rdp_send_server_control_granted_pdu(rdpRdp* rdp) { STREAM* s; s = rdp_data_pdu_init(rdp); stream_write_uint16(s, CTRLACTION_GRANTED_CONTROL); /* action (2 bytes) */ stream_write_uint16(s, rdp->mcs->user_id); /* grantId (2 bytes) */ stream_write_uint32(s, 0x03EA); /* controlId (4 bytes) */ rdp_send_data_pdu(rdp, s, DATA_PDU_TYPE_CONTROL, rdp->mcs->user_id); return true; } boolean rdp_send_client_control_pdu(rdpRdp* rdp, uint16 action) { STREAM* s; s = rdp_data_pdu_init(rdp); rdp_write_client_control_pdu(s, action); return rdp_send_data_pdu(rdp, s, DATA_PDU_TYPE_CONTROL, rdp->mcs->user_id); } void rdp_write_persistent_list_entry(STREAM* s, uint32 key1, uint32 key2) { stream_write_uint32(s, key1); /* key1 (4 bytes) */ stream_write_uint32(s, key2); /* key2 (4 bytes) */ } void rdp_write_client_persistent_key_list_pdu(STREAM* s, rdpSettings* settings) { stream_write_uint16(s, 0); /* numEntriesCache0 (2 bytes) */ stream_write_uint16(s, 0); /* numEntriesCache1 (2 bytes) */ stream_write_uint16(s, 0); /* numEntriesCache2 (2 bytes) */ stream_write_uint16(s, 0); /* numEntriesCache3 (2 bytes) */ stream_write_uint16(s, 0); /* numEntriesCache4 (2 bytes) */ stream_write_uint16(s, 0); /* totalEntriesCache0 (2 bytes) */ stream_write_uint16(s, 0); /* totalEntriesCache1 (2 bytes) */ stream_write_uint16(s, 0); /* totalEntriesCache2 (2 bytes) */ stream_write_uint16(s, 0); /* totalEntriesCache3 (2 bytes) */ stream_write_uint16(s, 0); /* totalEntriesCache4 (2 bytes) */ stream_write_uint8(s, PERSIST_FIRST_PDU | PERSIST_LAST_PDU); /* bBitMask (1 byte) */ stream_write_uint8(s, 0); /* pad1 (1 byte) */ stream_write_uint16(s, 0); /* pad3 (2 bytes) */ /* entries */ } boolean rdp_send_client_persistent_key_list_pdu(rdpRdp* rdp) { STREAM* s; s = rdp_data_pdu_init(rdp); rdp_write_client_persistent_key_list_pdu(s, rdp->settings); return rdp_send_data_pdu(rdp, s, DATA_PDU_TYPE_BITMAP_CACHE_PERSISTENT_LIST, rdp->mcs->user_id); } boolean rdp_recv_client_font_list_pdu(STREAM* s) { if (stream_get_left(s) < 8) return false; return true; } void rdp_write_client_font_list_pdu(STREAM* s, uint16 flags) { stream_write_uint16(s, 0); /* numberFonts (2 bytes) */ stream_write_uint16(s, 0); /* totalNumFonts (2 bytes) */ stream_write_uint16(s, flags); /* listFlags (2 bytes) */ stream_write_uint16(s, 50); /* entrySize (2 bytes) */ } boolean rdp_send_client_font_list_pdu(rdpRdp* rdp, uint16 flags) { STREAM* s; s = rdp_data_pdu_init(rdp); rdp_write_client_font_list_pdu(s, flags); return rdp_send_data_pdu(rdp, s, DATA_PDU_TYPE_FONT_LIST, rdp->mcs->user_id); } boolean rdp_recv_font_map_pdu(rdpRdp* rdp, STREAM* s) { if (rdp->settings->server_mode) return rdp_recv_server_font_map_pdu(rdp, s); else return rdp_recv_client_font_map_pdu(rdp, s); } boolean rdp_recv_server_font_map_pdu(rdpRdp* rdp, STREAM* s) { rdp->finalize_sc_pdus |= FINALIZE_SC_FONT_MAP_PDU; return true; } boolean rdp_recv_client_font_map_pdu(rdpRdp* rdp, STREAM* s) { rdp->finalize_sc_pdus |= FINALIZE_SC_FONT_MAP_PDU; stream_seek_uint16(s); /* numberEntries (2 bytes) */ stream_seek_uint16(s); /* totalNumEntries (2 bytes) */ stream_seek_uint16(s); /* mapFlags (2 bytes) */ stream_seek_uint16(s); /* entrySize (2 bytes) */ return true; } boolean rdp_send_server_font_map_pdu(rdpRdp* rdp) { STREAM* s; s = rdp_data_pdu_init(rdp); stream_write_uint16(s, 0); /* numberEntries (2 bytes) */ stream_write_uint16(s, 0); /* totalNumEntries (2 bytes) */ stream_write_uint16(s, FONTLIST_FIRST | FONTLIST_LAST); /* mapFlags (2 bytes) */ stream_write_uint16(s, 4); /* entrySize (2 bytes) */ return rdp_send_data_pdu(rdp, s, DATA_PDU_TYPE_FONT_MAP, rdp->mcs->user_id); } boolean rdp_recv_deactivate_all(rdpRdp* rdp, STREAM* s) { uint16 lengthSourceDescriptor; /* * Windows XP can send short DEACTIVATE_ALL PDU that doesn't contain * the following fields. */ if (stream_get_left(s) > 0) { stream_read_uint32(s, rdp->settings->share_id); /* shareId (4 bytes) */ stream_read_uint16(s, lengthSourceDescriptor); /* lengthSourceDescriptor (2 bytes) */ stream_seek(s, lengthSourceDescriptor); /* sourceDescriptor (should be 0x00) */ } rdp->state = CONNECTION_STATE_CAPABILITY; while (rdp->state != CONNECTION_STATE_ACTIVE) { if (rdp_check_fds(rdp) < 0) return false; if (rdp->disconnect) break; } return true; } boolean rdp_send_deactivate_all(rdpRdp* rdp) { STREAM* s; s = rdp_pdu_init(rdp); stream_write_uint32(s, rdp->settings->share_id); /* shareId (4 bytes) */ stream_write_uint16(s, 1); /* lengthSourceDescriptor (2 bytes) */ stream_write_uint8(s, 0); /* sourceDescriptor (should be 0x00) */ return rdp_send_pdu(rdp, s, PDU_TYPE_DEACTIVATE_ALL, rdp->mcs->user_id); } boolean rdp_server_accept_client_control_pdu(rdpRdp* rdp, STREAM* s) { uint16 action; if (!rdp_recv_control_pdu(s, &action)) return false; if (action == CTRLACTION_REQUEST_CONTROL) { if (!rdp_send_server_control_granted_pdu(rdp)) return false; } return true; } boolean rdp_server_accept_client_font_list_pdu(rdpRdp* rdp, STREAM* s) { if (!rdp_recv_client_font_list_pdu(s)) return false; if (!rdp_send_server_font_map_pdu(rdp)) return false; return true; } FreeRDP-1.0.2/libfreerdp-core/activation.h000066400000000000000000000046001207112532300203130ustar00rootroot00000000000000/** * FreeRDP: A Remote Desktop Protocol Client * Activation Sequence * * Copyright 2011 Marc-Andre Moreau * * 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. */ #ifndef __ACTIVATION_H #define __ACTIVATION_H #include "rdp.h" #include #include #define SYNCMSGTYPE_SYNC 0x0001 #define CTRLACTION_REQUEST_CONTROL 0x0001 #define CTRLACTION_GRANTED_CONTROL 0x0002 #define CTRLACTION_DETACH 0x0003 #define CTRLACTION_COOPERATE 0x0004 #define PERSIST_FIRST_PDU 0x01 #define PERSIST_LAST_PDU 0x02 #define FONTLIST_FIRST 0x0001 #define FONTLIST_LAST 0x0002 boolean rdp_recv_deactivate_all(rdpRdp* rdp, STREAM* s); boolean rdp_send_deactivate_all(rdpRdp* rdp); boolean rdp_recv_synchronize_pdu(rdpRdp* rdp, STREAM* s); boolean rdp_recv_server_synchronize_pdu(rdpRdp* rdp, STREAM* s); boolean rdp_send_server_synchronize_pdu(rdpRdp* rdp); boolean rdp_recv_client_synchronize_pdu(rdpRdp* rdp, STREAM* s); boolean rdp_send_client_synchronize_pdu(rdpRdp* rdp); boolean rdp_recv_control_pdu(STREAM* s, uint16* action); boolean rdp_recv_server_control_pdu(rdpRdp* rdp, STREAM* s); boolean rdp_send_server_control_cooperate_pdu(rdpRdp* rdp); boolean rdp_send_server_control_granted_pdu(rdpRdp* rdp); boolean rdp_send_client_control_pdu(rdpRdp* rdp, uint16 action); boolean rdp_send_client_persistent_key_list_pdu(rdpRdp* rdp); boolean rdp_recv_client_font_list_pdu(STREAM* s); boolean rdp_send_client_font_list_pdu(rdpRdp* rdp, uint16 flags); boolean rdp_recv_font_map_pdu(rdpRdp* rdp, STREAM* s); boolean rdp_recv_server_font_map_pdu(rdpRdp* rdp, STREAM* s); boolean rdp_recv_client_font_map_pdu(rdpRdp* rdp, STREAM* s); boolean rdp_send_server_font_map_pdu(rdpRdp* rdp); boolean rdp_server_accept_client_control_pdu(rdpRdp* rdp, STREAM* s); boolean rdp_server_accept_client_font_list_pdu(rdpRdp* rdp, STREAM* s); #endif /* __ACTIVATION_H */ FreeRDP-1.0.2/libfreerdp-core/ber.c000066400000000000000000000177731207112532300167340ustar00rootroot00000000000000/** * FreeRDP: A Remote Desktop Protocol Client * ASN.1 Basic Encoding Rules (BER) * * Copyright 2011 Marc-Andre Moreau * * 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. */ #include "ber.h" void ber_read_length(STREAM* s, int* length) { uint8 byte; stream_read_uint8(s, byte); if (byte & 0x80) { byte &= ~(0x80); if (byte == 1) stream_read_uint8(s, *length); if (byte == 2) stream_read_uint16_be(s, *length); } else { *length = byte; } } /** * Write BER length. * @param s stream * @param length length */ int ber_write_length(STREAM* s, int length) { if (length > 0x7F) { stream_write_uint8(s, 0x82); stream_write_uint16_be(s, length); return 3; } else { stream_write_uint8(s, length); return 1; } } int _ber_skip_length(int length) { if (length > 0x7F) return 3; else return 1; } int ber_get_content_length(int length) { if (length - 1 > 0x7F) return length - 4; else return length - 2; } /** * Read BER Universal tag. * @param s stream * @param tag BER universally-defined tag * @return */ boolean ber_read_universal_tag(STREAM* s, uint8 tag, boolean pc) { uint8 byte; stream_read_uint8(s, byte); if (byte != (BER_CLASS_UNIV | BER_PC(pc) | (BER_TAG_MASK & tag))) return false; return true; } /** * Write BER Universal tag. * @param s stream * @param tag BER universally-defined tag * @param pc primitive (false) or constructed (true) */ void ber_write_universal_tag(STREAM* s, uint8 tag, boolean pc) { stream_write_uint8(s, (BER_CLASS_UNIV | BER_PC(pc)) | (BER_TAG_MASK & tag)); } /** * Read BER Application tag. * @param s stream * @param tag BER application-defined tag * @param length length */ boolean ber_read_application_tag(STREAM* s, uint8 tag, int* length) { uint8 byte; if (tag > 30) { stream_read_uint8(s, byte); if (byte != ((BER_CLASS_APPL | BER_CONSTRUCT) | BER_TAG_MASK)) return false; stream_read_uint8(s, byte); if (byte != tag) return false; ber_read_length(s, length); } else { stream_read_uint8(s, byte); if (byte != ((BER_CLASS_APPL | BER_CONSTRUCT) | (BER_TAG_MASK & tag))) return false; ber_read_length(s, length); } return true; } /** * Write BER Application tag. * @param s stream * @param tag BER application-defined tag * @param length length */ void ber_write_application_tag(STREAM* s, uint8 tag, int length) { if (tag > 30) { stream_write_uint8(s, (BER_CLASS_APPL | BER_CONSTRUCT) | BER_TAG_MASK); stream_write_uint8(s, tag); ber_write_length(s, length); } else { stream_write_uint8(s, (BER_CLASS_APPL | BER_CONSTRUCT) | (BER_TAG_MASK & tag)); ber_write_length(s, length); } } boolean ber_read_contextual_tag(STREAM* s, uint8 tag, int* length, boolean pc) { uint8 byte; stream_read_uint8(s, byte); if (byte != ((BER_CLASS_CTXT | BER_PC(pc)) | (BER_TAG_MASK & tag))) { stream_rewind(s, 1); return false; } ber_read_length(s, length); return true; } int ber_write_contextual_tag(STREAM* s, uint8 tag, int length, boolean pc) { stream_write_uint8(s, (BER_CLASS_CTXT | BER_PC(pc)) | (BER_TAG_MASK & tag)); return ber_write_length(s, length) + 1; } int ber_skip_contextual_tag(int length) { return _ber_skip_length(length) + 1; } boolean ber_read_sequence_tag(STREAM* s, int* length) { uint8 byte; stream_read_uint8(s, byte); if (byte != ((BER_CLASS_UNIV | BER_CONSTRUCT) | (BER_TAG_SEQUENCE_OF))) return false; ber_read_length(s, length); return true; } /** * Write BER SEQUENCE tag. * @param s stream * @param length length */ int ber_write_sequence_tag(STREAM* s, int length) { stream_write_uint8(s, (BER_CLASS_UNIV | BER_CONSTRUCT) | (BER_TAG_MASK & BER_TAG_SEQUENCE)); return ber_write_length(s, length) + 1; } int ber_skip_sequence(int length) { return 1 + _ber_skip_length(length) + length; } int ber_skip_sequence_tag(int length) { return 1 + _ber_skip_length(length); } boolean ber_read_enumerated(STREAM* s, uint8* enumerated, uint8 count) { int length; ber_read_universal_tag(s, BER_TAG_ENUMERATED, false); ber_read_length(s, &length); if (length == 1) stream_read_uint8(s, *enumerated); else return false; /* check that enumerated value falls within expected range */ if (*enumerated + 1 > count) return false; return true; } void ber_write_enumerated(STREAM* s, uint8 enumerated, uint8 count) { ber_write_universal_tag(s, BER_TAG_ENUMERATED, false); ber_write_length(s, 1); stream_write_uint8(s, enumerated); } boolean ber_read_bit_string(STREAM* s, int* length, uint8* padding) { ber_read_universal_tag(s, BER_TAG_BIT_STRING, false); ber_read_length(s, length); stream_read_uint8(s, *padding); return true; } boolean ber_read_octet_string(STREAM* s, int* length) { ber_read_universal_tag(s, BER_TAG_OCTET_STRING, false); ber_read_length(s, length); return true; } /** * Write a BER OCTET_STRING * @param s stream * @param oct_str octet string * @param length string length */ void ber_write_octet_string(STREAM* s, const uint8* oct_str, int length) { ber_write_universal_tag(s, BER_TAG_OCTET_STRING, false); ber_write_length(s, length); stream_write(s, oct_str, length); } int ber_write_octet_string_tag(STREAM* s, int length) { ber_write_universal_tag(s, BER_TAG_OCTET_STRING, false); ber_write_length(s, length); return 1 + _ber_skip_length(length); } int ber_skip_octet_string(int length) { return 1 + _ber_skip_length(length) + length; } /** * Read a BER BOOLEAN * @param s * @param value */ boolean ber_read_boolean(STREAM* s, boolean* value) { int length; uint8 v; if (!ber_read_universal_tag(s, BER_TAG_BOOLEAN, false)) return false; ber_read_length(s, &length); if (length != 1) return false; stream_read_uint8(s, v); *value = (v ? true : false); return true; } /** * Write a BER BOOLEAN * @param s * @param value */ void ber_write_boolean(STREAM* s, boolean value) { ber_write_universal_tag(s, BER_TAG_BOOLEAN, false); ber_write_length(s, 1); stream_write_uint8(s, (value == true) ? 0xFF : 0); } boolean ber_read_integer(STREAM* s, uint32* value) { int length; ber_read_universal_tag(s, BER_TAG_INTEGER, false); ber_read_length(s, &length); if (value == NULL) { stream_seek(s, length); return true; } if (length == 1) stream_read_uint8(s, *value); else if (length == 2) stream_read_uint16_be(s, *value); else if (length == 3) { uint8 byte; stream_read_uint8(s, byte); stream_read_uint16_be(s, *value); *value += (byte << 16); } else if (length == 4) stream_read_uint32_be(s, *value); else return false; return true; } /** * Write a BER INTEGER * @param s * @param value */ int ber_write_integer(STREAM* s, uint32 value) { ber_write_universal_tag(s, BER_TAG_INTEGER, false); if (value <= 0xFF) { ber_write_length(s, 1); stream_write_uint8(s, value); return 2; } else if (value < 0xFF80) { ber_write_length(s, 2); stream_write_uint16_be(s, value); return 3; } else if (value < 0xFF8000) { ber_write_length(s, 3); stream_write_uint8(s, (value >> 16)); stream_write_uint16_be(s, (value & 0xFFFF)); return 4; } else if (value <= 0xFFFFFFFF) { ber_write_length(s, 4); stream_write_uint32_be(s, value); return 5; } return 0; } int ber_skip_integer(uint32 value) { if (value <= 0xFF) { return _ber_skip_length(1) + 2; } else if (value <= 0xFFFF) { return _ber_skip_length(2) + 3; } else if (value <= 0xFFFFFFFF) { return _ber_skip_length(4) + 5; } return 0; } boolean ber_read_integer_length(STREAM* s, int* length) { ber_read_universal_tag(s, BER_TAG_INTEGER, false); ber_read_length(s, length); return true; } FreeRDP-1.0.2/libfreerdp-core/ber.h000066400000000000000000000061211207112532300167220ustar00rootroot00000000000000/** * FreeRDP: A Remote Desktop Protocol Client * ASN.1 Basic Encoding Rules (BER) * * Copyright 2011 Marc-Andre Moreau * * 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. */ #ifndef __BER_H #define __BER_H #include #include /* BER type */ /* Class - bits 8 and 7 */ #define BER_CLASS_MASK 0xC0 #define BER_CLASS_UNIV 0x00 /* 0 0 */ #define BER_CLASS_APPL 0x40 /* 0 1 */ #define BER_CLASS_CTXT 0x80 /* 1 0 */ #define BER_CLASS_PRIV 0xC0 /* 1 1 */ /* P/C - bit 6 */ #define BER_PC_MASK 0x20 #define BER_PRIMITIVE 0x00 /* 0 */ #define BER_CONSTRUCT 0x20 /* 1 */ /* Tag - bits 5 to 1 */ #define BER_TAG_MASK 0x1F #define BER_TAG_BOOLEAN 0x01 #define BER_TAG_INTEGER 0x02 #define BER_TAG_BIT_STRING 0x03 #define BER_TAG_OCTET_STRING 0x04 #define BER_TAG_OBJECT_IDENFIER 0x06 #define BER_TAG_ENUMERATED 0x0A #define BER_TAG_SEQUENCE 0x10 #define BER_TAG_SEQUENCE_OF 0x10 #define BER_PC(_pc) (_pc ? BER_CONSTRUCT : BER_PRIMITIVE) void ber_read_length(STREAM* s, int* length); int ber_write_length(STREAM* s, int length); int _ber_skip_length(int length); int ber_get_content_length(int length); boolean ber_read_universal_tag(STREAM* s, uint8 tag, boolean pc); void ber_write_universal_tag(STREAM* s, uint8 tag, boolean pc); boolean ber_read_application_tag(STREAM* s, uint8 tag, int* length); void ber_write_application_tag(STREAM* s, uint8 tag, int length); boolean ber_read_application_tag(STREAM* s, uint8 tag, int* length); boolean ber_read_enumerated(STREAM* s, uint8* enumerated, uint8 count); void ber_write_enumerated(STREAM* s, uint8 enumerated, uint8 count); boolean ber_read_contextual_tag(STREAM* s, uint8 tag, int* length, boolean pc); int ber_write_contextual_tag(STREAM* s, uint8 tag, int length, boolean pc); int ber_skip_contextual_tag(int length); boolean ber_read_sequence_tag(STREAM* s, int* length); int ber_write_sequence_tag(STREAM* s, int length); int ber_skip_sequence(int length); int ber_skip_sequence_tag(int length); boolean ber_read_bit_string(STREAM* s, int* length, uint8* padding); boolean ber_read_octet_string(STREAM* s, int* length); void ber_write_octet_string(STREAM* s, const uint8* oct_str, int length); int ber_write_octet_string_tag(STREAM* s, int length); int ber_skip_octet_string(int length); boolean ber_read_boolean(STREAM* s, boolean* value); void ber_write_boolean(STREAM* s, boolean value); boolean ber_read_integer(STREAM* s, uint32* value); int ber_write_integer(STREAM* s, uint32 value); boolean ber_read_integer_length(STREAM* s, int* length); int ber_skip_integer(uint32 value); #endif /* __BER_H */ FreeRDP-1.0.2/libfreerdp-core/capabilities.c000066400000000000000000001654171207112532300206140ustar00rootroot00000000000000/** * FreeRDP: A Remote Desktop Protocol Client * RDP Capability Sets * * Copyright 2011 Marc-Andre Moreau * * 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. */ #include "capabilities.h" /* static const char* const CAPSET_TYPE_STRINGS[] = { "Unknown", "General", "Bitmap", "Order", "Bitmap Cache", "Control", "Unknown", "Window Activation", "Pointer", "Share", "Color Cache", "Unknown", "Sound", "Input", "Font", "Brush", "Glyph Cache", "Offscreen Bitmap Cache", "Bitmap Cache Host Support", "Bitmap Cache v2", "Virtual Channel", "DrawNineGrid Cache", "Draw GDI+ Cache", "Remote Programs", "Window List", "Desktop Composition", "Multifragment Update", "Large Pointer", "Surface Commands", "Bitmap Codecs", "Frame Acknowledge" }; */ /* CODEC_GUID_REMOTEFX 0x76772F12BD724463AFB3B73C9C6F7886 */ #define CODEC_GUID_REMOTEFX "\x12\x2F\x77\x76\x72\xBD\x63\x44\xAF\xB3\xB7\x3C\x9C\x6F\x78\x86" /* CODEC_GUID_NSCODEC 0xCA8D1BB9000F154F589FAE2D1A87E2D6 */ #define CODEC_GUID_NSCODEC "\xb9\x1b\x8d\xca\x0f\x00\x4f\x15\x58\x9f\xae\x2d\x1a\x87\xe2\xd6" void rdp_read_capability_set_header(STREAM* s, uint16* length, uint16* type) { stream_read_uint16(s, *type); /* capabilitySetType */ stream_read_uint16(s, *length); /* lengthCapability */ } void rdp_write_capability_set_header(STREAM* s, uint16 length, uint16 type) { stream_write_uint16(s, type); /* capabilitySetType */ stream_write_uint16(s, length); /* lengthCapability */ } uint8* rdp_capability_set_start(STREAM* s) { uint8* header; stream_get_mark(s, header); stream_write_zero(s, CAPSET_HEADER_LENGTH); return header; } void rdp_capability_set_finish(STREAM* s, uint8* header, uint16 type) { uint16 length; uint8* footer; footer = s->p; length = footer - header; stream_set_mark(s, header); rdp_write_capability_set_header(s, length, type); stream_set_mark(s, footer); } /** * Read general capability set.\n * @msdn{cc240549} * @param s stream * @param settings settings */ void rdp_read_general_capability_set(STREAM* s, uint16 length, rdpSettings* settings) { uint16 extraFlags; uint8 refreshRectSupport; uint8 suppressOutputSupport; if (settings->server_mode) { stream_read_uint16(s, settings->os_major_type); /* osMajorType (2 bytes) */ stream_read_uint16(s, settings->os_minor_type); /* osMinorType (2 bytes) */ } else { stream_seek_uint16(s); /* osMajorType (2 bytes) */ stream_seek_uint16(s); /* osMinorType (2 bytes) */ } stream_seek_uint16(s); /* protocolVersion (2 bytes) */ stream_seek_uint16(s); /* pad2OctetsA (2 bytes) */ stream_seek_uint16(s); /* generalCompressionTypes (2 bytes) */ stream_read_uint16(s, extraFlags); /* extraFlags (2 bytes) */ stream_seek_uint16(s); /* updateCapabilityFlag (2 bytes) */ stream_seek_uint16(s); /* remoteUnshareFlag (2 bytes) */ stream_seek_uint16(s); /* generalCompressionLevel (2 bytes) */ stream_read_uint8(s, refreshRectSupport); /* refreshRectSupport (1 byte) */ stream_read_uint8(s, suppressOutputSupport); /* suppressOutputSupport (1 byte) */ if (!(extraFlags & FASTPATH_OUTPUT_SUPPORTED)) settings->fastpath_output = false; if (refreshRectSupport == false) settings->refresh_rect = false; if (suppressOutputSupport == false) settings->suppress_output = false; } /** * Write general capability set.\n * @msdn{cc240549} * @param s stream * @param settings settings */ void rdp_write_general_capability_set(STREAM* s, rdpSettings* settings) { uint8* header; uint16 extraFlags; header = rdp_capability_set_start(s); extraFlags = LONG_CREDENTIALS_SUPPORTED | NO_BITMAP_COMPRESSION_HDR; if (settings->auto_reconnection) extraFlags |= AUTORECONNECT_SUPPORTED; if (settings->fastpath_output) extraFlags |= FASTPATH_OUTPUT_SUPPORTED; if (settings->server_mode) { /* not yet supported server-side */ settings->refresh_rect = false; settings->suppress_output = false; } stream_write_uint16(s, settings->os_major_type); /* osMajorType (2 bytes) */ stream_write_uint16(s, settings->os_minor_type); /* osMinorType (2 bytes) */ stream_write_uint16(s, CAPS_PROTOCOL_VERSION); /* protocolVersion (2 bytes) */ stream_write_uint16(s, 0); /* pad2OctetsA (2 bytes) */ stream_write_uint16(s, 0); /* generalCompressionTypes (2 bytes) */ stream_write_uint16(s, extraFlags); /* extraFlags (2 bytes) */ stream_write_uint16(s, 0); /* updateCapabilityFlag (2 bytes) */ stream_write_uint16(s, 0); /* remoteUnshareFlag (2 bytes) */ stream_write_uint16(s, 0); /* generalCompressionLevel (2 bytes) */ stream_write_uint8(s, settings->refresh_rect); /* refreshRectSupport (1 byte) */ stream_write_uint8(s, settings->suppress_output); /* suppressOutputSupport (1 byte) */ rdp_capability_set_finish(s, header, CAPSET_TYPE_GENERAL); } /** * Read bitmap capability set.\n * @msdn{cc240554} * @param s stream * @param settings settings */ void rdp_read_bitmap_capability_set(STREAM* s, uint16 length, rdpSettings* settings) { uint8 drawingFlags; uint16 desktopWidth; uint16 desktopHeight; uint16 desktopResizeFlag; uint16 preferredBitsPerPixel; stream_read_uint16(s, preferredBitsPerPixel); /* preferredBitsPerPixel (2 bytes) */ stream_seek_uint16(s); /* receive1BitPerPixel (2 bytes) */ stream_seek_uint16(s); /* receive4BitsPerPixel (2 bytes) */ stream_seek_uint16(s); /* receive8BitsPerPixel (2 bytes) */ stream_read_uint16(s, desktopWidth); /* desktopWidth (2 bytes) */ stream_read_uint16(s, desktopHeight); /* desktopHeight (2 bytes) */ stream_seek_uint16(s); /* pad2Octets (2 bytes) */ stream_read_uint16(s, desktopResizeFlag); /* desktopResizeFlag (2 bytes) */ stream_seek_uint16(s); /* bitmapCompressionFlag (2 bytes) */ stream_seek_uint8(s); /* highColorFlags (1 byte) */ stream_read_uint8(s, drawingFlags); /* drawingFlags (1 byte) */ stream_seek_uint16(s); /* multipleRectangleSupport (2 bytes) */ stream_seek_uint16(s); /* pad2OctetsB (2 bytes) */ if (!settings->server_mode && preferredBitsPerPixel != settings->color_depth) { /* The client must respect the actual color depth used by the server */ settings->color_depth = preferredBitsPerPixel; } if (desktopResizeFlag == false) settings->desktop_resize = false; if (!settings->server_mode && settings->desktop_resize) { /* The server may request a different desktop size during Deactivation-Reactivation sequence */ settings->width = desktopWidth; settings->height = desktopHeight; } } /** * Write bitmap capability set.\n * @msdn{cc240554} * @param s stream * @param settings settings */ void rdp_write_bitmap_capability_set(STREAM* s, rdpSettings* settings) { uint8* header; uint8 drawingFlags; uint16 desktopResizeFlag; uint16 preferredBitsPerPixel; header = rdp_capability_set_start(s); drawingFlags = 0; if (settings->rdp_version > 5) preferredBitsPerPixel = settings->color_depth; else preferredBitsPerPixel = 8; desktopResizeFlag = settings->desktop_resize; stream_write_uint16(s, preferredBitsPerPixel); /* preferredBitsPerPixel (2 bytes) */ stream_write_uint16(s, 1); /* receive1BitPerPixel (2 bytes) */ stream_write_uint16(s, 1); /* receive4BitsPerPixel (2 bytes) */ stream_write_uint16(s, 1); /* receive8BitsPerPixel (2 bytes) */ stream_write_uint16(s, settings->width); /* desktopWidth (2 bytes) */ stream_write_uint16(s, settings->height); /* desktopHeight (2 bytes) */ stream_write_uint16(s, 0); /* pad2Octets (2 bytes) */ stream_write_uint16(s, desktopResizeFlag); /* desktopResizeFlag (2 bytes) */ stream_write_uint16(s, 1); /* bitmapCompressionFlag (2 bytes) */ stream_write_uint8(s, 0); /* highColorFlags (1 byte) */ stream_write_uint8(s, drawingFlags); /* drawingFlags (1 byte) */ stream_write_uint16(s, 1); /* multipleRectangleSupport (2 bytes) */ stream_write_uint16(s, 0); /* pad2OctetsB (2 bytes) */ rdp_capability_set_finish(s, header, CAPSET_TYPE_BITMAP); } /** * Read order capability set.\n * @msdn{cc240556} * @param s stream * @param settings settings */ void rdp_read_order_capability_set(STREAM* s, uint16 length, rdpSettings* settings) { int i; uint16 orderFlags; uint8 orderSupport[32]; uint16 orderSupportExFlags; stream_seek(s, 16); /* terminalDescriptor (16 bytes) */ stream_seek_uint32(s); /* pad4OctetsA (4 bytes) */ stream_seek_uint16(s); /* desktopSaveXGranularity (2 bytes) */ stream_seek_uint16(s); /* desktopSaveYGranularity (2 bytes) */ stream_seek_uint16(s); /* pad2OctetsA (2 bytes) */ stream_seek_uint16(s); /* maximumOrderLevel (2 bytes) */ stream_seek_uint16(s); /* numberFonts (2 bytes) */ stream_read_uint16(s, orderFlags); /* orderFlags (2 bytes) */ stream_read(s, orderSupport, 32); /* orderSupport (32 bytes) */ stream_seek_uint16(s); /* textFlags (2 bytes) */ stream_read_uint16(s, orderSupportExFlags); /* orderSupportExFlags (2 bytes) */ stream_seek_uint32(s); /* pad4OctetsB (4 bytes) */ stream_seek_uint32(s); /* desktopSaveSize (4 bytes) */ stream_seek_uint16(s); /* pad2OctetsC (2 bytes) */ stream_seek_uint16(s); /* pad2OctetsD (2 bytes) */ stream_seek_uint16(s); /* textANSICodePage (2 bytes) */ stream_seek_uint16(s); /* pad2OctetsE (2 bytes) */ for (i = 0; i < 32; i++) { if (orderSupport[i] == false) settings->order_support[i] = false; } } /** * Write order capability set.\n * @msdn{cc240556} * @param s stream * @param settings settings */ void rdp_write_order_capability_set(STREAM* s, rdpSettings* settings) { uint8* header; uint16 orderFlags; uint16 orderSupportExFlags; uint16 textANSICodePage; header = rdp_capability_set_start(s); /* see [MSDN-CP]: http://msdn.microsoft.com/en-us/library/dd317756 */ textANSICodePage = 65001; /* Unicode (UTF-8) */ orderSupportExFlags = 0; orderFlags = NEGOTIATE_ORDER_SUPPORT | ZERO_BOUNDS_DELTA_SUPPORT | COLOR_INDEX_SUPPORT; if (settings->bitmap_cache_v3) { orderSupportExFlags |= CACHE_BITMAP_V3_SUPPORT; orderFlags |= ORDER_FLAGS_EXTRA_SUPPORT; } if (settings->frame_marker) { orderSupportExFlags |= ALTSEC_FRAME_MARKER_SUPPORT; orderFlags |= ORDER_FLAGS_EXTRA_SUPPORT; } stream_write_zero(s, 16); /* terminalDescriptor (16 bytes) */ stream_write_uint32(s, 0); /* pad4OctetsA (4 bytes) */ stream_write_uint16(s, 1); /* desktopSaveXGranularity (2 bytes) */ stream_write_uint16(s, 20); /* desktopSaveYGranularity (2 bytes) */ stream_write_uint16(s, 0); /* pad2OctetsA (2 bytes) */ stream_write_uint16(s, 1); /* maximumOrderLevel (2 bytes) */ stream_write_uint16(s, 0); /* numberFonts (2 bytes) */ stream_write_uint16(s, orderFlags); /* orderFlags (2 bytes) */ stream_write(s, settings->order_support, 32); /* orderSupport (32 bytes) */ stream_write_uint16(s, 0); /* textFlags (2 bytes) */ stream_write_uint16(s, orderSupportExFlags); /* orderSupportExFlags (2 bytes) */ stream_write_uint32(s, 0); /* pad4OctetsB (4 bytes) */ stream_write_uint32(s, 230400); /* desktopSaveSize (4 bytes) */ stream_write_uint16(s, 0); /* pad2OctetsC (2 bytes) */ stream_write_uint16(s, 0); /* pad2OctetsD (2 bytes) */ stream_write_uint16(s, 0); /* textANSICodePage (2 bytes) */ stream_write_uint16(s, 0); /* pad2OctetsE (2 bytes) */ rdp_capability_set_finish(s, header, CAPSET_TYPE_ORDER); } /** * Read bitmap cache capability set.\n * @msdn{cc240559} * @param s stream * @param settings settings */ void rdp_read_bitmap_cache_capability_set(STREAM* s, uint16 length, rdpSettings* settings) { stream_seek_uint32(s); /* pad1 (4 bytes) */ stream_seek_uint32(s); /* pad2 (4 bytes) */ stream_seek_uint32(s); /* pad3 (4 bytes) */ stream_seek_uint32(s); /* pad4 (4 bytes) */ stream_seek_uint32(s); /* pad5 (4 bytes) */ stream_seek_uint32(s); /* pad6 (4 bytes) */ stream_seek_uint16(s); /* Cache0Entries (2 bytes) */ stream_seek_uint16(s); /* Cache0MaximumCellSize (2 bytes) */ stream_seek_uint16(s); /* Cache1Entries (2 bytes) */ stream_seek_uint16(s); /* Cache1MaximumCellSize (2 bytes) */ stream_seek_uint16(s); /* Cache2Entries (2 bytes) */ stream_seek_uint16(s); /* Cache2MaximumCellSize (2 bytes) */ } /** * Write bitmap cache capability set.\n * @msdn{cc240559} * @param s stream * @param settings settings */ void rdp_write_bitmap_cache_capability_set(STREAM* s, rdpSettings* settings) { int bpp; uint16 size; uint8* header; header = rdp_capability_set_start(s); bpp = (settings->color_depth + 7) / 8; stream_write_uint32(s, 0); /* pad1 (4 bytes) */ stream_write_uint32(s, 0); /* pad2 (4 bytes) */ stream_write_uint32(s, 0); /* pad3 (4 bytes) */ stream_write_uint32(s, 0); /* pad4 (4 bytes) */ stream_write_uint32(s, 0); /* pad5 (4 bytes) */ stream_write_uint32(s, 0); /* pad6 (4 bytes) */ size = bpp * 256; stream_write_uint16(s, 200); /* Cache0Entries (2 bytes) */ stream_write_uint16(s, size); /* Cache0MaximumCellSize (2 bytes) */ size = bpp * 1024; stream_write_uint16(s, 600); /* Cache1Entries (2 bytes) */ stream_write_uint16(s, size); /* Cache1MaximumCellSize (2 bytes) */ size = bpp * 4096; stream_write_uint16(s, 1000); /* Cache2Entries (2 bytes) */ stream_write_uint16(s, size); /* Cache2MaximumCellSize (2 bytes) */ rdp_capability_set_finish(s, header, CAPSET_TYPE_BITMAP_CACHE); } /** * Read control capability set.\n * @msdn{cc240568} * @param s stream * @param settings settings */ void rdp_read_control_capability_set(STREAM* s, uint16 length, rdpSettings* settings) { stream_seek_uint16(s); /* controlFlags (2 bytes) */ stream_seek_uint16(s); /* remoteDetachFlag (2 bytes) */ stream_seek_uint16(s); /* controlInterest (2 bytes) */ stream_seek_uint16(s); /* detachInterest (2 bytes) */ } /** * Write control capability set.\n * @msdn{cc240568} * @param s stream * @param settings settings */ void rdp_write_control_capability_set(STREAM* s, rdpSettings* settings) { uint8* header; header = rdp_capability_set_start(s); stream_write_uint16(s, 0); /* controlFlags (2 bytes) */ stream_write_uint16(s, 0); /* remoteDetachFlag (2 bytes) */ stream_write_uint16(s, 2); /* controlInterest (2 bytes) */ stream_write_uint16(s, 2); /* detachInterest (2 bytes) */ rdp_capability_set_finish(s, header, CAPSET_TYPE_CONTROL); } /** * Read window activation capability set.\n * @msdn{cc240569} * @param s stream * @param settings settings */ void rdp_read_window_activation_capability_set(STREAM* s, uint16 length, rdpSettings* settings) { stream_seek_uint16(s); /* helpKeyFlag (2 bytes) */ stream_seek_uint16(s); /* helpKeyIndexFlag (2 bytes) */ stream_seek_uint16(s); /* helpExtendedKeyFlag (2 bytes) */ stream_seek_uint16(s); /* windowManagerKeyFlag (2 bytes) */ } /** * Write window activation capability set.\n * @msdn{cc240569} * @param s stream * @param settings settings */ void rdp_write_window_activation_capability_set(STREAM* s, rdpSettings* settings) { uint8* header; header = rdp_capability_set_start(s); stream_write_uint16(s, 0); /* helpKeyFlag (2 bytes) */ stream_write_uint16(s, 0); /* helpKeyIndexFlag (2 bytes) */ stream_write_uint16(s, 0); /* helpExtendedKeyFlag (2 bytes) */ stream_write_uint16(s, 0); /* windowManagerKeyFlag (2 bytes) */ rdp_capability_set_finish(s, header, CAPSET_TYPE_ACTIVATION); } /** * Read pointer capability set.\n * @msdn{cc240562} * @param s stream * @param settings settings */ void rdp_read_pointer_capability_set(STREAM* s, uint16 length, rdpSettings* settings) { uint16 colorPointerFlag; uint16 colorPointerCacheSize; uint16 pointerCacheSize; stream_read_uint16(s, colorPointerFlag); /* colorPointerFlag (2 bytes) */ stream_read_uint16(s, colorPointerCacheSize); /* colorPointerCacheSize (2 bytes) */ stream_read_uint16(s, pointerCacheSize); /* pointerCacheSize (2 bytes) */ if (colorPointerFlag == false) settings->color_pointer = false; if (settings->server_mode) { settings->pointer_cache_size = pointerCacheSize; } } /** * Write pointer capability set.\n * @msdn{cc240562} * @param s stream * @param settings settings */ void rdp_write_pointer_capability_set(STREAM* s, rdpSettings* settings) { uint8* header; uint16 colorPointerFlag; header = rdp_capability_set_start(s); colorPointerFlag = (settings->color_pointer) ? 1 : 0; stream_write_uint16(s, colorPointerFlag); /* colorPointerFlag (2 bytes) */ stream_write_uint16(s, settings->pointer_cache_size); /* colorPointerCacheSize (2 bytes) */ if (settings->large_pointer) { stream_write_uint16(s, settings->pointer_cache_size); /* pointerCacheSize (2 bytes) */ } rdp_capability_set_finish(s, header, CAPSET_TYPE_POINTER); } /** * Read share capability set.\n * @msdn{cc240570} * @param s stream * @param settings settings */ void rdp_read_share_capability_set(STREAM* s, uint16 length, rdpSettings* settings) { stream_seek_uint16(s); /* nodeId (2 bytes) */ stream_seek_uint16(s); /* pad2Octets (2 bytes) */ } /** * Write share capability set.\n * @msdn{cc240570} * @param s stream * @param settings settings */ void rdp_write_share_capability_set(STREAM* s, rdpSettings* settings) { uint8* header; uint16 nodeId; header = rdp_capability_set_start(s); nodeId = (settings->server_mode) ? 0x03EA : 0; stream_write_uint16(s, nodeId); /* nodeId (2 bytes) */ stream_write_uint16(s, 0); /* pad2Octets (2 bytes) */ rdp_capability_set_finish(s, header, CAPSET_TYPE_SHARE); } /** * Read color cache capability set.\n * @msdn{cc241564} * @param s stream * @param settings settings */ void rdp_read_color_cache_capability_set(STREAM* s, uint16 length, rdpSettings* settings) { stream_seek_uint16(s); /* colorTableCacheSize (2 bytes) */ stream_seek_uint16(s); /* pad2Octets (2 bytes) */ } /** * Write color cache capability set.\n * @msdn{cc241564} * @param s stream * @param settings settings */ void rdp_write_color_cache_capability_set(STREAM* s, rdpSettings* settings) { uint8* header; header = rdp_capability_set_start(s); stream_write_uint16(s, 6); /* colorTableCacheSize (2 bytes) */ stream_write_uint16(s, 0); /* pad2Octets (2 bytes) */ rdp_capability_set_finish(s, header, CAPSET_TYPE_COLOR_CACHE); } /** * Read sound capability set.\n * @msdn{cc240552} * @param s stream * @param settings settings */ void rdp_read_sound_capability_set(STREAM* s, uint16 length, rdpSettings* settings) { uint16 soundFlags; stream_read_uint16(s, soundFlags); /* soundFlags (2 bytes) */ stream_seek_uint16(s); /* pad2OctetsA (2 bytes) */ settings->sound_beeps = (soundFlags & SOUND_BEEPS_FLAG) ? true : false; } /** * Write sound capability set.\n * @msdn{cc240552} * @param s stream * @param settings settings */ void rdp_write_sound_capability_set(STREAM* s, rdpSettings* settings) { uint8* header; uint16 soundFlags; header = rdp_capability_set_start(s); soundFlags = (settings->sound_beeps) ? SOUND_BEEPS_FLAG : 0; stream_write_uint16(s, soundFlags); /* soundFlags (2 bytes) */ stream_write_uint16(s, 0); /* pad2OctetsA (2 bytes) */ rdp_capability_set_finish(s, header, CAPSET_TYPE_SOUND); } /** * Read input capability set.\n * @msdn{cc240563} * @param s stream * @param settings settings */ void rdp_read_input_capability_set(STREAM* s, uint16 length, rdpSettings* settings) { uint16 inputFlags; stream_read_uint16(s, inputFlags); /* inputFlags (2 bytes) */ stream_seek_uint16(s); /* pad2OctetsA (2 bytes) */ if (settings->server_mode) { stream_read_uint32(s, settings->kbd_layout); /* keyboardLayout (4 bytes) */ stream_read_uint32(s, settings->kbd_type); /* keyboardType (4 bytes) */ stream_read_uint32(s, settings->kbd_subtype); /* keyboardSubType (4 bytes) */ stream_read_uint32(s, settings->kbd_fn_keys); /* keyboardFunctionKeys (4 bytes) */ } else { stream_seek_uint32(s); /* keyboardLayout (4 bytes) */ stream_seek_uint32(s); /* keyboardType (4 bytes) */ stream_seek_uint32(s); /* keyboardSubType (4 bytes) */ stream_seek_uint32(s); /* keyboardFunctionKeys (4 bytes) */ } stream_seek(s, 64); /* imeFileName (64 bytes) */ if (settings->server_mode != true) { if (inputFlags & INPUT_FLAG_FASTPATH_INPUT) { /* advertised by RDP 5.0 and 5.1 servers */ } else if (inputFlags & INPUT_FLAG_FASTPATH_INPUT2) { /* avertised by RDP 5.2, 6.0, 6.1 and 7.0 servers */ } else { /* server does not support fastpath input */ settings->fastpath_input = false; } } } /** * Write input capability set.\n * @msdn{cc240563} * @param s stream * @param settings settings */ void rdp_write_input_capability_set(STREAM* s, rdpSettings* settings) { uint8* header; uint16 inputFlags; header = rdp_capability_set_start(s); inputFlags = INPUT_FLAG_SCANCODES | INPUT_FLAG_MOUSEX | INPUT_FLAG_UNICODE; if (settings->fastpath_input) { inputFlags |= INPUT_FLAG_FASTPATH_INPUT; inputFlags |= INPUT_FLAG_FASTPATH_INPUT2; } stream_write_uint16(s, inputFlags); /* inputFlags (2 bytes) */ stream_write_uint16(s, 0); /* pad2OctetsA (2 bytes) */ stream_write_uint32(s, settings->kbd_layout); /* keyboardLayout (4 bytes) */ stream_write_uint32(s, settings->kbd_type); /* keyboardType (4 bytes) */ stream_write_uint32(s, settings->kbd_subtype); /* keyboardSubType (4 bytes) */ stream_write_uint32(s, settings->kbd_fn_keys); /* keyboardFunctionKeys (4 bytes) */ stream_write_zero(s, 64); /* imeFileName (64 bytes) */ rdp_capability_set_finish(s, header, CAPSET_TYPE_INPUT); } /** * Read font capability set.\n * @msdn{cc240571} * @param s stream * @param settings settings */ void rdp_read_font_capability_set(STREAM* s, uint16 length, rdpSettings* settings) { if (length > 4) stream_seek_uint16(s); /* fontSupportFlags (2 bytes) */ if (length > 6) stream_seek_uint16(s); /* pad2Octets (2 bytes) */ } /** * Write font capability set.\n * @msdn{cc240571} * @param s stream * @param settings settings */ void rdp_write_font_capability_set(STREAM* s, rdpSettings* settings) { uint8* header; header = rdp_capability_set_start(s); stream_write_uint16(s, FONTSUPPORT_FONTLIST); /* fontSupportFlags (2 bytes) */ stream_write_uint16(s, 0); /* pad2Octets (2 bytes) */ rdp_capability_set_finish(s, header, CAPSET_TYPE_FONT); } /** * Read brush capability set.\n * @msdn{cc240564} * @param s stream * @param settings settings */ void rdp_read_brush_capability_set(STREAM* s, uint16 length, rdpSettings* settings) { stream_seek_uint32(s); /* brushSupportLevel (4 bytes) */ } /** * Write brush capability set.\n * @msdn{cc240564} * @param s stream * @param settings settings */ void rdp_write_brush_capability_set(STREAM* s, rdpSettings* settings) { uint8* header; header = rdp_capability_set_start(s); stream_write_uint32(s, BRUSH_COLOR_FULL); /* brushSupportLevel (4 bytes) */ rdp_capability_set_finish(s, header, CAPSET_TYPE_BRUSH); } /** * Read cache definition (glyph).\n * @msdn{cc240566} * @param s stream */ void rdp_read_cache_definition(STREAM* s, GLYPH_CACHE_DEFINITION* cache_definition) { stream_read_uint16(s, cache_definition->cacheEntries); /* cacheEntries (2 bytes) */ stream_read_uint16(s, cache_definition->cacheMaximumCellSize); /* cacheMaximumCellSize (2 bytes) */ } /** * Write cache definition (glyph).\n * @msdn{cc240566} * @param s stream */ void rdp_write_cache_definition(STREAM* s, GLYPH_CACHE_DEFINITION* cache_definition) { stream_write_uint16(s, cache_definition->cacheEntries); /* cacheEntries (2 bytes) */ stream_write_uint16(s, cache_definition->cacheMaximumCellSize); /* cacheMaximumCellSize (2 bytes) */ } /** * Read glyph cache capability set.\n * @msdn{cc240565} * @param s stream * @param settings settings */ void rdp_read_glyph_cache_capability_set(STREAM* s, uint16 length, rdpSettings* settings) { uint16 glyphSupportLevel; stream_seek(s, 40); /* glyphCache (40 bytes) */ stream_seek_uint32(s); /* fragCache (4 bytes) */ stream_read_uint16(s, glyphSupportLevel); /* glyphSupportLevel (2 bytes) */ stream_seek_uint16(s); /* pad2Octets (2 bytes) */ settings->glyphSupportLevel = glyphSupportLevel; } /** * Write glyph cache capability set.\n * @msdn{cc240565} * @param s stream * @param settings settings */ void rdp_write_glyph_cache_capability_set(STREAM* s, rdpSettings* settings) { uint8* header; header = rdp_capability_set_start(s); /* glyphCache (40 bytes) */ rdp_write_cache_definition(s, &(settings->glyphCache[0])); /* glyphCache0 (4 bytes) */ rdp_write_cache_definition(s, &(settings->glyphCache[1])); /* glyphCache1 (4 bytes) */ rdp_write_cache_definition(s, &(settings->glyphCache[2])); /* glyphCache2 (4 bytes) */ rdp_write_cache_definition(s, &(settings->glyphCache[3])); /* glyphCache3 (4 bytes) */ rdp_write_cache_definition(s, &(settings->glyphCache[4])); /* glyphCache4 (4 bytes) */ rdp_write_cache_definition(s, &(settings->glyphCache[5])); /* glyphCache5 (4 bytes) */ rdp_write_cache_definition(s, &(settings->glyphCache[6])); /* glyphCache6 (4 bytes) */ rdp_write_cache_definition(s, &(settings->glyphCache[7])); /* glyphCache7 (4 bytes) */ rdp_write_cache_definition(s, &(settings->glyphCache[8])); /* glyphCache8 (4 bytes) */ rdp_write_cache_definition(s, &(settings->glyphCache[9])); /* glyphCache9 (4 bytes) */ rdp_write_cache_definition(s, settings->fragCache); /* fragCache (4 bytes) */ stream_write_uint16(s, settings->glyphSupportLevel); /* glyphSupportLevel (2 bytes) */ stream_write_uint16(s, 0); /* pad2Octets (2 bytes) */ rdp_capability_set_finish(s, header, CAPSET_TYPE_GLYPH_CACHE); } /** * Read offscreen bitmap cache capability set.\n * @msdn{cc240550} * @param s stream * @param settings settings */ void rdp_read_offscreen_bitmap_cache_capability_set(STREAM* s, uint16 length, rdpSettings* settings) { uint32 offscreenSupportLevel; stream_read_uint32(s, offscreenSupportLevel); /* offscreenSupportLevel (4 bytes) */ stream_read_uint16(s, settings->offscreen_bitmap_cache_size); /* offscreenCacheSize (2 bytes) */ stream_read_uint16(s, settings->offscreen_bitmap_cache_entries); /* offscreenCacheEntries (2 bytes) */ if (offscreenSupportLevel & true) settings->offscreen_bitmap_cache = true; } /** * Write offscreen bitmap cache capability set.\n * @msdn{cc240550} * @param s stream * @param settings settings */ void rdp_write_offscreen_bitmap_cache_capability_set(STREAM* s, rdpSettings* settings) { uint8* header; uint32 offscreenSupportLevel = false; header = rdp_capability_set_start(s); if (settings->offscreen_bitmap_cache) offscreenSupportLevel = true; stream_write_uint32(s, offscreenSupportLevel); /* offscreenSupportLevel (4 bytes) */ stream_write_uint16(s, settings->offscreen_bitmap_cache_size); /* offscreenCacheSize (2 bytes) */ stream_write_uint16(s, settings->offscreen_bitmap_cache_entries); /* offscreenCacheEntries (2 bytes) */ rdp_capability_set_finish(s, header, CAPSET_TYPE_OFFSCREEN_CACHE); } /** * Read bitmap cache host support capability set.\n * @msdn{cc240557} * @param s stream * @param settings settings */ void rdp_read_bitmap_cache_host_support_capability_set(STREAM* s, uint16 length, rdpSettings* settings) { uint8 cacheVersion; stream_read_uint8(s, cacheVersion); /* cacheVersion (1 byte) */ stream_seek_uint8(s); /* pad1 (1 byte) */ stream_seek_uint16(s); /* pad2 (2 bytes) */ if (cacheVersion & BITMAP_CACHE_V2) settings->persistent_bitmap_cache = true; } /** * Write bitmap cache host support capability set.\n * @msdn{cc240557} * @param s stream * @param settings settings */ void rdp_write_bitmap_cache_host_support_capability_set(STREAM* s, rdpSettings* settings) { uint8* header; header = rdp_capability_set_start(s); stream_write_uint8(s, BITMAP_CACHE_V2); /* cacheVersion (1 byte) */ stream_write_uint8(s, 0); /* pad1 (1 byte) */ stream_write_uint16(s, 0); /* pad2 (2 bytes) */ rdp_capability_set_finish(s, header, CAPSET_TYPE_BITMAP_CACHE_HOST_SUPPORT); } void rdp_write_bitmap_cache_cell_info(STREAM* s, BITMAP_CACHE_V2_CELL_INFO* cellInfo) { uint32 info; /** * numEntries is in the first 31 bits, while the last bit (k) * is used to indicate a persistent bitmap cache. */ info = (cellInfo->numEntries | (cellInfo->persistent << 31)); stream_write_uint32(s, info); } /** * Read bitmap cache v2 capability set.\n * @msdn{cc240560} * @param s stream * @param settings settings */ void rdp_read_bitmap_cache_v2_capability_set(STREAM* s, uint16 length, rdpSettings* settings) { stream_seek_uint16(s); /* cacheFlags (2 bytes) */ stream_seek_uint8(s); /* pad2 (1 byte) */ stream_seek_uint8(s); /* numCellCaches (1 byte) */ stream_seek(s, 4); /* bitmapCache0CellInfo (4 bytes) */ stream_seek(s, 4); /* bitmapCache1CellInfo (4 bytes) */ stream_seek(s, 4); /* bitmapCache2CellInfo (4 bytes) */ stream_seek(s, 4); /* bitmapCache3CellInfo (4 bytes) */ stream_seek(s, 4); /* bitmapCache4CellInfo (4 bytes) */ stream_seek(s, 12); /* pad3 (12 bytes) */ } /** * Write bitmap cache v2 capability set.\n * @msdn{cc240560} * @param s stream * @param settings settings */ void rdp_write_bitmap_cache_v2_capability_set(STREAM* s, rdpSettings* settings) { uint8* header; uint16 cacheFlags; header = rdp_capability_set_start(s); cacheFlags = ALLOW_CACHE_WAITING_LIST_FLAG; if (settings->persistent_bitmap_cache) cacheFlags |= PERSISTENT_KEYS_EXPECTED_FLAG; stream_write_uint16(s, cacheFlags); /* cacheFlags (2 bytes) */ stream_write_uint8(s, 0); /* pad2 (1 byte) */ stream_write_uint8(s, settings->bitmapCacheV2NumCells); /* numCellCaches (1 byte) */ rdp_write_bitmap_cache_cell_info(s, &settings->bitmapCacheV2CellInfo[0]); /* bitmapCache0CellInfo (4 bytes) */ rdp_write_bitmap_cache_cell_info(s, &settings->bitmapCacheV2CellInfo[1]); /* bitmapCache1CellInfo (4 bytes) */ rdp_write_bitmap_cache_cell_info(s, &settings->bitmapCacheV2CellInfo[2]); /* bitmapCache2CellInfo (4 bytes) */ rdp_write_bitmap_cache_cell_info(s, &settings->bitmapCacheV2CellInfo[3]); /* bitmapCache3CellInfo (4 bytes) */ rdp_write_bitmap_cache_cell_info(s, &settings->bitmapCacheV2CellInfo[4]); /* bitmapCache4CellInfo (4 bytes) */ stream_write_zero(s, 12); /* pad3 (12 bytes) */ rdp_capability_set_finish(s, header, CAPSET_TYPE_BITMAP_CACHE_V2); } /** * Read virtual channel capability set.\n * @msdn{cc240551} * @param s stream * @param settings settings */ void rdp_read_virtual_channel_capability_set(STREAM* s, uint16 length, rdpSettings* settings) { uint32 flags; uint32 VCChunkSize; stream_read_uint32(s, flags); /* flags (4 bytes) */ if (length > 8) stream_read_uint32(s, VCChunkSize); /* VCChunkSize (4 bytes) */ else VCChunkSize = 1600; if (settings->server_mode != true) settings->vc_chunk_size = VCChunkSize; } /** * Write virtual channel capability set.\n * @msdn{cc240551} * @param s stream * @param settings settings */ void rdp_write_virtual_channel_capability_set(STREAM* s, rdpSettings* settings) { uint8* header; uint32 flags; header = rdp_capability_set_start(s); flags = (settings->server_mode) ? VCCAPS_COMPR_CS_8K : VCCAPS_NO_COMPR; stream_write_uint32(s, flags); /* flags (4 bytes) */ stream_write_uint32(s, settings->vc_chunk_size); /* VCChunkSize (4 bytes) */ rdp_capability_set_finish(s, header, CAPSET_TYPE_VIRTUAL_CHANNEL); } /** * Read drawn nine grid cache capability set.\n * @msdn{cc241565} * @param s stream * @param settings settings */ void rdp_read_draw_nine_grid_cache_capability_set(STREAM* s, uint16 length, rdpSettings* settings) { uint32 drawNineGridSupportLevel; stream_read_uint32(s, drawNineGridSupportLevel); /* drawNineGridSupportLevel (4 bytes) */ stream_read_uint16(s, settings->draw_nine_grid_cache_size); /* drawNineGridCacheSize (2 bytes) */ stream_read_uint16(s, settings->draw_nine_grid_cache_entries); /* drawNineGridCacheEntries (2 bytes) */ if ((drawNineGridSupportLevel & DRAW_NINEGRID_SUPPORTED) || (drawNineGridSupportLevel & DRAW_NINEGRID_SUPPORTED_V2)) settings->draw_nine_grid = true; } /** * Write drawn nine grid cache capability set.\n * @msdn{cc241565} * @param s stream * @param settings settings */ void rdp_write_draw_nine_grid_cache_capability_set(STREAM* s, rdpSettings* settings) { uint8* header; uint32 drawNineGridSupportLevel; header = rdp_capability_set_start(s); drawNineGridSupportLevel = (settings->draw_nine_grid) ? DRAW_NINEGRID_SUPPORTED : DRAW_NINEGRID_NO_SUPPORT; stream_write_uint32(s, drawNineGridSupportLevel); /* drawNineGridSupportLevel (4 bytes) */ stream_write_uint16(s, settings->draw_nine_grid_cache_size); /* drawNineGridCacheSize (2 bytes) */ stream_write_uint16(s, settings->draw_nine_grid_cache_entries); /* drawNineGridCacheEntries (2 bytes) */ rdp_capability_set_finish(s, header, CAPSET_TYPE_DRAW_NINE_GRID_CACHE); } void rdp_write_gdiplus_cache_entries(STREAM* s, uint16 gce, uint16 bce, uint16 pce, uint16 ice, uint16 ace) { stream_write_uint16(s, gce); /* gdipGraphicsCacheEntries (2 bytes) */ stream_write_uint16(s, bce); /* gdipBrushCacheEntries (2 bytes) */ stream_write_uint16(s, pce); /* gdipPenCacheEntries (2 bytes) */ stream_write_uint16(s, ice); /* gdipImageCacheEntries (2 bytes) */ stream_write_uint16(s, ace); /* gdipImageAttributesCacheEntries (2 bytes) */ } void rdp_write_gdiplus_cache_chunk_size(STREAM* s, uint16 gccs, uint16 obccs, uint16 opccs, uint16 oiaccs) { stream_write_uint16(s, gccs); /* gdipGraphicsCacheChunkSize (2 bytes) */ stream_write_uint16(s, obccs); /* gdipObjectBrushCacheChunkSize (2 bytes) */ stream_write_uint16(s, opccs); /* gdipObjectPenCacheChunkSize (2 bytes) */ stream_write_uint16(s, oiaccs); /* gdipObjectImageAttributesCacheChunkSize (2 bytes) */ } void rdp_write_gdiplus_image_cache_properties(STREAM* s, uint16 oiccs, uint16 oicts, uint16 oicms) { stream_write_uint16(s, oiccs); /* gdipObjectImageCacheChunkSize (2 bytes) */ stream_write_uint16(s, oicts); /* gdipObjectImageCacheTotalSize (2 bytes) */ stream_write_uint16(s, oicms); /* gdipObjectImageCacheMaxSize (2 bytes) */ } /** * Read GDI+ cache capability set.\n * @msdn{cc241566} * @param s stream * @param settings settings */ void rdp_read_draw_gdiplus_cache_capability_set(STREAM* s, uint16 length, rdpSettings* settings) { uint32 drawGDIPlusSupportLevel; uint32 drawGdiplusCacheLevel; stream_read_uint32(s, drawGDIPlusSupportLevel); /* drawGDIPlusSupportLevel (4 bytes) */ stream_seek_uint32(s); /* GdipVersion (4 bytes) */ stream_read_uint32(s, drawGdiplusCacheLevel); /* drawGdiplusCacheLevel (4 bytes) */ stream_seek(s, 10); /* GdipCacheEntries (10 bytes) */ stream_seek(s, 8); /* GdipCacheChunkSize (8 bytes) */ stream_seek(s, 6); /* GdipImageCacheProperties (6 bytes) */ if (drawGDIPlusSupportLevel & DRAW_GDIPLUS_SUPPORTED) settings->draw_gdi_plus = true; if (drawGdiplusCacheLevel & DRAW_GDIPLUS_CACHE_LEVEL_ONE) settings->draw_gdi_plus_cache = true; } /** * Write GDI+ cache capability set.\n * @msdn{cc241566} * @param s stream * @param settings settings */ void rdp_write_draw_gdiplus_cache_capability_set(STREAM* s, rdpSettings* settings) { uint8* header; uint32 drawGDIPlusSupportLevel; uint32 drawGdiplusCacheLevel; header = rdp_capability_set_start(s); drawGDIPlusSupportLevel = (settings->draw_gdi_plus) ? DRAW_GDIPLUS_SUPPORTED : DRAW_GDIPLUS_DEFAULT; drawGdiplusCacheLevel = (settings->draw_gdi_plus) ? DRAW_GDIPLUS_CACHE_LEVEL_ONE : DRAW_GDIPLUS_CACHE_LEVEL_DEFAULT; stream_write_uint32(s, drawGDIPlusSupportLevel); /* drawGDIPlusSupportLevel (4 bytes) */ stream_write_uint32(s, 0); /* GdipVersion (4 bytes) */ stream_write_uint32(s, drawGdiplusCacheLevel); /* drawGdiplusCacheLevel (4 bytes) */ rdp_write_gdiplus_cache_entries(s, 10, 5, 5, 10, 2); /* GdipCacheEntries (10 bytes) */ rdp_write_gdiplus_cache_chunk_size(s, 512, 2048, 1024, 64); /* GdipCacheChunkSize (8 bytes) */ rdp_write_gdiplus_image_cache_properties(s, 4096, 256, 128); /* GdipImageCacheProperties (6 bytes) */ rdp_capability_set_finish(s, header, CAPSET_TYPE_DRAW_GDI_PLUS); } /** * Read remote programs capability set.\n * @msdn{cc242518} * @param s stream * @param settings settings */ void rdp_read_remote_programs_capability_set(STREAM* s, uint16 length, rdpSettings* settings) { uint32 railSupportLevel; stream_read_uint32(s, railSupportLevel); /* railSupportLevel (4 bytes) */ if ((railSupportLevel & RAIL_LEVEL_SUPPORTED) == 0) { if (settings->remote_app == true) { /* RemoteApp Failure! */ settings->remote_app = false; } } } /** * Write remote programs capability set.\n * @msdn{cc242518} * @param s stream * @param settings settings */ void rdp_write_remote_programs_capability_set(STREAM* s, rdpSettings* settings) { uint8* header; uint32 railSupportLevel; header = rdp_capability_set_start(s); railSupportLevel = RAIL_LEVEL_SUPPORTED; if (settings->rail_langbar_supported) railSupportLevel |= RAIL_LEVEL_DOCKED_LANGBAR_SUPPORTED; stream_write_uint32(s, railSupportLevel); /* railSupportLevel (4 bytes) */ rdp_capability_set_finish(s, header, CAPSET_TYPE_RAIL); } /** * Read window list capability set.\n * @msdn{cc242564} * @param s stream * @param settings settings */ void rdp_read_window_list_capability_set(STREAM* s, uint16 length, rdpSettings* settings) { stream_seek_uint32(s); /* wndSupportLevel (4 bytes) */ stream_seek_uint8(s); /* numIconCaches (1 byte) */ stream_seek_uint16(s); /* numIconCacheEntries (2 bytes) */ } /** * Write window list capability set.\n * @msdn{cc242564} * @param s stream * @param settings settings */ void rdp_write_window_list_capability_set(STREAM* s, rdpSettings* settings) { uint8* header; uint32 wndSupportLevel; header = rdp_capability_set_start(s); wndSupportLevel = WINDOW_LEVEL_SUPPORTED_EX; stream_write_uint32(s, wndSupportLevel); /* wndSupportLevel (4 bytes) */ stream_write_uint8(s, settings->num_icon_caches); /* numIconCaches (1 byte) */ stream_write_uint16(s, settings->num_icon_cache_entries); /* numIconCacheEntries (2 bytes) */ rdp_capability_set_finish(s, header, CAPSET_TYPE_WINDOW); } /** * Read desktop composition capability set.\n * @msdn{cc240855} * @param s stream * @param settings settings */ void rdp_read_desktop_composition_capability_set(STREAM* s, uint16 length, rdpSettings* settings) { stream_seek_uint16(s); /* compDeskSupportLevel (2 bytes) */ } /** * Write desktop composition capability set.\n * @msdn{cc240855} * @param s stream * @param settings settings */ void rdp_write_desktop_composition_capability_set(STREAM* s, rdpSettings* settings) { uint8* header; uint16 compDeskSupportLevel; header = rdp_capability_set_start(s); compDeskSupportLevel = (settings->desktop_composition) ? COMPDESK_SUPPORTED : COMPDESK_NOT_SUPPORTED; stream_write_uint16(s, compDeskSupportLevel); /* compDeskSupportLevel (2 bytes) */ rdp_capability_set_finish(s, header, CAPSET_TYPE_COMP_DESK); } /** * Read multifragment update capability set.\n * @msdn{cc240649} * @param s stream * @param settings settings */ void rdp_read_multifragment_update_capability_set(STREAM* s, uint16 length, rdpSettings* settings) { stream_read_uint32(s, settings->multifrag_max_request_size); /* MaxRequestSize (4 bytes) */ } /** * Write multifragment update capability set.\n * @msdn{cc240649} * @param s stream * @param settings settings */ void rdp_write_multifragment_update_capability_set(STREAM* s, rdpSettings* settings) { uint8* header; header = rdp_capability_set_start(s); stream_write_uint32(s, settings->multifrag_max_request_size); /* MaxRequestSize (4 bytes) */ rdp_capability_set_finish(s, header, CAPSET_TYPE_MULTI_FRAGMENT_UPDATE); } /** * Read large pointer capability set.\n * @msdn{cc240650} * @param s stream * @param settings settings */ void rdp_read_large_pointer_capability_set(STREAM* s, uint16 length, rdpSettings* settings) { stream_seek_uint16(s); /* largePointerSupportFlags (2 bytes) */ } /** * Write large pointer capability set.\n * @msdn{cc240650} * @param s stream * @param settings settings */ void rdp_write_large_pointer_capability_set(STREAM* s, rdpSettings* settings) { uint8* header; uint16 largePointerSupportFlags; header = rdp_capability_set_start(s); largePointerSupportFlags = (settings->large_pointer) ? LARGE_POINTER_FLAG_96x96 : 0; stream_write_uint16(s, largePointerSupportFlags); /* largePointerSupportFlags (2 bytes) */ rdp_capability_set_finish(s, header, CAPSET_TYPE_LARGE_POINTER); } /** * Read surface commands capability set.\n * @msdn{dd871563} * @param s stream * @param settings settings */ void rdp_read_surface_commands_capability_set(STREAM* s, uint16 length, rdpSettings* settings) { stream_seek_uint32(s); /* cmdFlags (4 bytes) */ stream_seek_uint32(s); /* reserved (4 bytes) */ settings->surface_commands = true; } /** * Write surface commands capability set.\n * @msdn{dd871563} * @param s stream * @param settings settings */ void rdp_write_surface_commands_capability_set(STREAM* s, rdpSettings* settings) { uint8* header; uint32 cmdFlags; header = rdp_capability_set_start(s); cmdFlags = SURFCMDS_FRAME_MARKER | SURFCMDS_SET_SURFACE_BITS | SURFCMDS_STREAM_SURFACE_BITS; stream_write_uint32(s, cmdFlags); /* cmdFlags (4 bytes) */ stream_write_uint32(s, 0); /* reserved (4 bytes) */ rdp_capability_set_finish(s, header, CAPSET_TYPE_SURFACE_COMMANDS); } /** * Read bitmap codecs capability set.\n * @msdn{dd891377} * @param s stream * @param settings settings */ void rdp_read_bitmap_codecs_capability_set(STREAM* s, uint16 length, rdpSettings* settings) { uint8 bitmapCodecCount; uint16 codecPropertiesLength; stream_read_uint8(s, bitmapCodecCount); /* bitmapCodecCount (1 byte) */ if (settings->server_mode) { settings->rfx_codec = false; settings->ns_codec = false; } while (bitmapCodecCount > 0) { if (settings->server_mode && strncmp((char*)stream_get_tail(s), CODEC_GUID_REMOTEFX, 16) == 0) { stream_seek(s, 16); /* codecGUID (16 bytes) */ stream_read_uint8(s, settings->rfx_codec_id); settings->rfx_codec = true; } else if (settings->server_mode && strncmp((char*)stream_get_tail(s),CODEC_GUID_NSCODEC, 16) == 0) { stream_seek(s, 16); /*codec GUID (16 bytes) */ stream_read_uint8(s, settings->ns_codec_id); settings->ns_codec = true; } else { stream_seek(s, 16); /* codecGUID (16 bytes) */ stream_seek_uint8(s); /* codecID (1 byte) */ } stream_read_uint16(s, codecPropertiesLength); /* codecPropertiesLength (2 bytes) */ stream_seek(s, codecPropertiesLength); /* codecProperties */ bitmapCodecCount--; } } /** * Write RemoteFX Client Capability Container.\n * @param s stream * @param settings settings */ void rdp_write_rfx_client_capability_container(STREAM* s, rdpSettings* settings) { uint32 captureFlags; uint8 codecMode; captureFlags = settings->dump_rfx ? 0 : CARDP_CAPS_CAPTURE_NON_CAC; codecMode = settings->rfx_codec_mode; stream_write_uint16(s, 49); /* codecPropertiesLength */ /* TS_RFX_CLNT_CAPS_CONTAINER */ stream_write_uint32(s, 49); /* length */ stream_write_uint32(s, captureFlags); /* captureFlags */ stream_write_uint32(s, 37); /* capsLength */ /* TS_RFX_CAPS */ stream_write_uint16(s, CBY_CAPS); /* blockType */ stream_write_uint32(s, 8); /* blockLen */ stream_write_uint16(s, 1); /* numCapsets */ /* TS_RFX_CAPSET */ stream_write_uint16(s, CBY_CAPSET); /* blockType */ stream_write_uint32(s, 29); /* blockLen */ stream_write_uint8(s, 0x01); /* codecId (MUST be set to 0x01) */ stream_write_uint16(s, CLY_CAPSET); /* capsetType */ stream_write_uint16(s, 2); /* numIcaps */ stream_write_uint16(s, 8); /* icapLen */ /* TS_RFX_ICAP (RLGR1) */ stream_write_uint16(s, CLW_VERSION_1_0); /* version */ stream_write_uint16(s, CT_TILE_64x64); /* tileSize */ stream_write_uint8(s, codecMode); /* flags */ stream_write_uint8(s, CLW_COL_CONV_ICT); /* colConvBits */ stream_write_uint8(s, CLW_XFORM_DWT_53_A); /* transformBits */ stream_write_uint8(s, CLW_ENTROPY_RLGR1); /* entropyBits */ /* TS_RFX_ICAP (RLGR3) */ stream_write_uint16(s, CLW_VERSION_1_0); /* version */ stream_write_uint16(s, CT_TILE_64x64); /* tileSize */ stream_write_uint8(s, codecMode); /* flags */ stream_write_uint8(s, CLW_COL_CONV_ICT); /* colConvBits */ stream_write_uint8(s, CLW_XFORM_DWT_53_A); /* transformBits */ stream_write_uint8(s, CLW_ENTROPY_RLGR3); /* entropyBits */ } /** * Write NSCODEC Client Capability Container.\n * @param s stream * @param settings settings */ void rdp_write_nsc_client_capability_container(STREAM* s, rdpSettings* settings) { stream_write_uint16(s, 3); /* codecPropertiesLength */ /* TS_NSCODEC_CAPABILITYSET */ stream_write_uint8(s, 1); /* fAllowDynamicFidelity */ stream_write_uint8(s, 1); /* fAllowSubsampling */ stream_write_uint8(s, 3); /* colorLossLevel */ } /** * Write RemoteFX Server Capability Container.\n * @param s stream * @param settings settings */ void rdp_write_rfx_server_capability_container(STREAM* s, rdpSettings* settings) { stream_write_uint16(s, 4); /* codecPropertiesLength */ stream_write_uint32(s, 0); /* reserved */ } /** * Write NSCODEC Server Capability Container.\n * @param s stream * @param settings settings */ void rdp_write_nsc_server_capability_container(STREAM* s, rdpSettings* settings) { stream_write_uint16(s, 4); /* codecPropertiesLength */ stream_write_uint32(s, 0); /* reserved */ } /** * Write bitmap codecs capability set.\n * @msdn{dd891377} * @param s stream * @param settings settings */ void rdp_write_bitmap_codecs_capability_set(STREAM* s, rdpSettings* settings) { uint8* header; uint8 bitmapCodecCount; header = rdp_capability_set_start(s); bitmapCodecCount = 0; if (settings->rfx_codec) bitmapCodecCount++; if (settings->ns_codec) bitmapCodecCount++; stream_write_uint8(s, bitmapCodecCount); if (settings->rfx_codec) { stream_write(s, CODEC_GUID_REMOTEFX, 16); /* codecGUID */ if (settings->server_mode) { stream_write_uint8(s, 0); /* codecID is defined by the client */ rdp_write_rfx_server_capability_container(s, settings); } else { stream_write_uint8(s, CODEC_ID_REMOTEFX); /* codecID */ rdp_write_rfx_client_capability_container(s, settings); } } if (settings->ns_codec) { stream_write(s, CODEC_GUID_NSCODEC, 16); if (settings->server_mode) { stream_write_uint8(s, 0); /* codecID is defined by the client */ rdp_write_nsc_server_capability_container(s, settings); } else { stream_write_uint8(s, CODEC_ID_NSCODEC); /* codecID */ rdp_write_nsc_client_capability_container(s, settings); } } rdp_capability_set_finish(s, header, CAPSET_TYPE_BITMAP_CODECS); } /** * Read frame acknowledge capability set.\n * @param s stream * @param settings settings */ void rdp_read_frame_acknowledge_capability_set(STREAM* s, uint16 length, rdpSettings* settings) { stream_seek_uint32(s); /* (4 bytes) */ } /** * Write frame acknowledge capability set.\n * @param s stream * @param settings settings */ void rdp_write_frame_acknowledge_capability_set(STREAM* s, rdpSettings* settings) { uint8* header; header = rdp_capability_set_start(s); stream_write_uint32(s, 2); /* (4 bytes) */ rdp_capability_set_finish(s, header, CAPSET_TYPE_FRAME_ACKNOWLEDGE); } boolean rdp_read_capability_sets(STREAM* s, rdpSettings* settings, uint16 numberCapabilities) { uint16 type; uint16 length; uint8 *bm, *em; while (numberCapabilities > 0) { stream_get_mark(s, bm); rdp_read_capability_set_header(s, &length, &type); //printf("%s Capability Set (0x%02X), length:%d\n", CAPSET_TYPE_STRINGS[type], type, length); settings->received_caps[type] = true; em = bm + length; if (stream_get_left(s) < length - 4) { printf("error processing stream\n"); return false; } switch (type) { case CAPSET_TYPE_GENERAL: rdp_read_general_capability_set(s, length, settings); break; case CAPSET_TYPE_BITMAP: rdp_read_bitmap_capability_set(s, length, settings); break; case CAPSET_TYPE_ORDER: rdp_read_order_capability_set(s, length, settings); break; case CAPSET_TYPE_BITMAP_CACHE: rdp_read_bitmap_cache_capability_set(s, length, settings); break; case CAPSET_TYPE_CONTROL: rdp_read_control_capability_set(s, length, settings); break; case CAPSET_TYPE_ACTIVATION: rdp_read_window_activation_capability_set(s, length, settings); break; case CAPSET_TYPE_POINTER: rdp_read_pointer_capability_set(s, length, settings); break; case CAPSET_TYPE_SHARE: rdp_read_share_capability_set(s, length, settings); break; case CAPSET_TYPE_COLOR_CACHE: rdp_read_color_cache_capability_set(s, length, settings); break; case CAPSET_TYPE_SOUND: rdp_read_sound_capability_set(s, length, settings); break; case CAPSET_TYPE_INPUT: rdp_read_input_capability_set(s, length, settings); break; case CAPSET_TYPE_FONT: rdp_read_font_capability_set(s, length, settings); break; case CAPSET_TYPE_BRUSH: rdp_read_brush_capability_set(s, length, settings); break; case CAPSET_TYPE_GLYPH_CACHE: rdp_read_glyph_cache_capability_set(s, length, settings); break; case CAPSET_TYPE_OFFSCREEN_CACHE: rdp_read_offscreen_bitmap_cache_capability_set(s, length, settings); break; case CAPSET_TYPE_BITMAP_CACHE_HOST_SUPPORT: rdp_read_bitmap_cache_host_support_capability_set(s, length, settings); break; case CAPSET_TYPE_BITMAP_CACHE_V2: rdp_read_bitmap_cache_v2_capability_set(s, length, settings); break; case CAPSET_TYPE_VIRTUAL_CHANNEL: rdp_read_virtual_channel_capability_set(s, length, settings); break; case CAPSET_TYPE_DRAW_NINE_GRID_CACHE: rdp_read_draw_nine_grid_cache_capability_set(s, length, settings); break; case CAPSET_TYPE_DRAW_GDI_PLUS: rdp_read_draw_gdiplus_cache_capability_set(s, length, settings); break; case CAPSET_TYPE_RAIL: rdp_read_remote_programs_capability_set(s, length, settings); break; case CAPSET_TYPE_WINDOW: rdp_read_window_list_capability_set(s, length, settings); break; case CAPSET_TYPE_COMP_DESK: rdp_read_desktop_composition_capability_set(s, length, settings); break; case CAPSET_TYPE_MULTI_FRAGMENT_UPDATE: rdp_read_multifragment_update_capability_set(s, length, settings); break; case CAPSET_TYPE_LARGE_POINTER: rdp_read_large_pointer_capability_set(s, length, settings); break; case CAPSET_TYPE_SURFACE_COMMANDS: rdp_read_surface_commands_capability_set(s, length, settings); break; case CAPSET_TYPE_BITMAP_CODECS: rdp_read_bitmap_codecs_capability_set(s, length, settings); break; case CAPSET_TYPE_FRAME_ACKNOWLEDGE: rdp_read_frame_acknowledge_capability_set(s, length, settings); break; default: printf("unknown capability type %d\n", type); break; } if (s->p != em) { printf("incorrect offset, type:0x%02X actual:%d expected:%d\n", type, (int) (s->p - bm), (int) (em - bm)); } stream_set_mark(s, em); numberCapabilities--; } return true; } boolean rdp_recv_demand_active(rdpRdp* rdp, STREAM* s) { uint16 length; uint16 channelId; uint16 pduType; uint16 pduLength; uint16 pduSource; uint16 numberCapabilities; uint16 lengthSourceDescriptor; uint16 lengthCombinedCapabilities; uint16 securityFlags; if (!rdp_read_header(rdp, s, &length, &channelId)) return false; if (rdp->disconnect) return true; if (rdp->settings->encryption) { rdp_read_security_header(s, &securityFlags); if (securityFlags & SEC_ENCRYPT) { if (!rdp_decrypt(rdp, s, length - 4, securityFlags)) { printf("rdp_decrypt failed\n"); return false; } } } if (channelId != MCS_GLOBAL_CHANNEL_ID) { printf("channelId bad\n"); return false; } if (!rdp_read_share_control_header(s, &pduLength, &pduType, &pduSource)) { printf("rdp_read_share_control_header failed\n"); return false; } rdp->settings->pdu_source = pduSource; if (pduType != PDU_TYPE_DEMAND_ACTIVE) { printf("pduType bad\n"); return false; } stream_read_uint32(s, rdp->settings->share_id); /* shareId (4 bytes) */ stream_read_uint16(s, lengthSourceDescriptor); /* lengthSourceDescriptor (2 bytes) */ stream_read_uint16(s, lengthCombinedCapabilities); /* lengthCombinedCapabilities (2 bytes) */ stream_seek(s, lengthSourceDescriptor); /* sourceDescriptor */ stream_read_uint16(s, numberCapabilities); /* numberCapabilities (2 bytes) */ stream_seek(s, 2); /* pad2Octets (2 bytes) */ /* capabilitySets */ if (!rdp_read_capability_sets(s, rdp->settings, numberCapabilities)) { printf("rdp_read_capability_sets failed\n"); return false; } rdp->update->secondary->glyph_v2 = (rdp->settings->glyphSupportLevel > GLYPH_SUPPORT_FULL) ? true : false; return true; } void rdp_write_demand_active(STREAM* s, rdpSettings* settings) { uint8 *bm, *em, *lm; uint16 numberCapabilities; uint16 lengthCombinedCapabilities; stream_write_uint32(s, settings->share_id); /* shareId (4 bytes) */ stream_write_uint16(s, 4); /* lengthSourceDescriptor (2 bytes) */ stream_get_mark(s, lm); stream_seek_uint16(s); /* lengthCombinedCapabilities (2 bytes) */ stream_write(s, "RDP", 4); /* sourceDescriptor */ stream_get_mark(s, bm); stream_seek_uint16(s); /* numberCapabilities (2 bytes) */ stream_write_uint16(s, 0); /* pad2Octets (2 bytes) */ numberCapabilities = 13; rdp_write_general_capability_set(s, settings); rdp_write_bitmap_capability_set(s, settings); rdp_write_order_capability_set(s, settings); rdp_write_pointer_capability_set(s, settings); rdp_write_input_capability_set(s, settings); rdp_write_virtual_channel_capability_set(s, settings); rdp_write_share_capability_set(s, settings); rdp_write_font_capability_set(s, settings); rdp_write_multifragment_update_capability_set(s, settings); rdp_write_large_pointer_capability_set(s, settings); rdp_write_desktop_composition_capability_set(s, settings); rdp_write_surface_commands_capability_set(s, settings); rdp_write_bitmap_codecs_capability_set(s, settings); if (settings->persistent_bitmap_cache) { numberCapabilities++; rdp_write_bitmap_cache_host_support_capability_set(s, settings); } stream_get_mark(s, em); stream_set_mark(s, lm); /* go back to lengthCombinedCapabilities */ lengthCombinedCapabilities = (em - bm); stream_write_uint16(s, lengthCombinedCapabilities); /* lengthCombinedCapabilities (2 bytes) */ stream_set_mark(s, bm); /* go back to numberCapabilities */ stream_write_uint16(s, numberCapabilities); /* numberCapabilities (2 bytes) */ stream_set_mark(s, em); stream_write_uint32(s, 0); /* sessionId */ } boolean rdp_send_demand_active(rdpRdp* rdp) { STREAM* s; s = rdp_pdu_init(rdp); rdp->settings->share_id = 0x10000 + rdp->mcs->user_id; rdp_write_demand_active(s, rdp->settings); rdp_send_pdu(rdp, s, PDU_TYPE_DEMAND_ACTIVE, rdp->mcs->user_id); return true; } boolean rdp_recv_confirm_active(rdpRdp* rdp, STREAM* s) { uint16 length; uint16 channelId; uint16 pduType; uint16 pduLength; uint16 pduSource; uint16 lengthSourceDescriptor; uint16 lengthCombinedCapabilities; uint16 numberCapabilities; uint16 securityFlags; if (!rdp_read_header(rdp, s, &length, &channelId)) return false; if (rdp->settings->encryption) { rdp_read_security_header(s, &securityFlags); if (securityFlags & SEC_ENCRYPT) { if (!rdp_decrypt(rdp, s, length - 4, securityFlags)) { printf("rdp_decrypt failed\n"); return false; } } } if (channelId != MCS_GLOBAL_CHANNEL_ID) return false; if (!rdp_read_share_control_header(s, &pduLength, &pduType, &pduSource)) return false; rdp->settings->pdu_source = pduSource; if (pduType != PDU_TYPE_CONFIRM_ACTIVE) return false; stream_seek_uint32(s); /* shareId (4 bytes) */ stream_seek_uint16(s); /* originatorId (2 bytes) */ stream_read_uint16(s, lengthSourceDescriptor); /* lengthSourceDescriptor (2 bytes) */ stream_read_uint16(s, lengthCombinedCapabilities); /* lengthCombinedCapabilities (2 bytes) */ stream_seek(s, lengthSourceDescriptor); /* sourceDescriptor */ stream_read_uint16(s, numberCapabilities); /* numberCapabilities (2 bytes) */ stream_seek(s, 2); /* pad2Octets (2 bytes) */ if (!rdp_read_capability_sets(s, rdp->settings, numberCapabilities)) return false; return true; } void rdp_write_confirm_active(STREAM* s, rdpSettings* settings) { uint8 *bm, *em, *lm; uint16 numberCapabilities; uint16 lengthSourceDescriptor; uint16 lengthCombinedCapabilities; lengthSourceDescriptor = sizeof(SOURCE_DESCRIPTOR); stream_write_uint32(s, settings->share_id); /* shareId (4 bytes) */ stream_write_uint16(s, 0x03EA); /* originatorId (2 bytes) */ stream_write_uint16(s, lengthSourceDescriptor);/* lengthSourceDescriptor (2 bytes) */ stream_get_mark(s, lm); stream_seek_uint16(s); /* lengthCombinedCapabilities (2 bytes) */ stream_write(s, SOURCE_DESCRIPTOR, lengthSourceDescriptor); /* sourceDescriptor */ stream_get_mark(s, bm); stream_seek_uint16(s); /* numberCapabilities (2 bytes) */ stream_write_uint16(s, 0); /* pad2Octets (2 bytes) */ /* Capability Sets */ numberCapabilities = 15; rdp_write_general_capability_set(s, settings); rdp_write_bitmap_capability_set(s, settings); rdp_write_order_capability_set(s, settings); if (settings->rdp_version >= 5) rdp_write_bitmap_cache_v2_capability_set(s, settings); else rdp_write_bitmap_cache_capability_set(s, settings); rdp_write_pointer_capability_set(s, settings); rdp_write_input_capability_set(s, settings); rdp_write_brush_capability_set(s, settings); rdp_write_glyph_cache_capability_set(s, settings); rdp_write_virtual_channel_capability_set(s, settings); rdp_write_sound_capability_set(s, settings); rdp_write_share_capability_set(s, settings); rdp_write_font_capability_set(s, settings); rdp_write_control_capability_set(s, settings); rdp_write_color_cache_capability_set(s, settings); rdp_write_window_activation_capability_set(s, settings); if (settings->offscreen_bitmap_cache) { numberCapabilities++; rdp_write_offscreen_bitmap_cache_capability_set(s, settings); } if (settings->received_caps[CAPSET_TYPE_LARGE_POINTER]) { if (settings->large_pointer) { numberCapabilities++; rdp_write_large_pointer_capability_set(s, settings); } } if (settings->remote_app) { numberCapabilities += 2; rdp_write_remote_programs_capability_set(s, settings); rdp_write_window_list_capability_set(s, settings); } if (settings->received_caps[CAPSET_TYPE_MULTI_FRAGMENT_UPDATE]) { numberCapabilities++; rdp_write_multifragment_update_capability_set(s, settings); } if (settings->received_caps[CAPSET_TYPE_SURFACE_COMMANDS]) { numberCapabilities++; rdp_write_surface_commands_capability_set(s, settings); } if (settings->received_caps[CAPSET_TYPE_BITMAP_CODECS]) { numberCapabilities++; rdp_write_bitmap_codecs_capability_set(s, settings); } if (settings->received_caps[CAPSET_TYPE_FRAME_ACKNOWLEDGE]) { if (settings->frame_acknowledge) { numberCapabilities++; rdp_write_frame_acknowledge_capability_set(s, settings); } } stream_get_mark(s, em); stream_set_mark(s, lm); /* go back to lengthCombinedCapabilities */ lengthCombinedCapabilities = (em - bm); stream_write_uint16(s, lengthCombinedCapabilities); /* lengthCombinedCapabilities (2 bytes) */ stream_set_mark(s, bm); /* go back to numberCapabilities */ stream_write_uint16(s, numberCapabilities); /* numberCapabilities (2 bytes) */ stream_set_mark(s, em); } boolean rdp_send_confirm_active(rdpRdp* rdp) { STREAM* s; s = rdp_pdu_init(rdp); rdp_write_confirm_active(s, rdp->settings); return rdp_send_pdu(rdp, s, PDU_TYPE_CONFIRM_ACTIVE, rdp->mcs->user_id); } FreeRDP-1.0.2/libfreerdp-core/capabilities.h000066400000000000000000000126201207112532300206040ustar00rootroot00000000000000/** * FreeRDP: A Remote Desktop Protocol Client * RDP Capability Sets * * Copyright 2011 Marc-Andre Moreau * * 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. */ #ifndef __CAPABILITIES_H #define __CAPABILITIES_H #include "rdp.h" #include #include #include #include /* Capability Set Types */ #define CAPSET_TYPE_GENERAL 0x0001 #define CAPSET_TYPE_BITMAP 0x0002 #define CAPSET_TYPE_ORDER 0x0003 #define CAPSET_TYPE_BITMAP_CACHE 0x0004 #define CAPSET_TYPE_CONTROL 0x0005 #define CAPSET_TYPE_ACTIVATION 0x0007 #define CAPSET_TYPE_POINTER 0x0008 #define CAPSET_TYPE_SHARE 0x0009 #define CAPSET_TYPE_COLOR_CACHE 0x000A #define CAPSET_TYPE_SOUND 0x000C #define CAPSET_TYPE_INPUT 0x000D #define CAPSET_TYPE_FONT 0x000E #define CAPSET_TYPE_BRUSH 0x000F #define CAPSET_TYPE_GLYPH_CACHE 0x0010 #define CAPSET_TYPE_OFFSCREEN_CACHE 0x0011 #define CAPSET_TYPE_BITMAP_CACHE_HOST_SUPPORT 0x0012 #define CAPSET_TYPE_BITMAP_CACHE_V2 0x0013 #define CAPSET_TYPE_VIRTUAL_CHANNEL 0x0014 #define CAPSET_TYPE_DRAW_NINE_GRID_CACHE 0x0015 #define CAPSET_TYPE_DRAW_GDI_PLUS 0x0016 #define CAPSET_TYPE_RAIL 0x0017 #define CAPSET_TYPE_WINDOW 0x0018 #define CAPSET_TYPE_COMP_DESK 0x0019 #define CAPSET_TYPE_MULTI_FRAGMENT_UPDATE 0x001A #define CAPSET_TYPE_LARGE_POINTER 0x001B #define CAPSET_TYPE_SURFACE_COMMANDS 0x001C #define CAPSET_TYPE_BITMAP_CODECS 0x001D #define CAPSET_TYPE_FRAME_ACKNOWLEDGE 0x001E #define CAPSET_HEADER_LENGTH 4 #define SOURCE_DESCRIPTOR "FREERDP" /* Capabilities Protocol Version */ #define CAPS_PROTOCOL_VERSION 0x0200 /* General Capability Flags */ #define FASTPATH_OUTPUT_SUPPORTED 0x0001 #define NO_BITMAP_COMPRESSION_HDR 0x0400 #define LONG_CREDENTIALS_SUPPORTED 0x0004 #define AUTORECONNECT_SUPPORTED 0x0008 #define ENC_SALTED_CHECKSUM 0x0010 /* Drawing Flags */ #define DRAW_ALLOW_DYNAMIC_COLOR_FIDELITY 0x02 #define DRAW_ALLOW_COLOR_SUBSAMPLING 0x04 #define DRAW_ALLOW_SKIP_ALPHA 0x08 /* Order Flags */ #define NEGOTIATE_ORDER_SUPPORT 0x0002 #define ZERO_BOUNDS_DELTA_SUPPORT 0x0008 #define COLOR_INDEX_SUPPORT 0x0020 #define SOLID_PATTERN_BRUSH_ONLY 0x0040 #define ORDER_FLAGS_EXTRA_SUPPORT 0x0080 /* Extended Order Flags */ #define CACHE_BITMAP_V3_SUPPORT 0x0002 #define ALTSEC_FRAME_MARKER_SUPPORT 0x0004 /* Sound Flags */ #define SOUND_BEEPS_FLAG 0x0001 /* Input Flags */ #define INPUT_FLAG_SCANCODES 0x0001 #define INPUT_FLAG_MOUSEX 0x0004 #define INPUT_FLAG_FASTPATH_INPUT 0x0008 #define INPUT_FLAG_UNICODE 0x0010 #define INPUT_FLAG_FASTPATH_INPUT2 0x0020 /* Font Support Flags */ #define FONTSUPPORT_FONTLIST 0x0001 /* Brush Support Level */ #define BRUSH_DEFAULT 0x00000000 #define BRUSH_COLOR_8x8 0x00000001 #define BRUSH_COLOR_FULL 0x00000002 /* Bitmap Cache Version */ #define BITMAP_CACHE_V2 0x01 /* Bitmap Cache V2 Flags */ #define PERSISTENT_KEYS_EXPECTED_FLAG 0x0001 #define ALLOW_CACHE_WAITING_LIST_FLAG 0x0002 /* Virtual Channel Flags */ #define VCCAPS_NO_COMPR 0x00000000 #define VCCAPS_COMPR_SC 0x00000001 #define VCCAPS_COMPR_CS_8K 0x00000002 /* Draw Nine Grid Support Level */ #define DRAW_NINEGRID_NO_SUPPORT 0x00000000 #define DRAW_NINEGRID_SUPPORTED 0x00000001 #define DRAW_NINEGRID_SUPPORTED_V2 0x00000002 /* Draw GDI+ Support Level */ #define DRAW_GDIPLUS_DEFAULT 0x00000000 #define DRAW_GDIPLUS_SUPPORTED 0x00000001 /* Draw GDI+ Cache Level */ #define DRAW_GDIPLUS_CACHE_LEVEL_DEFAULT 0x00000000 #define DRAW_GDIPLUS_CACHE_LEVEL_ONE 0x00000001 /* RAIL Support Level */ #define RAIL_LEVEL_SUPPORTED 0x00000001 #define RAIL_LEVEL_DOCKED_LANGBAR_SUPPORTED 0x00000002 /* Window Support Level */ #define WINDOW_LEVEL_NOT_SUPPORTED 0x00000000 #define WINDOW_LEVEL_SUPPORTED 0x00000001 #define WINDOW_LEVEL_SUPPORTED_EX 0x00000002 /* Desktop Composition Support Level */ #define COMPDESK_NOT_SUPPORTED 0x0000 #define COMPDESK_SUPPORTED 0x0001 /* Large Pointer Support Flags */ #define LARGE_POINTER_FLAG_96x96 0x00000001 /* Surface Commands Flags */ #define SURFCMDS_SET_SURFACE_BITS 0x00000002 #define SURFCMDS_FRAME_MARKER 0x00000010 #define SURFCMDS_STREAM_SURFACE_BITS 0x00000040 /* Bitmap Codec Constants */ #define CARDP_CAPS_CAPTURE_NON_CAC 0x00000001 #define CBY_CAPS 0xCBC0 #define CBY_CAPSET 0xCBC1 #define CLY_CAPSET 0xCFC0 #define CLW_VERSION_1_0 0x0100 #define CT_TILE_64x64 0x0040 #define CLW_COL_CONV_ICT 0x1 #define CLW_XFORM_DWT_53_A 0x1 #define CLW_ENTROPY_RLGR1 0x01 #define CLW_ENTROPY_RLGR3 0x04 boolean rdp_recv_demand_active(rdpRdp* rdp, STREAM* s); void rdp_write_demand_active(STREAM* s, rdpSettings* settings); boolean rdp_send_demand_active(rdpRdp* rdp); boolean rdp_recv_confirm_active(rdpRdp* rdp, STREAM* s); void rdp_write_confirm_active(STREAM* s, rdpSettings* settings); boolean rdp_send_confirm_active(rdpRdp* rdp); #endif /* __CAPABILITIES_H */ FreeRDP-1.0.2/libfreerdp-core/certificate.c000066400000000000000000000427341207112532300204410ustar00rootroot00000000000000/** * FreeRDP: A Remote Desktop Protocol Client * Certificate Handling * * Copyright 2011 Jiten Pathy * Copyright 2011 Marc-Andre Moreau * * 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. */ #include #include #include #include #include #include static const char certificate_store_dir[] = "certs"; static const char certificate_known_hosts_file[] = "known_hosts"; #include "certificate.h" /** * * X.509 Certificate Structure * * Certificate ::= SEQUENCE * { * tbsCertificate TBSCertificate, * signatureAlgorithm AlgorithmIdentifier, * signatureValue BIT_STRING * } * * TBSCertificate ::= SEQUENCE * { * version [0] EXPLICIT Version DEFAULT v1, * serialNumber CertificateSerialNumber, * signature AlgorithmIdentifier, * issuer Name, * validity Validity, * subject Name, * subjectPublicKeyInfo SubjectPublicKeyInfo, * issuerUniqueID [1] IMPLICIT UniqueIdentifier OPTIONAL, * subjectUniqueId [2] IMPLICIT UniqueIdentifier OPTIONAL, * extensions [3] EXPLICIT Extensions OPTIONAL * } * * Version ::= INTEGER { v1(0), v2(1), v3(2) } * * CertificateSerialNumber ::= INTEGER * * AlgorithmIdentifier ::= SEQUENCE * { * algorithm OBJECT_IDENTIFIER, * parameters ANY DEFINED BY algorithm OPTIONAL * } * * Name ::= CHOICE { RDNSequence } * * RDNSequence ::= SEQUENCE OF RelativeDistinguishedName * * RelativeDistinguishedName ::= SET OF AttributeTypeAndValue * * AttributeTypeAndValue ::= SEQUENCE * { * type AttributeType, * value AttributeValue * } * * AttributeType ::= OBJECT_IDENTIFIER * * AttributeValue ::= ANY DEFINED BY AttributeType * * Validity ::= SEQUENCE * { * notBefore Time, * notAfter Time * } * * Time ::= CHOICE * { * utcTime UTCTime, * generalTime GeneralizedTime * } * * UniqueIdentifier ::= BIT_STRING * * SubjectPublicKeyInfo ::= SEQUENCE * { * algorithm AlgorithmIdentifier, * subjectPublicKey BIT_STRING * } * * RSAPublicKey ::= SEQUENCE * { * modulus INTEGER * publicExponent INTEGER * } * * Extensions ::= SEQUENCE SIZE (1..MAX) OF Extension * * Extension ::= SEQUENCE * { * extnID OBJECT_IDENTIFIER * critical BOOLEAN DEFAULT FALSE, * extnValue OCTET_STRING * } * */ /** * Read X.509 Certificate * @param certificate certificate module * @param cert X.509 certificate */ void certificate_read_x509_certificate(rdpCertBlob* cert, rdpCertInfo* info) { STREAM* s; int length; uint8 padding; uint32 version; int modulus_length; int exponent_length; s = stream_new(0); stream_attach(s, cert->data, cert->length); ber_read_sequence_tag(s, &length); /* Certificate (SEQUENCE) */ ber_read_sequence_tag(s, &length); /* TBSCertificate (SEQUENCE) */ /* Explicit Contextual Tag [0] */ ber_read_contextual_tag(s, 0, &length, true); ber_read_integer(s, &version); /* version (INTEGER) */ version++; /* serialNumber */ ber_read_integer(s, NULL); /* CertificateSerialNumber (INTEGER) */ /* signature */ ber_read_sequence_tag(s, &length); /* AlgorithmIdentifier (SEQUENCE) */ stream_seek(s, length); /* issuer */ ber_read_sequence_tag(s, &length); /* Name (SEQUENCE) */ stream_seek(s, length); /* validity */ ber_read_sequence_tag(s, &length); /* Validity (SEQUENCE) */ stream_seek(s, length); /* subject */ ber_read_sequence_tag(s, &length); /* Name (SEQUENCE) */ stream_seek(s, length); /* subjectPublicKeyInfo */ ber_read_sequence_tag(s, &length); /* SubjectPublicKeyInfo (SEQUENCE) */ /* subjectPublicKeyInfo::AlgorithmIdentifier */ ber_read_sequence_tag(s, &length); /* AlgorithmIdentifier (SEQUENCE) */ stream_seek(s, length); /* subjectPublicKeyInfo::subjectPublicKey */ ber_read_bit_string(s, &length, &padding); /* BIT_STRING */ /* RSAPublicKey (SEQUENCE) */ ber_read_sequence_tag(s, &length); /* SEQUENCE */ ber_read_integer_length(s, &modulus_length); /* modulus (INTEGER) */ /* skip zero padding, if any */ do { stream_peek_uint8(s, padding); if (padding == 0) { stream_seek(s, 1); modulus_length--; } } while (padding == 0); freerdp_blob_alloc(&info->modulus, modulus_length); stream_read(s, info->modulus.data, modulus_length); ber_read_integer_length(s, &exponent_length); /* publicExponent (INTEGER) */ stream_read(s, &info->exponent[4 - exponent_length], exponent_length); crypto_reverse(info->modulus.data, modulus_length); crypto_reverse(info->exponent, 4); stream_detach(s); stream_free(s); } /** * Instantiate new X.509 Certificate Chain. * @param count certificate chain count * @return new X.509 certificate chain */ rdpX509CertChain* certificate_new_x509_certificate_chain(uint32 count) { rdpX509CertChain* x509_cert_chain; x509_cert_chain = (rdpX509CertChain*) xmalloc(sizeof(rdpX509CertChain)); x509_cert_chain->count = count; x509_cert_chain->array = (rdpCertBlob*) xzalloc(sizeof(rdpCertBlob) * count); return x509_cert_chain; } /** * Free X.509 Certificate Chain. * @param x509_cert_chain X.509 certificate chain to be freed */ void certificate_free_x509_certificate_chain(rdpX509CertChain* x509_cert_chain) { int i; if (x509_cert_chain != NULL) { for (i = 0; i < (int) x509_cert_chain->count; i++) { if (x509_cert_chain->array[i].data != NULL) xfree(x509_cert_chain->array[i].data); } xfree(x509_cert_chain->array); xfree(x509_cert_chain); } } static boolean certificate_process_server_public_key(rdpCertificate* certificate, STREAM* s, uint32 length) { uint8 magic[4]; uint32 keylen; uint32 bitlen; uint32 datalen; uint32 modlen; stream_read(s, magic, 4); if (memcmp(magic, "RSA1", 4) != 0) { printf("gcc_process_server_public_key: magic error\n"); return false; } stream_read_uint32(s, keylen); stream_read_uint32(s, bitlen); stream_read_uint32(s, datalen); stream_read(s, certificate->cert_info.exponent, 4); modlen = keylen - 8; freerdp_blob_alloc(&(certificate->cert_info.modulus), modlen); stream_read(s, certificate->cert_info.modulus.data, modlen); /* 8 bytes of zero padding */ stream_seek(s, 8); return true; } static boolean certificate_process_server_public_signature(rdpCertificate* certificate, uint8* sigdata, int sigdatalen, STREAM* s, uint32 siglen) { uint8 md5hash[CRYPTO_MD5_DIGEST_LENGTH]; uint8 encsig[TSSK_KEY_LENGTH + 8]; uint8 sig[TSSK_KEY_LENGTH]; CryptoMd5 md5ctx; int i, sum; md5ctx = crypto_md5_init(); crypto_md5_update(md5ctx, sigdata, sigdatalen); crypto_md5_final(md5ctx, md5hash); stream_read(s, encsig, siglen); /* Last 8 bytes shall be all zero. */ for (sum = 0, i = sizeof(encsig) - 8; i < sizeof(encsig); i++) sum += encsig[i]; if (sum != 0) { printf("certificate_process_server_public_signature: invalid signature\n"); //return false; } siglen -= 8; crypto_rsa_public_decrypt(encsig, siglen, TSSK_KEY_LENGTH, tssk_modulus, tssk_exponent, sig); /* Verify signature. */ if (memcmp(md5hash, sig, sizeof(md5hash)) != 0) { printf("certificate_process_server_public_signature: invalid signature\n"); //return false; } /* * Verify rest of decrypted data: * The 17th byte is 0x00. * The 18th through 62nd bytes are each 0xFF. * The 63rd byte is 0x01. */ for (sum = 0, i = 17; i < 62; i++) sum += sig[i]; if (sig[16] != 0x00 || sum != 0xFF * (62 - 17) || sig[62] != 0x01) { printf("certificate_process_server_public_signature: invalid signature\n"); //return false; } return true; } /** * Read a Server Proprietary Certificate.\n * @param certificate certificate module * @param s stream */ boolean certificate_read_server_proprietary_certificate(rdpCertificate* certificate, STREAM* s) { uint32 dwSigAlgId; uint32 dwKeyAlgId; uint32 wPublicKeyBlobType; uint32 wPublicKeyBlobLen; uint32 wSignatureBlobType; uint32 wSignatureBlobLen; uint8* sigdata; int sigdatalen; /* -4, because we need to include dwVersion */ sigdata = stream_get_tail(s) - 4; stream_read_uint32(s, dwSigAlgId); stream_read_uint32(s, dwKeyAlgId); if (!(dwSigAlgId == SIGNATURE_ALG_RSA && dwKeyAlgId == KEY_EXCHANGE_ALG_RSA)) { printf("certificate_read_server_proprietary_certificate: parse error 1\n"); return false; } stream_read_uint16(s, wPublicKeyBlobType); if (wPublicKeyBlobType != BB_RSA_KEY_BLOB) { printf("certificate_read_server_proprietary_certificate: parse error 2\n"); return false; } stream_read_uint16(s, wPublicKeyBlobLen); if (!certificate_process_server_public_key(certificate, s, wPublicKeyBlobLen)) { printf("certificate_read_server_proprietary_certificate: parse error 3\n"); return false; } sigdatalen = stream_get_tail(s) - sigdata; stream_read_uint16(s, wSignatureBlobType); if (wSignatureBlobType != BB_RSA_SIGNATURE_BLOB) { printf("certificate_read_server_proprietary_certificate: parse error 4\n"); return false; } stream_read_uint16(s, wSignatureBlobLen); if (wSignatureBlobLen != 72) { printf("certificate_process_server_public_signature: invalid signature length (got %d, expected %d)\n", wSignatureBlobLen, 64); return false; } if (!certificate_process_server_public_signature(certificate, sigdata, sigdatalen, s, wSignatureBlobLen)) { printf("certificate_read_server_proprietary_certificate: parse error 5\n"); return false; } return true; } /** * Read an X.509 Certificate Chain.\n * @param certificate certificate module * @param s stream */ boolean certificate_read_server_x509_certificate_chain(rdpCertificate* certificate, STREAM* s) { int i; uint32 certLength; uint32 numCertBlobs; DEBUG_CERTIFICATE("Server X.509 Certificate Chain"); stream_read_uint32(s, numCertBlobs); /* numCertBlobs */ certificate->x509_cert_chain = certificate_new_x509_certificate_chain(numCertBlobs); for (i = 0; i < (int) numCertBlobs; i++) { stream_read_uint32(s, certLength); DEBUG_CERTIFICATE("\nX.509 Certificate #%d, length:%d", i + 1, certLength); certificate->x509_cert_chain->array[i].data = (uint8*) xmalloc(certLength); stream_read(s, certificate->x509_cert_chain->array[i].data, certLength); certificate->x509_cert_chain->array[i].length = certLength; if (numCertBlobs - i == 2) { rdpCertInfo cert_info; DEBUG_CERTIFICATE("License Server Certificate"); certificate_read_x509_certificate(&certificate->x509_cert_chain->array[i], &cert_info); DEBUG_LICENSE("modulus length:%d", cert_info.modulus.length); freerdp_blob_free(&cert_info.modulus); } else if (numCertBlobs - i == 1) { DEBUG_CERTIFICATE("Terminal Server Certificate"); certificate_read_x509_certificate(&certificate->x509_cert_chain->array[i], &certificate->cert_info); DEBUG_CERTIFICATE("modulus length:%d", certificate->cert_info.modulus.length); } } return true; } /** * Read a Server Certificate.\n * @param certificate certificate module * @param server_cert server certificate * @param length certificate length */ boolean certificate_read_server_certificate(rdpCertificate* certificate, uint8* server_cert, int length) { STREAM* s; uint32 dwVersion; s = stream_new(0); stream_attach(s, server_cert, length); if (length < 1) { printf("null server certificate\n"); return false; } stream_read_uint32(s, dwVersion); /* dwVersion (4 bytes) */ switch (dwVersion & CERT_CHAIN_VERSION_MASK) { case CERT_CHAIN_VERSION_1: certificate_read_server_proprietary_certificate(certificate, s); break; case CERT_CHAIN_VERSION_2: certificate_read_server_x509_certificate_chain(certificate, s); break; default: printf("invalid certificate chain version:%d\n", dwVersion & CERT_CHAIN_VERSION_MASK); break; } xfree(s); return true; } rdpKey* key_new(const char* keyfile) { rdpKey* key; RSA *rsa; FILE *fp; key = (rdpKey*) xzalloc(sizeof(rdpKey)); if (key == NULL) return NULL; fp = fopen(keyfile, "r"); if (fp == NULL) { printf("unable to load RSA key from %s: %s.", keyfile, strerror(errno)); return NULL; } rsa = PEM_read_RSAPrivateKey(fp, NULL, NULL, NULL); if (rsa == NULL) { ERR_print_errors_fp(stdout); fclose(fp); return NULL; } fclose(fp); switch (RSA_check_key(rsa)) { case 0: RSA_free(rsa); printf("invalid RSA key in %s", keyfile); return NULL; case 1: /* Valid key. */ break; default: ERR_print_errors_fp(stdout); RSA_free(rsa); return NULL; } if (BN_num_bytes(rsa->e) > 4) { RSA_free(rsa); printf("RSA public exponent too large in %s", keyfile); return NULL; } freerdp_blob_alloc(&key->modulus, BN_num_bytes(rsa->n)); BN_bn2bin(rsa->n, key->modulus.data); crypto_reverse(key->modulus.data, key->modulus.length); freerdp_blob_alloc(&key->private_exponent, BN_num_bytes(rsa->d)); BN_bn2bin(rsa->d, key->private_exponent.data); crypto_reverse(key->private_exponent.data, key->private_exponent.length); memset(key->exponent, 0, sizeof(key->exponent)); BN_bn2bin(rsa->e, key->exponent + sizeof(key->exponent) - BN_num_bytes(rsa->e)); crypto_reverse(key->exponent, sizeof(key->exponent)); RSA_free(rsa); return key; } void key_free(rdpKey* key) { if (key != NULL) { freerdp_blob_free(&key->modulus); freerdp_blob_free(&key->private_exponent); xfree(key); } } void certificate_store_init(rdpCertificateStore* certificate_store) { char* config_path; rdpSettings* settings; settings = certificate_store->settings; config_path = freerdp_get_config_path(settings); certificate_store->path = freerdp_construct_path(config_path, (char*) certificate_store_dir); if (freerdp_check_file_exists(certificate_store->path) == false) { freerdp_mkdir(certificate_store->path); printf("creating directory %s\n", certificate_store->path); } certificate_store->file = freerdp_construct_path(config_path, (char*) certificate_known_hosts_file); if (freerdp_check_file_exists(certificate_store->file) == false) { certificate_store->fp = fopen((char*) certificate_store->file, "w+"); if (certificate_store->fp == NULL) { printf("certificate_store_open: error opening [%s] for writing\n", certificate_store->file); return; } fflush(certificate_store->fp); } else { certificate_store->fp = fopen((char*) certificate_store->file, "r+"); } } int certificate_data_match(rdpCertificateStore* certificate_store, rdpCertificateData* certificate_data) { FILE* fp; int length; char* data; char* pline; int match = 1; long int size; fp = certificate_store->fp; if (!fp) return match; fseek(fp, 0, SEEK_END); size = ftell(fp); fseek(fp, 0, SEEK_SET); if (size < 1) return match; data = (char*) xmalloc(size + 2); if (fread(data, size, 1, fp) != 1) { xfree(data); return match; } data[size] = '\n'; data[size + 1] = '\0'; pline = strtok(data, "\n"); while (pline != NULL) { length = strlen(pline); if (length > 0) { length = strcspn(pline, " \t"); pline[length] = '\0'; if (strcmp(pline, certificate_data->hostname) == 0) { pline = &pline[length + 1]; if (strcmp(pline, certificate_data->fingerprint) == 0) match = 0; else match = -1; break; } } pline = strtok(NULL, "\n"); } xfree(data); return match; } void certificate_data_print(rdpCertificateStore* certificate_store, rdpCertificateData* certificate_data) { FILE* fp; /* reopen in append mode */ fp = fopen(certificate_store->file, "a"); if (!fp) return; fprintf(fp, "%s %s\n", certificate_data->hostname, certificate_data->fingerprint); fclose(fp); } rdpCertificateData* certificate_data_new(char* hostname, char* fingerprint) { rdpCertificateData* certdata; certdata = (rdpCertificateData*) xzalloc(sizeof(rdpCertificateData)); if (certdata != NULL) { certdata->hostname = xstrdup(hostname); certdata->fingerprint = xstrdup(fingerprint); } return certdata; } void certificate_data_free(rdpCertificateData* certificate_data) { if (certificate_data != NULL) { xfree(certificate_data->hostname); xfree(certificate_data->fingerprint); xfree(certificate_data); } } rdpCertificateStore* certificate_store_new(rdpSettings* settings) { rdpCertificateStore* certificate_store; certificate_store = (rdpCertificateStore*) xzalloc(sizeof(rdpCertificateStore)); if (certificate_store != NULL) { certificate_store->settings = settings; certificate_store_init(certificate_store); } return certificate_store; } void certificate_store_free(rdpCertificateStore* certstore) { if (certstore != NULL) { if (certstore->fp != NULL) fclose(certstore->fp); xfree(certstore->path); xfree(certstore->file); xfree(certstore); } } /** * Instantiate new certificate module.\n * @param rdp RDP module * @return new certificate module */ rdpCertificate* certificate_new() { rdpCertificate* certificate; certificate = (rdpCertificate*) xzalloc(sizeof(rdpCertificate)); if (certificate != NULL) { certificate->x509_cert_chain = NULL; } return certificate; } /** * Free certificate module. * @param certificate certificate module to be freed */ void certificate_free(rdpCertificate* certificate) { if (certificate != NULL) { certificate_free_x509_certificate_chain(certificate->x509_cert_chain); if (certificate->cert_info.modulus.data != NULL) freerdp_blob_free(&(certificate->cert_info.modulus)); xfree(certificate); } } FreeRDP-1.0.2/libfreerdp-core/certificate.h000066400000000000000000000061071207112532300204400ustar00rootroot00000000000000/** * FreeRDP: A Remote Desktop Protocol Client * Certificate Handling * * Copyright 2011 Marc-Andre Moreau * * 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. */ #ifndef __CERTIFICATE_H #define __CERTIFICATE_H typedef struct rdp_certificate_data rdpCertificateData; typedef struct rdp_certificate_store rdpCertificateStore; #include "rdp.h" #include "ber.h" #include "crypto.h" #include #include #include #include /* Certificate Version */ #define CERT_CHAIN_VERSION_1 0x00000001 #define CERT_CHAIN_VERSION_2 0x00000002 #define CERT_CHAIN_VERSION_MASK 0x7FFFFFFF #define CERT_PERMANENTLY_ISSUED 0x00000000 #define CERT_TEMPORARILY_ISSUED 0x80000000 #define SIGNATURE_ALG_RSA 0x00000001 #define KEY_EXCHANGE_ALG_RSA 0x00000001 #define BB_RSA_KEY_BLOB 6 #define BB_RSA_SIGNATURE_BLOB 8 struct rdp_key { rdpBlob modulus; rdpBlob private_exponent; uint8 exponent[4]; }; struct rdp_certificate_data { char* hostname; char* fingerprint; }; struct rdp_certificate_store { FILE* fp; char* path; char* file; rdpSettings* settings; rdpCertificateData* certificate_data; }; rdpCertificateData* certificate_data_new(char* hostname, char* fingerprint); void certificate_data_free(rdpCertificateData* certificate_data); rdpCertificateStore* certificate_store_new(rdpSettings* settings); void certificate_store_free(rdpCertificateStore* certificate_store); int certificate_data_match(rdpCertificateStore* certificate_store, rdpCertificateData* certificate_data); void certificate_data_print(rdpCertificateStore* certificate_store, rdpCertificateData* certificate_data); void certificate_read_x509_certificate(rdpCertBlob* cert, rdpCertInfo* info); rdpX509CertChain* certificate_new_x509_certificate_chain(uint32 count); void certificate_free_x509_certificate_chain(rdpX509CertChain* x509_cert_chain); boolean certificate_read_server_proprietary_certificate(rdpCertificate* certificate, STREAM* s); boolean certificate_read_server_x509_certificate_chain(rdpCertificate* certificate, STREAM* s); boolean certificate_read_server_certificate(rdpCertificate* certificate, uint8* server_cert, int length); rdpCertificate* certificate_new(); void certificate_free(rdpCertificate* certificate); rdpKey* key_new(const char *keyfile); void key_free(rdpKey* key); #ifdef WITH_DEBUG_CERTIFICATE #define DEBUG_CERTIFICATE(fmt, ...) DEBUG_CLASS(CERTIFICATE, fmt, ## __VA_ARGS__) #else #define DEBUG_CERTIFICATE(fmt, ...) DEBUG_NULL(fmt, ## __VA_ARGS__) #endif #endif /* __CERTIFICATE_H */ FreeRDP-1.0.2/libfreerdp-core/channel.c000066400000000000000000000052151207112532300175600ustar00rootroot00000000000000/** * FreeRDP: A Remote Desktop Protocol Client * Virtual Channels * * Copyright 2011 Vic Lee * * 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. */ #include #include #include #include #include #include #include #include #include "rdp.h" #include "channel.h" boolean freerdp_channel_send(rdpRdp* rdp, uint16 channel_id, uint8* data, int size) { STREAM* s; uint32 flags; int i, left; int chunk_size; rdpChannel* channel = NULL; for (i = 0; i < rdp->settings->num_channels; i++) { if (rdp->settings->channels[i].channel_id == channel_id) { channel = &rdp->settings->channels[i]; break; } } if (channel == NULL) { printf("freerdp_channel_send: unknown channel_id %d\n", channel_id); return false; } flags = CHANNEL_FLAG_FIRST; left = size; while (left > 0) { s = rdp_send_stream_init(rdp); if (left > (int) rdp->settings->vc_chunk_size) { chunk_size = rdp->settings->vc_chunk_size; } else { chunk_size = left; flags |= CHANNEL_FLAG_LAST; } if ((channel->options & CHANNEL_OPTION_SHOW_PROTOCOL)) { flags |= CHANNEL_FLAG_SHOW_PROTOCOL; } stream_write_uint32(s, size); stream_write_uint32(s, flags); stream_check_size(s, chunk_size); stream_write(s, data, chunk_size); rdp_send(rdp, s, channel_id); data += chunk_size; left -= chunk_size; flags = 0; } return true; } void freerdp_channel_process(freerdp* instance, STREAM* s, uint16 channel_id) { uint32 length; uint32 flags; int chunk_length; stream_read_uint32(s, length); stream_read_uint32(s, flags); chunk_length = stream_get_left(s); IFCALL(instance->ReceiveChannelData, instance, channel_id, stream_get_tail(s), chunk_length, flags, length); } void freerdp_channel_peer_process(freerdp_peer* client, STREAM* s, uint16 channel_id) { uint32 length; uint32 flags; int chunk_length; stream_read_uint32(s, length); stream_read_uint32(s, flags); chunk_length = stream_get_left(s); IFCALL(client->ReceiveChannelData, client, channel_id, stream_get_tail(s), chunk_length, flags, length); } FreeRDP-1.0.2/libfreerdp-core/channel.h000066400000000000000000000017231207112532300175650ustar00rootroot00000000000000/** * FreeRDP: A Remote Desktop Protocol Client * Virtual Channels * * Copyright 2011 Vic Lee * * 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. */ #ifndef __CHANNEL_H #define __CHANNEL_H boolean freerdp_channel_send(rdpRdp* rdp, uint16 channel_id, uint8* data, int size); void freerdp_channel_process(freerdp* instance, STREAM* s, uint16 channel_id); void freerdp_channel_peer_process(freerdp_peer* client, STREAM* s, uint16 channel_id); #endif /* __CHANNEL_H */ FreeRDP-1.0.2/libfreerdp-core/connection.c000066400000000000000000000445441207112532300203170ustar00rootroot00000000000000/** * FreeRDP: A Remote Desktop Protocol Client * Connection Sequence * * Copyright 2011 Marc-Andre Moreau * * 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. */ #include "per.h" #include "info.h" #include "input.h" #include "connection.h" /** * Connection Sequence * client server * | | * |-----------------------X.224 Connection Request PDU--------------------->| * |<----------------------X.224 Connection Confirm PDU----------------------| * |-------MCS Connect-Initial PDU with GCC Conference Create Request------->| * |<-----MCS Connect-Response PDU with GCC Conference Create Response-------| * |------------------------MCS Erect Domain Request PDU-------------------->| * |------------------------MCS Attach User Request PDU--------------------->| * |<-----------------------MCS Attach User Confirm PDU----------------------| * |------------------------MCS Channel Join Request PDU-------------------->| * |<-----------------------MCS Channel Join Confirm PDU---------------------| * |----------------------------Security Exchange PDU----------------------->| * |-------------------------------Client Info PDU-------------------------->| * |<---------------------License Error PDU - Valid Client-------------------| * |<-----------------------------Demand Active PDU--------------------------| * |------------------------------Confirm Active PDU------------------------>| * |-------------------------------Synchronize PDU-------------------------->| * |---------------------------Control PDU - Cooperate---------------------->| * |------------------------Control PDU - Request Control------------------->| * |--------------------------Persistent Key List PDU(s)-------------------->| * |--------------------------------Font List PDU--------------------------->| * |<------------------------------Synchronize PDU---------------------------| * |<--------------------------Control PDU - Cooperate-----------------------| * |<-----------------------Control PDU - Granted Control--------------------| * |<-------------------------------Font Map PDU-----------------------------| * */ /** * Establish RDP Connection.\n * @msdn{cc240452} * @param rdp RDP module */ boolean rdp_client_connect(rdpRdp* rdp) { boolean status; uint32 selectedProtocol; rdpSettings* settings = rdp->settings; nego_init(rdp->nego); nego_set_target(rdp->nego, settings->hostname, settings->port); nego_set_cookie(rdp->nego, settings->username); nego_enable_rdp(rdp->nego, settings->rdp_security); nego_enable_nla(rdp->nego, settings->nla_security); nego_enable_tls(rdp->nego, settings->tls_security); if (nego_connect(rdp->nego) != true) { printf("Error: protocol security negotiation failure\n"); return false; } selectedProtocol = rdp->nego->selected_protocol; if ((selectedProtocol & PROTOCOL_TLS) || (selectedProtocol == PROTOCOL_RDP)) { if ((settings->username != NULL) && ((settings->password != NULL) || (settings->password_cookie != NULL && settings->password_cookie->length > 0))) settings->autologon = true; } status = false; if (selectedProtocol & PROTOCOL_NLA) status = transport_connect_nla(rdp->transport); else if (selectedProtocol & PROTOCOL_TLS) status = transport_connect_tls(rdp->transport); else if (selectedProtocol == PROTOCOL_RDP) /* 0 */ status = transport_connect_rdp(rdp->transport); if (status != true) return false; rdp_set_blocking_mode(rdp, false); rdp->state = CONNECTION_STATE_NEGO; rdp->finalize_sc_pdus = 0; if (mcs_send_connect_initial(rdp->mcs) != true) { printf("Error: unable to send MCS Connect Initial\n"); return false; } while (rdp->state != CONNECTION_STATE_ACTIVE) { if (rdp_check_fds(rdp) < 0) return false; } return true; } boolean rdp_client_disconnect(rdpRdp* rdp) { return transport_disconnect(rdp->transport); } boolean rdp_client_redirect(rdpRdp* rdp) { rdpSettings* settings = rdp->settings; rdpRedirection* redirection = rdp->redirection; rdp_client_disconnect(rdp); mcs_free(rdp->mcs); nego_free(rdp->nego); license_free(rdp->license); transport_free(rdp->transport); rdp->transport = transport_new(settings); rdp->license = license_new(rdp); rdp->nego = nego_new(rdp->transport); rdp->mcs = mcs_new(rdp->transport); rdp->transport->layer = TRANSPORT_LAYER_TCP; settings->redirected_session_id = redirection->sessionID; if (redirection->flags & LB_LOAD_BALANCE_INFO) { nego_set_routing_token(rdp->nego, &redirection->loadBalanceInfo); } else { if (redirection->flags & LB_TARGET_NET_ADDRESS) { xfree(settings->hostname); settings->hostname = xstrdup(redirection->targetNetAddress.ascii); } else if (redirection->flags & LB_TARGET_FQDN) { xfree(settings->hostname); settings->hostname = xstrdup(redirection->targetFQDN.ascii); } else if (redirection->flags & LB_TARGET_NETBIOS_NAME) { xfree(settings->hostname); settings->hostname = xstrdup(redirection->targetNetBiosName.ascii); } } if (redirection->flags & LB_USERNAME) { xfree(settings->username); settings->username = xstrdup(redirection->username.ascii); } if (redirection->flags & LB_DOMAIN) { xfree(settings->domain); settings->domain = xstrdup(redirection->domain.ascii); } if (redirection->flags & LB_PASSWORD) { settings->password_cookie = &redirection->password_cookie; } return rdp_client_connect(rdp); } static boolean rdp_client_establish_keys(rdpRdp* rdp) { uint8 client_random[CLIENT_RANDOM_LENGTH]; uint8 crypt_client_random[256 + 8]; uint32 key_len; uint8* mod; uint8* exp; uint32 length; STREAM* s; if (rdp->settings->encryption == false) { /* no RDP encryption */ return true; } /* encrypt client random */ memset(crypt_client_random, 0, sizeof(crypt_client_random)); crypto_nonce(client_random, sizeof(client_random)); key_len = rdp->settings->server_cert->cert_info.modulus.length; mod = rdp->settings->server_cert->cert_info.modulus.data; exp = rdp->settings->server_cert->cert_info.exponent; crypto_rsa_public_encrypt(client_random, sizeof(client_random), key_len, mod, exp, crypt_client_random); /* send crypt client random to server */ length = RDP_PACKET_HEADER_MAX_LENGTH + RDP_SECURITY_HEADER_LENGTH + 4 + key_len + 8; s = transport_send_stream_init(rdp->mcs->transport, length); rdp_write_header(rdp, s, length, MCS_GLOBAL_CHANNEL_ID); rdp_write_security_header(s, SEC_EXCHANGE_PKT); length = key_len + 8; stream_write_uint32(s, length); stream_write(s, crypt_client_random, length); if (transport_write(rdp->mcs->transport, s) < 0) { return false; } /* now calculate encrypt / decrypt and update keys */ if (!security_establish_keys(client_random, rdp)) { return false; } rdp->do_crypt = true; if (rdp->settings->secure_checksum) rdp->do_secure_checksum = true; if (rdp->settings->encryption_method == ENCRYPTION_METHOD_FIPS) { uint8 fips_ivec[8] = { 0x12, 0x34, 0x56, 0x78, 0x90, 0xAB, 0xCD, 0xEF }; rdp->fips_encrypt = crypto_des3_encrypt_init(rdp->fips_encrypt_key, fips_ivec); rdp->fips_decrypt = crypto_des3_decrypt_init(rdp->fips_decrypt_key, fips_ivec); rdp->fips_hmac = crypto_hmac_new(); return true; } rdp->rc4_decrypt_key = crypto_rc4_init(rdp->decrypt_key, rdp->rc4_key_len); rdp->rc4_encrypt_key = crypto_rc4_init(rdp->encrypt_key, rdp->rc4_key_len); return true; } static boolean rdp_server_establish_keys(rdpRdp* rdp, STREAM* s) { uint8 client_random[64]; /* Should be only 32 after successfull decryption, but on failure might take up to 64 bytes. */ uint8 crypt_client_random[256 + 8]; uint32 rand_len, key_len; uint16 channel_id, length, sec_flags; uint8* mod; uint8* priv_exp; if (rdp->settings->encryption == false) { /* No RDP Security. */ return true; } if (!rdp_read_header(rdp, s, &length, &channel_id)) { printf("rdp_server_establish_keys: invalid RDP header\n"); return false; } rdp_read_security_header(s, &sec_flags); if ((sec_flags & SEC_EXCHANGE_PKT) == 0) { printf("rdp_server_establish_keys: missing SEC_EXCHANGE_PKT in security header\n"); return false; } stream_read_uint32(s, rand_len); key_len = rdp->settings->server_key->modulus.length; if (rand_len != key_len + 8) { printf("rdp_server_establish_keys: invalid encrypted client random length\n"); return false; } memset(crypt_client_random, 0, sizeof(crypt_client_random)); stream_read(s, crypt_client_random, rand_len); /* 8 zero bytes of padding */ stream_seek(s, 8); mod = rdp->settings->server_key->modulus.data; priv_exp = rdp->settings->server_key->private_exponent.data; crypto_rsa_private_decrypt(crypt_client_random, rand_len - 8, key_len, mod, priv_exp, client_random); /* now calculate encrypt / decrypt and update keys */ if (!security_establish_keys(client_random, rdp)) { return false; } rdp->do_crypt = true; if (rdp->settings->secure_checksum) rdp->do_secure_checksum = true; if (rdp->settings->encryption_method == ENCRYPTION_METHOD_FIPS) { uint8 fips_ivec[8] = { 0x12, 0x34, 0x56, 0x78, 0x90, 0xAB, 0xCD, 0xEF }; rdp->fips_encrypt = crypto_des3_encrypt_init(rdp->fips_encrypt_key, fips_ivec); rdp->fips_decrypt = crypto_des3_decrypt_init(rdp->fips_decrypt_key, fips_ivec); rdp->fips_hmac = crypto_hmac_new(); return true; } rdp->rc4_decrypt_key = crypto_rc4_init(rdp->decrypt_key, rdp->rc4_key_len); rdp->rc4_encrypt_key = crypto_rc4_init(rdp->encrypt_key, rdp->rc4_key_len); return true; } boolean rdp_client_connect_mcs_connect_response(rdpRdp* rdp, STREAM* s) { if (!mcs_recv_connect_response(rdp->mcs, s)) { printf("rdp_client_connect_mcs_connect_response: mcs_recv_connect_response failed\n"); return false; } if (!mcs_send_erect_domain_request(rdp->mcs)) return false; if (!mcs_send_attach_user_request(rdp->mcs)) return false; rdp->state = CONNECTION_STATE_MCS_ATTACH_USER; return true; } boolean rdp_client_connect_mcs_attach_user_confirm(rdpRdp* rdp, STREAM* s) { if (!mcs_recv_attach_user_confirm(rdp->mcs, s)) return false; if (!mcs_send_channel_join_request(rdp->mcs, rdp->mcs->user_id)) return false; rdp->state = CONNECTION_STATE_MCS_CHANNEL_JOIN; return true; } boolean rdp_client_connect_mcs_channel_join_confirm(rdpRdp* rdp, STREAM* s) { int i; uint16 channel_id; boolean all_joined = true; if (!mcs_recv_channel_join_confirm(rdp->mcs, s, &channel_id)) return false; if (!rdp->mcs->user_channel_joined) { if (channel_id != rdp->mcs->user_id) return false; rdp->mcs->user_channel_joined = true; if (!mcs_send_channel_join_request(rdp->mcs, MCS_GLOBAL_CHANNEL_ID)) return false; } else if (!rdp->mcs->global_channel_joined) { if (channel_id != MCS_GLOBAL_CHANNEL_ID) return false; rdp->mcs->global_channel_joined = true; if (rdp->settings->num_channels > 0) { if (!mcs_send_channel_join_request(rdp->mcs, rdp->settings->channels[0].channel_id)) return false; all_joined = false; } } else { for (i = 0; i < rdp->settings->num_channels; i++) { if (rdp->settings->channels[i].joined) continue; if (rdp->settings->channels[i].channel_id != channel_id) return false; rdp->settings->channels[i].joined = true; break; } if (i + 1 < rdp->settings->num_channels) { if (!mcs_send_channel_join_request(rdp->mcs, rdp->settings->channels[i + 1].channel_id)) return false; all_joined = false; } } if (rdp->mcs->user_channel_joined && rdp->mcs->global_channel_joined && all_joined) { if (!rdp_client_establish_keys(rdp)) return false; if (!rdp_send_client_info(rdp)) return false; rdp->state = CONNECTION_STATE_LICENSE; } return true; } boolean rdp_client_connect_license(rdpRdp* rdp, STREAM* s) { if (!license_recv(rdp->license, s)) return false; if (rdp->license->state == LICENSE_STATE_ABORTED) { printf("license connection sequence aborted.\n"); return false; } if (rdp->license->state == LICENSE_STATE_COMPLETED) { rdp->state = CONNECTION_STATE_CAPABILITY; } return true; } boolean rdp_client_connect_demand_active(rdpRdp* rdp, STREAM* s) { uint8* mark; uint16 width; uint16 height; width = rdp->settings->width; height = rdp->settings->height; stream_get_mark(s, mark); if (!rdp_recv_demand_active(rdp, s)) { stream_set_mark(s, mark); stream_seek(s, RDP_PACKET_HEADER_MAX_LENGTH); if (rdp_recv_out_of_sequence_pdu(rdp, s) != true) return false; return true; } if (rdp->disconnect) return true; if (!rdp_send_confirm_active(rdp)) return false; input_register_client_callbacks(rdp->input); /** * The server may request a different desktop size during Deactivation-Reactivation sequence. * In this case, the UI should be informed and do actual window resizing at this point. */ if (width != rdp->settings->width || height != rdp->settings->height) { IFCALL(rdp->update->DesktopResize, rdp->update->context); } rdp->state = CONNECTION_STATE_FINALIZATION; update_reset_state(rdp->update); rdp_client_connect_finalize(rdp); return true; } boolean rdp_client_connect_finalize(rdpRdp* rdp) { /** * [MS-RDPBCGR] 1.3.1.1 - 8. * The client-to-server PDUs sent during this phase have no dependencies on any of the server-to- * client PDUs; they may be sent as a single batch, provided that sequencing is maintained. */ if (!rdp_send_client_synchronize_pdu(rdp)) return false; if (!rdp_send_client_control_pdu(rdp, CTRLACTION_COOPERATE)) return false; if (!rdp_send_client_control_pdu(rdp, CTRLACTION_REQUEST_CONTROL)) return false; if (!rdp_send_client_persistent_key_list_pdu(rdp)) return false; if (!rdp_send_client_font_list_pdu(rdp, FONTLIST_FIRST | FONTLIST_LAST)) return false; return true; } boolean rdp_server_accept_nego(rdpRdp* rdp, STREAM* s) { boolean ret; transport_set_blocking_mode(rdp->transport, true); if (!nego_read_request(rdp->nego, s)) return false; rdp->nego->selected_protocol = 0; printf("Requested protocols:"); if ((rdp->nego->requested_protocols & PROTOCOL_TLS)) { printf(" TLS"); if (rdp->settings->tls_security) { printf("(Y)"); rdp->nego->selected_protocol |= PROTOCOL_TLS; } else printf("(n)"); } if ((rdp->nego->requested_protocols & PROTOCOL_NLA)) { printf(" NLA"); if (rdp->settings->nla_security) { printf("(Y)"); rdp->nego->selected_protocol |= PROTOCOL_NLA; } else printf("(n)"); } printf(" RDP"); if (rdp->settings->rdp_security && rdp->nego->selected_protocol == 0) { printf("(Y)"); rdp->nego->selected_protocol = PROTOCOL_RDP; } else printf("(n)"); printf("\n"); if (!nego_send_negotiation_response(rdp->nego)) return false; ret = false; if (rdp->nego->selected_protocol & PROTOCOL_NLA) ret = transport_accept_nla(rdp->transport); else if (rdp->nego->selected_protocol & PROTOCOL_TLS) ret = transport_accept_tls(rdp->transport); else if (rdp->nego->selected_protocol == PROTOCOL_RDP) /* 0 */ ret = transport_accept_rdp(rdp->transport); if (!ret) return false; transport_set_blocking_mode(rdp->transport, false); rdp->state = CONNECTION_STATE_NEGO; return true; } boolean rdp_server_accept_mcs_connect_initial(rdpRdp* rdp, STREAM* s) { int i; if (!mcs_recv_connect_initial(rdp->mcs, s)) return false; printf("Accepted client: %s\n", rdp->settings->client_hostname); printf("Accepted channels:"); for (i = 0; i < rdp->settings->num_channels; i++) { printf(" %s", rdp->settings->channels[i].name); } printf("\n"); if (!mcs_send_connect_response(rdp->mcs)) return false; rdp->state = CONNECTION_STATE_MCS_CONNECT; return true; } boolean rdp_server_accept_mcs_erect_domain_request(rdpRdp* rdp, STREAM* s) { if (!mcs_recv_erect_domain_request(rdp->mcs, s)) return false; rdp->state = CONNECTION_STATE_MCS_ERECT_DOMAIN; return true; } boolean rdp_server_accept_mcs_attach_user_request(rdpRdp* rdp, STREAM* s) { if (!mcs_recv_attach_user_request(rdp->mcs, s)) return false; if (!mcs_send_attach_user_confirm(rdp->mcs)) return false; rdp->state = CONNECTION_STATE_MCS_ATTACH_USER; return true; } boolean rdp_server_accept_mcs_channel_join_request(rdpRdp* rdp, STREAM* s) { int i; uint16 channel_id; boolean all_joined = true; if (!mcs_recv_channel_join_request(rdp->mcs, s, &channel_id)) return false; if (!mcs_send_channel_join_confirm(rdp->mcs, channel_id)) return false; if (channel_id == rdp->mcs->user_id) rdp->mcs->user_channel_joined = true; else if (channel_id == MCS_GLOBAL_CHANNEL_ID) rdp->mcs->global_channel_joined = true; for (i = 0; i < rdp->settings->num_channels; i++) { if (rdp->settings->channels[i].channel_id == channel_id) rdp->settings->channels[i].joined = true; if (!rdp->settings->channels[i].joined) all_joined = false; } if (rdp->mcs->user_channel_joined && rdp->mcs->global_channel_joined && all_joined) rdp->state = CONNECTION_STATE_MCS_CHANNEL_JOIN; return true; } boolean rdp_server_accept_client_keys(rdpRdp* rdp, STREAM* s) { if (!rdp_server_establish_keys(rdp, s)) return false; rdp->state = CONNECTION_STATE_ESTABLISH_KEYS; return true; } boolean rdp_server_accept_client_info(rdpRdp* rdp, STREAM* s) { if (!rdp_recv_client_info(rdp, s)) return false; if (!license_send_valid_client_error_packet(rdp->license)) return false; rdp->state = CONNECTION_STATE_LICENSE; return true; } boolean rdp_server_accept_confirm_active(rdpRdp* rdp, STREAM* s) { if (!rdp_recv_confirm_active(rdp, s)) return false; rdp->state = CONNECTION_STATE_ACTIVE; update_reset_state(rdp->update); if (!rdp_send_server_synchronize_pdu(rdp)) return false; if (!rdp_send_server_control_cooperate_pdu(rdp)) return false; return true; } boolean rdp_server_reactivate(rdpRdp* rdp) { if (!rdp_send_deactivate_all(rdp)) return false; rdp->state = CONNECTION_STATE_LICENSE; if (!rdp_send_demand_active(rdp)) return false; return true; } FreeRDP-1.0.2/libfreerdp-core/connection.h000066400000000000000000000045711207112532300203200ustar00rootroot00000000000000/** * FreeRDP: A Remote Desktop Protocol Client * Connection Sequence * * Copyright 2011 Marc-Andre Moreau * * 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. */ #ifndef __CONNECTION_H #define __CONNECTION_H #include "rdp.h" #include "tpkt.h" #include "tpdu.h" #include "nego.h" #include "mcs.h" #include "transport.h" #include "activation.h" #include #include enum CONNECTION_STATE { CONNECTION_STATE_INITIAL = 0, CONNECTION_STATE_NEGO, CONNECTION_STATE_MCS_CONNECT, CONNECTION_STATE_MCS_ERECT_DOMAIN, CONNECTION_STATE_MCS_ATTACH_USER, CONNECTION_STATE_MCS_CHANNEL_JOIN, CONNECTION_STATE_ESTABLISH_KEYS, CONNECTION_STATE_LICENSE, CONNECTION_STATE_CAPABILITY, CONNECTION_STATE_FINALIZATION, CONNECTION_STATE_ACTIVE }; boolean rdp_client_connect(rdpRdp* rdp); boolean rdp_client_redirect(rdpRdp* rdp); boolean rdp_client_connect_mcs_connect_response(rdpRdp* rdp, STREAM* s); boolean rdp_client_connect_mcs_attach_user_confirm(rdpRdp* rdp, STREAM* s); boolean rdp_client_connect_mcs_channel_join_confirm(rdpRdp* rdp, STREAM* s); boolean rdp_client_connect_license(rdpRdp* rdp, STREAM* s); boolean rdp_client_connect_demand_active(rdpRdp* rdp, STREAM* s); boolean rdp_client_connect_finalize(rdpRdp* rdp); boolean rdp_server_accept_nego(rdpRdp* rdp, STREAM* s); boolean rdp_server_accept_mcs_connect_initial(rdpRdp* rdp, STREAM* s); boolean rdp_server_accept_mcs_erect_domain_request(rdpRdp* rdp, STREAM* s); boolean rdp_server_accept_mcs_attach_user_request(rdpRdp* rdp, STREAM* s); boolean rdp_server_accept_mcs_channel_join_request(rdpRdp* rdp, STREAM* s); boolean rdp_server_accept_client_keys(rdpRdp* rdp, STREAM* s); boolean rdp_server_accept_client_info(rdpRdp* rdp, STREAM* s); boolean rdp_server_accept_confirm_active(rdpRdp* rdp, STREAM* s); boolean rdp_server_reactivate(rdpRdp* rdp); #endif /* __CONNECTION_H */ FreeRDP-1.0.2/libfreerdp-core/credssp.c000066400000000000000000000424241207112532300176160ustar00rootroot00000000000000/** * FreeRDP: A Remote Desktop Protocol Client * Credential Security Support Provider (CredSSP) * * Copyright 2010 Marc-Andre Moreau * * 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. */ #ifndef _WIN32 #include #endif #include #include "ntlmssp.h" #include "credssp.h" /** * TSRequest ::= SEQUENCE { * version [0] INTEGER, * negoTokens [1] NegoData OPTIONAL, * authInfo [2] OCTET STRING OPTIONAL, * pubKeyAuth [3] OCTET STRING OPTIONAL * } * * NegoData ::= SEQUENCE OF NegoDataItem * * NegoDataItem ::= SEQUENCE { * negoToken [0] OCTET STRING * } * * TSCredentials ::= SEQUENCE { * credType [0] INTEGER, * credentials [1] OCTET STRING * } * * TSPasswordCreds ::= SEQUENCE { * domainName [0] OCTET STRING, * userName [1] OCTET STRING, * password [2] OCTET STRING * } * * TSSmartCardCreds ::= SEQUENCE { * pin [0] OCTET STRING, * cspData [1] TSCspDataDetail, * userHint [2] OCTET STRING OPTIONAL, * domainHint [3] OCTET STRING OPTIONAL * } * * TSCspDataDetail ::= SEQUENCE { * keySpec [0] INTEGER, * cardName [1] OCTET STRING OPTIONAL, * readerName [2] OCTET STRING OPTIONAL, * containerName [3] OCTET STRING OPTIONAL, * cspName [4] OCTET STRING OPTIONAL * } * */ /** * Initialize NTLMSSP authentication module. * @param credssp */ int credssp_ntlmssp_init(rdpCredssp* credssp) { freerdp* instance; NTLMSSP* ntlmssp = credssp->ntlmssp; rdpSettings* settings = credssp->transport->settings; instance = (freerdp*) settings->instance; if ((settings->password == NULL) || (settings->username == NULL)) { if(instance->Authenticate) { boolean proceed = instance->Authenticate(instance, &settings->username, &settings->password, &settings->domain); if (!proceed) return 0; } } if (settings->ntlm_version == 2) ntlmssp->ntlm_v2 = 1; ntlmssp_set_password(ntlmssp, settings->password); ntlmssp_set_username(ntlmssp, settings->username); if (ntlmssp->ntlm_v2) { ntlmssp_set_workstation(ntlmssp, "WORKSTATION"); } if (settings->domain != NULL) { if (strlen(settings->domain) > 0) ntlmssp_set_domain(ntlmssp, settings->domain); } else { ntlmssp_set_domain(ntlmssp, NULL); } ntlmssp_generate_client_challenge(ntlmssp); ntlmssp_generate_random_session_key(ntlmssp); ntlmssp_generate_exported_session_key(ntlmssp); return 1; } /** * Get TLS public key. * @param credssp */ int credssp_get_public_key(rdpCredssp* credssp) { int status; CryptoCert cert; cert = tls_get_certificate(credssp->transport->tls); if (cert == NULL) { printf("credssp_get_public_key: tls_get_certificate failed to return the server certificate.\n"); return 0; } if (!tls_verify_certificate(credssp->transport->tls, cert, credssp->transport->settings->hostname)) tls_disconnect(credssp->transport->tls); status = crypto_cert_get_public_key(cert, &credssp->public_key); crypto_cert_free(cert); return status; } /** * Authenticate with server using CredSSP. * @param credssp * @return 1 if authentication is successful */ int credssp_authenticate(rdpCredssp* credssp) { NTLMSSP* ntlmssp = credssp->ntlmssp; STREAM* s = stream_new(0); uint8* negoTokenBuffer = (uint8*) xmalloc(2048); if (credssp_ntlmssp_init(credssp) == 0) return 0; if (credssp_get_public_key(credssp) == 0) return 0; /* NTLMSSP NEGOTIATE MESSAGE */ stream_attach(s, negoTokenBuffer, 2048); ntlmssp_send(ntlmssp, s); credssp->negoToken.data = stream_get_head(s); credssp->negoToken.length = stream_get_length(s); credssp_send(credssp, &credssp->negoToken, NULL, NULL); /* NTLMSSP CHALLENGE MESSAGE */ if (credssp_recv(credssp, &credssp->negoToken, NULL, NULL) < 0) return -1; stream_attach(s, credssp->negoToken.data, credssp->negoToken.length); ntlmssp_recv(ntlmssp, s); freerdp_blob_free(&credssp->negoToken); /* NTLMSSP AUTHENTICATE MESSAGE */ stream_attach(s, negoTokenBuffer, 2048); ntlmssp_send(ntlmssp, s); /* The last NTLMSSP message is sent with the encrypted public key */ credssp->negoToken.data = stream_get_head(s); credssp->negoToken.length = stream_get_length(s); credssp_encrypt_public_key(credssp, &credssp->pubKeyAuth); credssp_send(credssp, &credssp->negoToken, NULL, &credssp->pubKeyAuth); freerdp_blob_free(&credssp->pubKeyAuth); /* Encrypted Public Key +1 */ if (credssp_recv(credssp, &credssp->negoToken, NULL, &credssp->pubKeyAuth) < 0) return -1; if (credssp_verify_public_key(credssp, &credssp->pubKeyAuth) == 0) { /* Failed to verify server public key echo */ return 0; /* DO NOT SEND CREDENTIALS! */ } freerdp_blob_free(&credssp->negoToken); freerdp_blob_free(&credssp->pubKeyAuth); /* Send encrypted credentials */ credssp_encode_ts_credentials(credssp); credssp_encrypt_ts_credentials(credssp, &credssp->authInfo); credssp_send(credssp, NULL, &credssp->authInfo, NULL); freerdp_blob_free(&credssp->authInfo); xfree(s); return 1; } /** * Encrypt TLS public key using CredSSP. * @param credssp * @param s */ void credssp_encrypt_public_key(rdpCredssp* credssp, rdpBlob* d) { uint8* p; uint8 signature[16]; rdpBlob encrypted_public_key; NTLMSSP *ntlmssp = credssp->ntlmssp; freerdp_blob_alloc(d, credssp->public_key.length + 16); ntlmssp_encrypt_message(ntlmssp, &credssp->public_key, &encrypted_public_key, signature); #ifdef WITH_DEBUG_NLA printf("Public Key (length = %d)\n", credssp->public_key.length); freerdp_hexdump(credssp->public_key.data, credssp->public_key.length); printf("\n"); printf("Encrypted Public Key (length = %d)\n", encrypted_public_key.length); freerdp_hexdump(encrypted_public_key.data, encrypted_public_key.length); printf("\n"); printf("Signature\n"); freerdp_hexdump(signature, 16); printf("\n"); #endif p = (uint8*) d->data; memcpy(p, signature, 16); /* Message Signature */ memcpy(&p[16], encrypted_public_key.data, encrypted_public_key.length); /* Encrypted Public Key */ freerdp_blob_free(&encrypted_public_key); } /** * Verify TLS public key using CredSSP. * @param credssp * @param s * @return 1 if verification is successful, 0 otherwise */ int credssp_verify_public_key(rdpCredssp* credssp, rdpBlob* d) { uint8 *p1, *p2; uint8* signature; rdpBlob public_key; rdpBlob encrypted_public_key; signature = d->data; encrypted_public_key.data = (void*) (signature + 16); encrypted_public_key.length = d->length - 16; ntlmssp_decrypt_message(credssp->ntlmssp, &encrypted_public_key, &public_key, signature); p1 = (uint8*) credssp->public_key.data; p2 = (uint8*) public_key.data; p2[0]--; if (memcmp(p1, p2, public_key.length) != 0) { printf("Could not verify server's public key echo\n"); return 0; } p2[0]++; freerdp_blob_free(&public_key); return 1; } /** * Encrypt and sign TSCredentials structure. * @param credssp * @param s */ void credssp_encrypt_ts_credentials(rdpCredssp* credssp, rdpBlob* d) { uint8* p; uint8 signature[16]; rdpBlob encrypted_ts_credentials; NTLMSSP* ntlmssp = credssp->ntlmssp; freerdp_blob_alloc(d, credssp->ts_credentials.length + 16); ntlmssp_encrypt_message(ntlmssp, &credssp->ts_credentials, &encrypted_ts_credentials, signature); #ifdef WITH_DEBUG_NLA printf("TSCredentials (length = %d)\n", credssp->ts_credentials.length); freerdp_hexdump(credssp->ts_credentials.data, credssp->ts_credentials.length); printf("\n"); printf("Encrypted TSCredentials (length = %d)\n", encrypted_ts_credentials.length); freerdp_hexdump(encrypted_ts_credentials.data, encrypted_ts_credentials.length); printf("\n"); printf("Signature\n"); freerdp_hexdump(signature, 16); printf("\n"); #endif p = (uint8*) d->data; memcpy(p, signature, 16); /* Message Signature */ memcpy(&p[16], encrypted_ts_credentials.data, encrypted_ts_credentials.length); /* Encrypted TSCredentials */ freerdp_blob_free(&encrypted_ts_credentials); } int credssp_skip_ts_password_creds(rdpCredssp* credssp) { int length; int ts_password_creds_length = 0; length = ber_skip_octet_string(credssp->ntlmssp->domain.length); length += ber_skip_contextual_tag(length); ts_password_creds_length += length; length = ber_skip_octet_string(credssp->ntlmssp->username.length); length += ber_skip_contextual_tag(length); ts_password_creds_length += length; length = ber_skip_octet_string(credssp->ntlmssp->password.length); length += ber_skip_contextual_tag(length); ts_password_creds_length += length; length = ber_skip_sequence(ts_password_creds_length); return length; } void credssp_write_ts_password_creds(rdpCredssp* credssp, STREAM* s) { int length; length = credssp_skip_ts_password_creds(credssp); /* TSPasswordCreds (SEQUENCE) */ length = ber_get_content_length(length); ber_write_sequence_tag(s, length); /* [0] domainName (OCTET STRING) */ ber_write_contextual_tag(s, 0, credssp->ntlmssp->domain.length + 2, true); ber_write_octet_string(s, credssp->ntlmssp->domain.data, credssp->ntlmssp->domain.length); /* [1] userName (OCTET STRING) */ ber_write_contextual_tag(s, 1, credssp->ntlmssp->username.length + 2, true); ber_write_octet_string(s, credssp->ntlmssp->username.data, credssp->ntlmssp->username.length); /* [2] password (OCTET STRING) */ ber_write_contextual_tag(s, 2, credssp->ntlmssp->password.length + 2, true); ber_write_octet_string(s, credssp->ntlmssp->password.data, credssp->ntlmssp->password.length); } int credssp_skip_ts_credentials(rdpCredssp* credssp) { int length; int ts_password_creds_length; int ts_credentials_length = 0; length = ber_skip_integer(0); length += ber_skip_contextual_tag(length); ts_credentials_length += length; ts_password_creds_length = credssp_skip_ts_password_creds(credssp); length = ber_skip_octet_string(ts_password_creds_length); length += ber_skip_contextual_tag(length); ts_credentials_length += length; length = ber_skip_sequence(ts_credentials_length); return length; } void credssp_write_ts_credentials(rdpCredssp* credssp, STREAM* s) { int length; int ts_password_creds_length; length = credssp_skip_ts_credentials(credssp); ts_password_creds_length = credssp_skip_ts_password_creds(credssp); /* TSCredentials (SEQUENCE) */ length = ber_get_content_length(length); length -= ber_write_sequence_tag(s, length); /* [0] credType (INTEGER) */ length -= ber_write_contextual_tag(s, 0, 3, true); length -= ber_write_integer(s, 1); /* [1] credentials (OCTET STRING) */ length -= 1; length -= ber_write_contextual_tag(s, 1, length, true); length -= ber_write_octet_string_tag(s, ts_password_creds_length); credssp_write_ts_password_creds(credssp, s); } /** * Encode TSCredentials structure. * @param credssp */ void credssp_encode_ts_credentials(rdpCredssp* credssp) { STREAM* s; int length; s = stream_new(0); length = credssp_skip_ts_credentials(credssp); freerdp_blob_alloc(&credssp->ts_credentials, length); stream_attach(s, credssp->ts_credentials.data, length); credssp_write_ts_credentials(credssp, s); stream_detach(s); stream_free(s); } int credssp_skip_nego_token(int length) { length = ber_skip_octet_string(length); length += ber_skip_contextual_tag(length); return length; } int credssp_skip_nego_tokens(int length) { length = credssp_skip_nego_token(length); length += ber_skip_sequence_tag(length); length += ber_skip_sequence_tag(length); length += ber_skip_contextual_tag(length); return length; } int credssp_skip_pub_key_auth(int length) { length = ber_skip_octet_string(length); length += ber_skip_contextual_tag(length); return length; } int credssp_skip_auth_info(int length) { length = ber_skip_octet_string(length); length += ber_skip_contextual_tag(length); return length; } int credssp_skip_ts_request(int length) { length += ber_skip_integer(2); length += ber_skip_contextual_tag(3); length += ber_skip_sequence_tag(length); return length; } /** * Send CredSSP message. * @param credssp * @param negoToken * @param authInfo * @param pubKeyAuth */ void credssp_send(rdpCredssp* credssp, rdpBlob* negoToken, rdpBlob* authInfo, rdpBlob* pubKeyAuth) { STREAM* s; int length; int ts_request_length; int nego_tokens_length; int pub_key_auth_length; int auth_info_length; nego_tokens_length = (negoToken != NULL) ? credssp_skip_nego_tokens(negoToken->length) : 0; pub_key_auth_length = (pubKeyAuth != NULL) ? credssp_skip_pub_key_auth(pubKeyAuth->length) : 0; auth_info_length = (authInfo != NULL) ? credssp_skip_auth_info(authInfo->length) : 0; length = nego_tokens_length + pub_key_auth_length + auth_info_length; ts_request_length = credssp_skip_ts_request(length); s = stream_new(ts_request_length); /* TSRequest */ length = ber_get_content_length(ts_request_length); ber_write_sequence_tag(s, length); /* SEQUENCE */ ber_write_contextual_tag(s, 0, 3, true); /* [0] version */ ber_write_integer(s, 2); /* INTEGER */ /* [1] negoTokens (NegoData) */ if (nego_tokens_length > 0) { length = ber_get_content_length(nego_tokens_length); length -= ber_write_contextual_tag(s, 1, length, true); /* NegoData */ length -= ber_write_sequence_tag(s, length); /* SEQUENCE OF NegoDataItem */ length -= ber_write_sequence_tag(s, length); /* NegoDataItem */ length -= ber_write_contextual_tag(s, 0, length, true); /* [0] negoToken */ ber_write_octet_string(s, negoToken->data, length); /* OCTET STRING */ } /* [2] authInfo (OCTET STRING) */ if (auth_info_length > 0) { length = ber_get_content_length(auth_info_length); length -= ber_write_contextual_tag(s, 2, length, true); ber_write_octet_string(s, authInfo->data, authInfo->length); } /* [3] pubKeyAuth (OCTET STRING) */ if (pub_key_auth_length > 0) { length = ber_get_content_length(pub_key_auth_length); length -= ber_write_contextual_tag(s, 3, length, true); ber_write_octet_string(s, pubKeyAuth->data, length); } transport_write(credssp->transport, s); stream_free(s); } /** * Receive CredSSP message. * @param credssp * @param negoToken * @param authInfo * @param pubKeyAuth * @return */ int credssp_recv(rdpCredssp* credssp, rdpBlob* negoToken, rdpBlob* authInfo, rdpBlob* pubKeyAuth) { STREAM* s; int length; int status; uint32 version; s = transport_recv_stream_init(credssp->transport, 2048); status = transport_read(credssp->transport, s); if (status < 0) return -1; /* TSRequest */ ber_read_sequence_tag(s, &length); ber_read_contextual_tag(s, 0, &length, true); ber_read_integer(s, &version); /* [1] negoTokens (NegoData) */ if (ber_read_contextual_tag(s, 1, &length, true) != false) { ber_read_sequence_tag(s, &length); /* SEQUENCE OF NegoDataItem */ ber_read_sequence_tag(s, &length); /* NegoDataItem */ ber_read_contextual_tag(s, 0, &length, true); /* [0] negoToken */ ber_read_octet_string(s, &length); /* OCTET STRING */ freerdp_blob_alloc(negoToken, length); stream_read(s, negoToken->data, length); } /* [2] authInfo (OCTET STRING) */ if (ber_read_contextual_tag(s, 2, &length, true) != false) { ber_read_octet_string(s, &length); /* OCTET STRING */ freerdp_blob_alloc(authInfo, length); stream_read(s, authInfo->data, length); } /* [3] pubKeyAuth (OCTET STRING) */ if (ber_read_contextual_tag(s, 3, &length, true) != false) { ber_read_octet_string(s, &length); /* OCTET STRING */ freerdp_blob_alloc(pubKeyAuth, length); stream_read(s, pubKeyAuth->data, length); } return 0; } /** * Encrypt the given plain text using RC4 and the given key. * @param key RC4 key * @param length text length * @param plaintext plain text * @param ciphertext cipher text */ void credssp_rc4k(uint8* key, int length, uint8* plaintext, uint8* ciphertext) { CryptoRc4 rc4; /* Initialize RC4 cipher with key */ rc4 = crypto_rc4_init((void*) key, 16); /* Encrypt plaintext with key */ crypto_rc4(rc4, length, (void*) plaintext, (void*) ciphertext); /* Free RC4 Cipher */ crypto_rc4_free(rc4); } /** * Get current time, in tenths of microseconds since midnight of January 1, 1601. * @param[out] timestamp 64-bit little-endian timestamp */ void credssp_current_time(uint8* timestamp) { uint64 time64; /* Timestamp (8 bytes), represented as the number of tenths of microseconds since midnight of January 1, 1601 */ time64 = time(NULL) + 11644473600LL; /* Seconds since January 1, 1601 */ time64 *= 10000000; /* Convert timestamp to tenths of a microsecond */ memcpy(timestamp, &time64, 8); /* Copy into timestamp in little-endian */ } /** * Create new CredSSP state machine. * @param transport * @return new CredSSP state machine. */ rdpCredssp* credssp_new(rdpTransport* transport) { rdpCredssp* self; self = (rdpCredssp*) xzalloc(sizeof(rdpCredssp)); if (self != NULL) { self->transport = transport; self->send_seq_num = 0; self->ntlmssp = ntlmssp_new(); self->settings = transport->settings; } return self; } /** * Free CredSSP state machine. * @param credssp */ void credssp_free(rdpCredssp* credssp) { if (credssp != NULL) { freerdp_blob_free(&credssp->public_key); freerdp_blob_free(&credssp->ts_credentials); ntlmssp_free(credssp->ntlmssp); xfree(credssp); } } FreeRDP-1.0.2/libfreerdp-core/credssp.h000066400000000000000000000040461207112532300176210ustar00rootroot00000000000000/** * FreeRDP: A Remote Desktop Protocol Client * Credential Security Support Provider (CredSSP) * * Copyright 2010 Marc-Andre Moreau * * 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. */ #ifndef __CREDSSP_H #define __CREDSSP_H typedef struct rdp_credssp rdpCredssp; #include "tls.h" #include "ber.h" #include "crypto.h" #include "transport.h" #include #include #include #include #include #include "ntlmssp.h" struct rdp_credssp { rdpBlob negoToken; rdpBlob pubKeyAuth; rdpBlob authInfo; int send_seq_num; rdpBlob public_key; rdpBlob ts_credentials; rdpSettings* settings; CryptoRc4 rc4_seal_state; struct _NTLMSSP *ntlmssp; struct rdp_transport* transport; }; int credssp_authenticate(rdpCredssp* credssp); void credssp_send(rdpCredssp* credssp, rdpBlob* negoToken, rdpBlob* authInfo, rdpBlob* pubKeyAuth); int credssp_recv(rdpCredssp* credssp, rdpBlob* negoToken, rdpBlob* authInfo, rdpBlob* pubKeyAuth); void credssp_encrypt_public_key(rdpCredssp* credssp, rdpBlob* d); void credssp_encrypt_ts_credentials(rdpCredssp* credssp, rdpBlob* d); int credssp_verify_public_key(rdpCredssp* credssp, rdpBlob* d); void credssp_encode_ts_credentials(rdpCredssp* credssp); void credssp_current_time(uint8* timestamp); void credssp_rc4k(uint8* key, int length, uint8* plaintext, uint8* ciphertext); rdpCredssp* credssp_new(rdpTransport* transport); void credssp_free(rdpCredssp* credssp); #endif /* __CREDSSP_H */ FreeRDP-1.0.2/libfreerdp-core/crypto.c000066400000000000000000000317441207112532300174760ustar00rootroot00000000000000/** * FreeRDP: A Remote Desktop Protocol Client * Cryptographic Abstraction Layer * * Copyright 2011 Marc-Andre Moreau * * 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. */ #include "crypto.h" CryptoSha1 crypto_sha1_init(void) { CryptoSha1 sha1 = xmalloc(sizeof(*sha1)); SHA1_Init(&sha1->sha_ctx); return sha1; } void crypto_sha1_update(CryptoSha1 sha1, const uint8* data, uint32 length) { SHA1_Update(&sha1->sha_ctx, data, length); } void crypto_sha1_final(CryptoSha1 sha1, uint8* out_data) { SHA1_Final(out_data, &sha1->sha_ctx); xfree(sha1); } CryptoMd5 crypto_md5_init(void) { CryptoMd5 md5 = xmalloc(sizeof(*md5)); MD5_Init(&md5->md5_ctx); return md5; } void crypto_md5_update(CryptoMd5 md5, const uint8* data, uint32 length) { MD5_Update(&md5->md5_ctx, data, length); } void crypto_md5_final(CryptoMd5 md5, uint8* out_data) { MD5_Final(out_data, &md5->md5_ctx); xfree(md5); } CryptoRc4 crypto_rc4_init(const uint8* key, uint32 length) { CryptoRc4 rc4 = xmalloc(sizeof(*rc4)); RC4_set_key(&rc4->rc4_key, length, key); return rc4; } void crypto_rc4(CryptoRc4 rc4, uint32 length, const uint8* in_data, uint8* out_data) { RC4(&rc4->rc4_key, length, in_data, out_data); } void crypto_rc4_free(CryptoRc4 rc4) { xfree(rc4); } CryptoDes3 crypto_des3_encrypt_init(const uint8* key, const uint8* ivec) { CryptoDes3 des3 = xmalloc(sizeof(*des3)); EVP_CIPHER_CTX_init(&des3->des3_ctx); EVP_EncryptInit_ex(&des3->des3_ctx, EVP_des_ede3_cbc(), NULL, key, ivec); EVP_CIPHER_CTX_set_padding(&des3->des3_ctx, 0); return des3; } CryptoDes3 crypto_des3_decrypt_init(const uint8* key, const uint8* ivec) { CryptoDes3 des3 = xmalloc(sizeof(*des3)); EVP_CIPHER_CTX_init(&des3->des3_ctx); EVP_DecryptInit_ex(&des3->des3_ctx, EVP_des_ede3_cbc(), NULL, key, ivec); EVP_CIPHER_CTX_set_padding(&des3->des3_ctx, 0); return des3; } void crypto_des3_encrypt(CryptoDes3 des3, uint32 length, const uint8* in_data, uint8* out_data) { int len; EVP_EncryptUpdate(&des3->des3_ctx, out_data, &len, in_data, length); } void crypto_des3_decrypt(CryptoDes3 des3, uint32 length, const uint8* in_data, uint8* out_data) { int len; EVP_DecryptUpdate(&des3->des3_ctx, out_data, &len, in_data, length); if (length != len) abort(); /* TODO */ } void crypto_des3_free(CryptoDes3 des3) { if (des3 == NULL) return; EVP_CIPHER_CTX_cleanup(&des3->des3_ctx); xfree(des3); } CryptoHmac crypto_hmac_new(void) { CryptoHmac hmac = xmalloc(sizeof(*hmac)); HMAC_CTX_init(&hmac->hmac_ctx); return hmac; } void crypto_hmac_sha1_init(CryptoHmac hmac, const uint8* data, uint32 length) { HMAC_Init_ex(&hmac->hmac_ctx, data, length, EVP_sha1(), NULL); } void crypto_hmac_update(CryptoHmac hmac, const uint8* data, uint32 length) { HMAC_Update(&hmac->hmac_ctx, data, length); } void crypto_hmac_final(CryptoHmac hmac, uint8* out_data, uint32 length) { HMAC_Final(&hmac->hmac_ctx, out_data, &length); } void crypto_hmac_free(CryptoHmac hmac) { if (hmac == NULL) return; HMAC_CTX_cleanup(&hmac->hmac_ctx); xfree(hmac); } CryptoCert crypto_cert_read(uint8* data, uint32 length) { CryptoCert cert = xmalloc(sizeof(*cert)); /* this will move the data pointer but we don't care, we don't use it again */ cert->px509 = d2i_X509(NULL, (D2I_X509_CONST uint8 **) &data, length); return cert; } void crypto_cert_free(CryptoCert cert) { if (cert == NULL) return; X509_free(cert->px509); xfree(cert); } boolean crypto_cert_get_public_key(CryptoCert cert, rdpBlob* public_key) { uint8* p; int length; boolean status = true; EVP_PKEY* pkey = NULL; pkey = X509_get_pubkey(cert->px509); if (!pkey) { printf("crypto_cert_get_public_key: X509_get_pubkey() failed\n"); status = false; goto exit; } length = i2d_PublicKey(pkey, NULL); if (length < 1) { printf("crypto_cert_get_public_key: i2d_PublicKey() failed\n"); status = false; goto exit; } freerdp_blob_alloc(public_key, length); p = (uint8*) public_key->data; i2d_PublicKey(pkey, &p); exit: if (pkey) EVP_PKEY_free(pkey); return status; } /* * Terminal Services Signing Keys. * Yes, Terminal Services Private Key is publicly available. */ const uint8 tssk_modulus[] = { 0x3d, 0x3a, 0x5e, 0xbd, 0x72, 0x43, 0x3e, 0xc9, 0x4d, 0xbb, 0xc1, 0x1e, 0x4a, 0xba, 0x5f, 0xcb, 0x3e, 0x88, 0x20, 0x87, 0xef, 0xf5, 0xc1, 0xe2, 0xd7, 0xb7, 0x6b, 0x9a, 0xf2, 0x52, 0x45, 0x95, 0xce, 0x63, 0x65, 0x6b, 0x58, 0x3a, 0xfe, 0xef, 0x7c, 0xe7, 0xbf, 0xfe, 0x3d, 0xf6, 0x5c, 0x7d, 0x6c, 0x5e, 0x06, 0x09, 0x1a, 0xf5, 0x61, 0xbb, 0x20, 0x93, 0x09, 0x5f, 0x05, 0x6d, 0xea, 0x87 }; const uint8 tssk_privateExponent[] = { 0x87, 0xa7, 0x19, 0x32, 0xda, 0x11, 0x87, 0x55, 0x58, 0x00, 0x16, 0x16, 0x25, 0x65, 0x68, 0xf8, 0x24, 0x3e, 0xe6, 0xfa, 0xe9, 0x67, 0x49, 0x94, 0xcf, 0x92, 0xcc, 0x33, 0x99, 0xe8, 0x08, 0x60, 0x17, 0x9a, 0x12, 0x9f, 0x24, 0xdd, 0xb1, 0x24, 0x99, 0xc7, 0x3a, 0xb8, 0x0a, 0x7b, 0x0d, 0xdd, 0x35, 0x07, 0x79, 0x17, 0x0b, 0x51, 0x9b, 0xb3, 0xc7, 0x10, 0x01, 0x13, 0xe7, 0x3f, 0xf3, 0x5f }; const uint8 tssk_exponent[] = { 0x5b, 0x7b, 0x88, 0xc0 }; static void crypto_rsa_common(const uint8* input, int length, uint32 key_length, const uint8* modulus, const uint8* exponent, int exponent_size, uint8* output) { BN_CTX* ctx; int output_length; uint8* input_reverse; uint8* modulus_reverse; uint8* exponent_reverse; BIGNUM mod, exp, x, y; input_reverse = (uint8*) xmalloc(2 * key_length + exponent_size); modulus_reverse = input_reverse + key_length; exponent_reverse = modulus_reverse + key_length; memcpy(modulus_reverse, modulus, key_length); crypto_reverse(modulus_reverse, key_length); memcpy(exponent_reverse, exponent, exponent_size); crypto_reverse(exponent_reverse, exponent_size); memcpy(input_reverse, input, length); crypto_reverse(input_reverse, length); ctx = BN_CTX_new(); BN_init(&mod); BN_init(&exp); BN_init(&x); BN_init(&y); BN_bin2bn(modulus_reverse, key_length, &mod); BN_bin2bn(exponent_reverse, exponent_size, &exp); BN_bin2bn(input_reverse, length, &x); BN_mod_exp(&y, &x, &exp, &mod, ctx); output_length = BN_bn2bin(&y, output); crypto_reverse(output, output_length); if (output_length < (int) key_length) memset(output + output_length, 0, key_length - output_length); BN_free(&y); BN_clear_free(&x); BN_free(&exp); BN_free(&mod); BN_CTX_free(ctx); xfree(input_reverse); } static void crypto_rsa_public(const uint8* input, int length, uint32 key_length, const uint8* modulus, const uint8* exponent, uint8* output) { crypto_rsa_common(input, length, key_length, modulus, exponent, EXPONENT_MAX_SIZE, output); } static void crypto_rsa_private(const uint8* input, int length, uint32 key_length, const uint8* modulus, const uint8* private_exponent, uint8* output) { crypto_rsa_common(input, length, key_length, modulus, private_exponent, key_length, output); } void crypto_rsa_public_encrypt(const uint8* input, int length, uint32 key_length, const uint8* modulus, const uint8* exponent, uint8* output) { crypto_rsa_public(input, length, key_length, modulus, exponent, output); } void crypto_rsa_public_decrypt(const uint8* input, int length, uint32 key_length, const uint8* modulus, const uint8* exponent, uint8* output) { crypto_rsa_public(input, length, key_length, modulus, exponent, output); } void crypto_rsa_private_encrypt(const uint8* input, int length, uint32 key_length, const uint8* modulus, const uint8* private_exponent, uint8* output) { crypto_rsa_private(input, length, key_length, modulus, private_exponent, output); } void crypto_rsa_private_decrypt(const uint8* input, int length, uint32 key_length, const uint8* modulus, const uint8* private_exponent, uint8* output) { crypto_rsa_private(input, length, key_length, modulus, private_exponent, output); } void crypto_rsa_decrypt(const uint8* input, int length, uint32 key_length, const uint8* modulus, const uint8* private_exponent, uint8* output) { crypto_rsa_common(input, length, key_length, modulus, private_exponent, key_length, output); } void crypto_reverse(uint8* data, int length) { int i, j; uint8 temp; for (i = 0, j = length - 1; i < j; i++, j--) { temp = data[i]; data[i] = data[j]; data[j] = temp; } } void crypto_nonce(uint8* nonce, int size) { RAND_bytes((void*) nonce, size); } char* crypto_cert_fingerprint(X509* xcert) { int i = 0; char* p; char* fp_buffer; uint32 fp_len; uint8 fp[EVP_MAX_MD_SIZE]; X509_digest(xcert, EVP_sha1(), fp, &fp_len); fp_buffer = (char*) xzalloc(3 * fp_len); p = fp_buffer; for (i = 0; i < (int) (fp_len - 1); i++) { sprintf(p, "%02x:", fp[i]); p = &fp_buffer[i * 3]; } sprintf(p, "%02x", fp[i]); return fp_buffer; } char* crypto_print_name(X509_NAME* name) { char* buffer = NULL; BIO* outBIO = BIO_new(BIO_s_mem()); if (X509_NAME_print_ex(outBIO, name, 0, XN_FLAG_ONELINE) > 0) { unsigned long size = BIO_number_written(outBIO); buffer = xzalloc(size + 1); memset(buffer, 0, size + 1); BIO_read(outBIO, buffer, size); } BIO_free(outBIO); return buffer; } char* crypto_cert_subject(X509* xcert) { return crypto_print_name(X509_get_subject_name(xcert)); } char* crypto_cert_subject_common_name(X509* xcert, int* length) { int index; uint8* common_name; X509_NAME* subject_name; X509_NAME_ENTRY* entry; ASN1_STRING* entry_data; subject_name = X509_get_subject_name(xcert); if (subject_name == NULL) return NULL; index = X509_NAME_get_index_by_NID(subject_name, NID_commonName, -1); if (index < 0) return NULL; entry = X509_NAME_get_entry(subject_name, index); if (entry == NULL) return NULL; entry_data = X509_NAME_ENTRY_get_data(entry); if (entry_data == NULL) return NULL; *length = ASN1_STRING_to_UTF8(&common_name, entry_data); if (*length < 0) return NULL; return (char*) common_name; } char** crypto_cert_subject_alt_name(X509* xcert, int* count, int** lengths) { int index; int length; char** strings; uint8* string; int num_subject_alt_names; GENERAL_NAMES* subject_alt_names; GENERAL_NAME* subject_alt_name; *count = 0; subject_alt_names = X509_get_ext_d2i(xcert, NID_subject_alt_name, 0, 0); if (!subject_alt_names) return NULL; num_subject_alt_names = sk_GENERAL_NAME_num(subject_alt_names); strings = (char**) malloc(sizeof(char*) * num_subject_alt_names); *lengths = (int*) malloc(sizeof(int*) * num_subject_alt_names); for (index = 0; index < num_subject_alt_names; ++index) { subject_alt_name = sk_GENERAL_NAME_value(subject_alt_names, index); if (subject_alt_name->type == GEN_DNS) { length = ASN1_STRING_to_UTF8(&string, subject_alt_name->d.dNSName); strings[*count] = (char*) string; *lengths[*count] = length; (*count)++; } } if (*count < 1) return NULL; return strings; } char* crypto_cert_issuer(X509* xcert) { return crypto_print_name(X509_get_issuer_name(xcert)); } boolean x509_verify_certificate(CryptoCert cert, char* certificate_store_path) { X509_STORE_CTX* csc; boolean status = false; X509_STORE* cert_ctx = NULL; X509_LOOKUP* lookup = NULL; X509* xcert = cert->px509; cert_ctx = X509_STORE_new(); if (cert_ctx == NULL) goto end; OpenSSL_add_all_algorithms(); lookup = X509_STORE_add_lookup(cert_ctx, X509_LOOKUP_file()); if (lookup == NULL) goto end; lookup = X509_STORE_add_lookup(cert_ctx, X509_LOOKUP_hash_dir()); if (lookup == NULL) goto end; X509_LOOKUP_add_dir(lookup, NULL, X509_FILETYPE_DEFAULT); if (certificate_store_path != NULL) { X509_LOOKUP_add_dir(lookup, certificate_store_path, X509_FILETYPE_ASN1); } csc = X509_STORE_CTX_new(); if (csc == NULL) goto end; X509_STORE_set_flags(cert_ctx, 0); if (!X509_STORE_CTX_init(csc, cert_ctx, xcert, 0)) goto end; if (X509_verify_cert(csc) == 1) status = true; X509_STORE_CTX_free(csc); X509_STORE_free(cert_ctx); end: return status; } rdpCertificateData* crypto_get_certificate_data(X509* xcert, char* hostname) { char* fp; rdpCertificateData* certdata; fp = crypto_cert_fingerprint(xcert); certdata = certificate_data_new(hostname, fp); xfree(fp); return certdata; } void crypto_cert_print_info(X509* xcert) { char* fp; char* issuer; char* subject; subject = crypto_cert_subject(xcert); issuer = crypto_cert_issuer(xcert); fp = crypto_cert_fingerprint(xcert); printf("Certificate details:\n"); printf("\tSubject: %s\n", subject); printf("\tIssuer: %s\n", issuer); printf("\tThumbprint: %s\n", fp); printf("The above X.509 certificate could not be verified, possibly because you do not have " "the CA certificate in your certificate store, or the certificate has expired. " "Please look at the documentation on how to create local certificate store for a private CA.\n"); xfree(subject); xfree(issuer); xfree(fp); } FreeRDP-1.0.2/libfreerdp-core/crypto.h000066400000000000000000000111641207112532300174750ustar00rootroot00000000000000/** * FreeRDP: A Remote Desktop Protocol Client * Cryptographic Abstraction Layer * * Copyright 2011 Marc-Andre Moreau * * 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. */ #ifndef __CRYPTO_H #define __CRYPTO_H #ifdef _WIN32 #include "tcp.h" #endif #include #include #include #include #include #include #include #include #include #if defined(OPENSSL_VERSION_NUMBER) && (OPENSSL_VERSION_NUMBER >= 0x0090800f) #define D2I_X509_CONST const #else #define D2I_X509_CONST #endif #define EXPONENT_MAX_SIZE 4 #define MODULUS_MAX_SIZE 256 #include #include #include struct crypto_sha1_struct { SHA_CTX sha_ctx; }; struct crypto_md5_struct { MD5_CTX md5_ctx; }; struct crypto_rc4_struct { RC4_KEY rc4_key; }; struct crypto_des3_struct { EVP_CIPHER_CTX des3_ctx; }; struct crypto_hmac_struct { HMAC_CTX hmac_ctx; }; struct crypto_cert_struct { X509 * px509; }; #define CRYPTO_SHA1_DIGEST_LENGTH SHA_DIGEST_LENGTH typedef struct crypto_sha1_struct* CryptoSha1; CryptoSha1 crypto_sha1_init(void); void crypto_sha1_update(CryptoSha1 sha1, const uint8* data, uint32 length); void crypto_sha1_final(CryptoSha1 sha1, uint8* out_data); #define CRYPTO_MD5_DIGEST_LENGTH MD5_DIGEST_LENGTH typedef struct crypto_md5_struct* CryptoMd5; CryptoMd5 crypto_md5_init(void); void crypto_md5_update(CryptoMd5 md5, const uint8* data, uint32 length); void crypto_md5_final(CryptoMd5 md5, uint8* out_data); typedef struct crypto_rc4_struct* CryptoRc4; CryptoRc4 crypto_rc4_init(const uint8* key, uint32 length); void crypto_rc4(CryptoRc4 rc4, uint32 length, const uint8* in_data, uint8* out_data); void crypto_rc4_free(CryptoRc4 rc4); typedef struct crypto_des3_struct* CryptoDes3; CryptoDes3 crypto_des3_encrypt_init(const uint8* key, const uint8* ivec); CryptoDes3 crypto_des3_decrypt_init(const uint8* key, const uint8* ivec); void crypto_des3_encrypt(CryptoDes3 des3, uint32 length, const uint8 *in_data, uint8 *out_data); void crypto_des3_decrypt(CryptoDes3 des3, uint32 length, const uint8 *in_data, uint8* out_data); void crypto_des3_free(CryptoDes3 des3); typedef struct crypto_hmac_struct* CryptoHmac; CryptoHmac crypto_hmac_new(void); void crypto_hmac_sha1_init(CryptoHmac hmac, const uint8 *data, uint32 length); void crypto_hmac_update(CryptoHmac hmac, const uint8 *data, uint32 length); void crypto_hmac_final(CryptoHmac hmac, uint8 *out_data, uint32 length); void crypto_hmac_free(CryptoHmac hmac); typedef struct crypto_cert_struct* CryptoCert; #include "certificate.h" CryptoCert crypto_cert_read(uint8* data, uint32 length); char* crypto_cert_fingerprint(X509* xcert); char* crypto_cert_subject(X509* xcert); char* crypto_cert_subject_common_name(X509* xcert, int* length); char** crypto_cert_subject_alt_name(X509* xcert, int* count, int** lengths); char* crypto_cert_issuer(X509* xcert); void crypto_cert_print_info(X509* xcert); void crypto_cert_free(CryptoCert cert); boolean x509_verify_certificate(CryptoCert cert, char* certificate_store_path); rdpCertificateData* crypto_get_certificate_data(X509* xcert, char* hostname); boolean crypto_cert_get_public_key(CryptoCert cert, rdpBlob* public_key); #define TSSK_KEY_LENGTH 64 extern const uint8 tssk_modulus[]; extern const uint8 tssk_privateExponent[]; extern const uint8 tssk_exponent[]; void crypto_rsa_public_encrypt(const uint8* input, int length, uint32 key_length, const uint8* modulus, const uint8* exponent, uint8* output); void crypto_rsa_public_decrypt(const uint8* input, int length, uint32 key_length, const uint8* modulus, const uint8* exponent, uint8* output); void crypto_rsa_private_encrypt(const uint8* input, int length, uint32 key_length, const uint8* modulus, const uint8* private_exponent, uint8* output); void crypto_rsa_private_decrypt(const uint8* input, int length, uint32 key_length, const uint8* modulus, const uint8* private_exponent, uint8* output); void crypto_reverse(uint8* data, int length); void crypto_nonce(uint8* nonce, int size); #endif /* __CRYPTO_H */ FreeRDP-1.0.2/libfreerdp-core/errinfo.c000066400000000000000000000533651207112532300176250ustar00rootroot00000000000000/** * FreeRDP: A Remote Desktop Protocol Client * Error Info * * Copyright 2011 Marc-Andre Moreau * * 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. */ #include "errinfo.h" /* Protocol-independent codes */ #define ERRINFO_RPC_INITIATED_DISCONNECT_STRING \ "The disconnection was initiated by an administrative tool on the server in another session." #define ERRINFO_RPC_INITIATED_LOGOFF_STRING \ "The disconnection was due to a forced logoff initiated by an administrative tool on the server in another session." #define ERRINFO_IDLE_TIMEOUT_STRING \ "The idle session limit timer on the server has elapsed." #define ERRINFO_LOGON_TIMEOUT_STRING \ "The active session limit timer on the server has elapsed." #define ERRINFO_DISCONNECTED_BY_OTHER_CONNECTION_STRING \ "Another user connected to the server, forcing the disconnection of the current connection." #define ERRINFO_OUT_OF_MEMORY_STRING \ "The server ran out of available memory resources." #define ERRINFO_SERVER_DENIED_CONNECTION_STRING \ "The server denied the connection." #define ERRINFO_SERVER_INSUFFICIENT_PRIVILEGES_STRING \ "The user cannot connect to the server due to insufficient access privileges." #define ERRINFO_SERVER_FRESH_CREDENTIALS_REQUIRED_STRING \ "The server does not accept saved user credentials and requires that the user enter their credentials for each connection." #define ERRINFO_RPC_INITIATED_DISCONNECT_BY_USER_STRING \ "The disconnection was initiated by an administrative tool on the server running in the user's session." /* Protocol-independent licensing codes */ #define ERRINFO_LICENSE_INTERNAL_STRING \ "An internal error has occurred in the Terminal Services licensing component." #define ERRINFO_LICENSE_NO_LICENSE_SERVER_STRING \ "A Remote Desktop License Server ([MS-RDPELE] section 1.1) could not be found to provide a license." #define ERRINFO_LICENSE_NO_LICENSE_STRING \ "There are no Client Access Licenses ([MS-RDPELE] section 1.1) available for the target remote computer." #define ERRINFO_LICENSE_BAD_CLIENT_MSG_STRING \ "The remote computer received an invalid licensing message from the client." #define ERRINFO_LICENSE_HWID_DOESNT_MATCH_LICENSE_STRING \ "The Client Access License ([MS-RDPELE] section 1.1) stored by the client has been modified." #define ERRINFO_LICENSE_BAD_CLIENT_LICENSE_STRING \ "The Client Access License ([MS-RDPELE] section 1.1) stored by the client is in an invalid format." #define ERRINFO_LICENSE_CANT_FINISH_PROTOCOL_STRING \ "Network problems have caused the licensing protocol ([MS-RDPELE] section 1.3.3) to be terminated." #define ERRINFO_LICENSE_CLIENT_ENDED_PROTOCOL_STRING \ "The client prematurely ended the licensing protocol ([MS-RDPELE] section 1.3.3)." #define ERRINFO_LICENSE_BAD_CLIENT_ENCRYPTION_STRING \ "A licensing message ([MS-RDPELE] sections 2.2 and 5.1) was incorrectly encrypted." #define ERRINFO_LICENSE_CANT_UPGRADE_LICENSE_STRING \ "The Client Access License ([MS-RDPELE] section 1.1) stored by the client could not be upgraded or renewed." #define ERRINFO_LICENSE_NO_REMOTE_CONNECTIONS_STRING \ "The remote computer is not licensed to accept remote connections." /* RDP specific codes */ #define ERRINFO_UNKNOWN_DATA_PDU_TYPE_STRING \ "Unknown pduType2 field in a received Share Data Header (section 2.2.8.1.1.1.2)." #define ERRINFO_UNKNOWN_PDU_TYPE_STRING \ "Unknown pduType field in a received Share Control Header (section 2.2.8.1.1.1.1)." #define ERRINFO_DATA_PDU_SEQUENCE_STRING \ "An out-of-sequence Slow-Path Data PDU (section 2.2.8.1.1.1.1) has been received." #define ERRINFO_CONTROL_PDU_SEQUENCE_STRING \ "An out-of-sequence Slow-Path Non-Data PDU (section 2.2.8.1.1.1.1) has been received." #define ERRINFO_INVALID_CONTROL_PDU_ACTION_STRING \ "A Control PDU (sections 2.2.1.15 and 2.2.1.16) has been received with an invalid action field." #define ERRINFO_INVALID_INPUT_PDU_TYPE_STRING \ "(a) A Slow-Path Input Event (section 2.2.8.1.1.3.1.1) has been received with an invalid messageType field.\n" \ "(b) A Fast-Path Input Event (section 2.2.8.1.2.2) has been received with an invalid eventCode field." #define ERRINFO_INVALID_INPUT_PDU_MOUSE_STRING \ "(a) A Slow-Path Mouse Event (section 2.2.8.1.1.3.1.1.3) or Extended Mouse Event " \ "(section 2.2.8.1.1.3.1.1.4) has been received with an invalid pointerFlags field.\n" \ "(b) A Fast-Path Mouse Event (section 2.2.8.1.2.2.3) or Fast-Path Extended Mouse Event " \ "(section 2.2.8.1.2.2.4) has been received with an invalid pointerFlags field." #define ERRINFO_INVALID_REFRESH_RECT_PDU_STRING \ "An invalid Refresh Rect PDU (section 2.2.11.2) has been received." #define ERRINFO_CREATE_USER_DATA_FAILED_STRING \ "The server failed to construct the GCC Conference Create Response user data (section 2.2.1.4)." #define ERRINFO_CONNECT_FAILED_STRING \ "Processing during the Channel Connection phase of the RDP Connection Sequence " \ "(see section 1.3.1.1 for an overview of the RDP Connection Sequence phases) has failed." #define ERRINFO_CONFIRM_ACTIVE_HAS_WRONG_SHAREID_STRING \ "A Confirm Active PDU (section 2.2.1.13.2) was received from the client with an invalid shareId field." #define ERRINFO_CONFIRM_ACTIVE_HAS_WRONG_ORIGINATOR_STRING \ "A Confirm Active PDU (section 2.2.1.13.2) was received from the client with an invalid originatorId field." #define ERRINFO_PERSISTENT_KEY_PDU_BAD_LENGTH_STRING \ "There is not enough data to process a Persistent Key List PDU (section 2.2.1.17)." #define ERRINFO_PERSISTENT_KEY_PDU_ILLEGAL_FIRST_STRING \ "A Persistent Key List PDU (section 2.2.1.17) marked as PERSIST_PDU_FIRST (0x01) was received after the reception " \ "of a prior Persistent Key List PDU also marked as PERSIST_PDU_FIRST." #define ERRINFO_PERSISTENT_KEY_PDU_TOO_MANY_TOTAL_KEYS_STRING \ "A Persistent Key List PDU (section 2.2.1.17) was received which specified a total number of bitmap cache entries larger than 262144." #define ERRINFO_PERSISTENT_KEY_PDU_TOO_MANY_CACHE_KEYS_STRING \ "A Persistent Key List PDU (section 2.2.1.17) was received which specified an invalid total number of keys for a bitmap cache " \ "(the number of entries that can be stored within each bitmap cache is specified in the Revision 1 or 2 Bitmap Cache Capability Set " \ "(section 2.2.7.1.4) that is sent from client to server)." #define ERRINFO_INPUT_PDU_BAD_LENGTH_STRING \ "There is not enough data to process Input Event PDU Data (section 2.2.8.1.1.3.1) or a Fast-Path Input Event PDU (section 2.2.8.1.2)." \ #define ERRINFO_BITMAP_CACHE_ERROR_PDU_BAD_LENGTH_STRING \ "There is not enough data to process the shareDataHeader, NumInfoBlocks, " \ "Pad1, and Pad2 fields of the Bitmap Cache Error PDU Data ([MS-RDPEGDI] section 2.2.2.3.1.1)." #define ERRINFO_SECURITY_DATA_TOO_SHORT_STRING \ "(a) The dataSignature field of the Fast-Path Input Event PDU (section 2.2.8.1.2) does not contain enough data.\n" \ "(b) The fipsInformation and dataSignature fields of the Fast-Path Input Event PDU (section 2.2.8.1.2) do not contain enough data." #define ERRINFO_VCHANNEL_DATA_TOO_SHORT_STRING \ "(a) There is not enough data in the Client Network Data (section 2.2.1.3.4) to read the virtual channel configuration data.\n" \ "(b) There is not enough data to read a complete Channel PDU Header (section 2.2.6.1.1)." #define ERRINFO_SHARE_DATA_TOO_SHORT_STRING \ "(a) There is not enough data to process Control PDU Data (section 2.2.1.15.1).\n" \ "(b) There is not enough data to read a complete Share Control Header (section 2.2.8.1.1.1.1).\n" \ "(c) There is not enough data to read a complete Share Data Header (section 2.2.8.1.1.1.2) of a Slow-Path Data PDU (section 2.2.8.1.1.1.1).\n" \ "(d) There is not enough data to process Font List PDU Data (section 2.2.1.18.1)." #define ERRINFO_BAD_SUPPRESS_OUTPUT_PDU_STRING \ "(a) There is not enough data to process Suppress Output PDU Data (section 2.2.11.3.1).\n" \ "(b) The allowDisplayUpdates field of the Suppress Output PDU Data (section 2.2.11.3.1) is invalid." #define ERRINFO_CONFIRM_ACTIVE_PDU_TOO_SHORT_STRING \ "(a) There is not enough data to read the shareControlHeader, shareId, originatorId, lengthSourceDescriptor, " \ "and lengthCombinedCapabilities fields of the Confirm Active PDU Data (section 2.2.1.13.2.1).\n" \ "(b) There is not enough data to read the sourceDescriptor, numberCapabilities, pad2Octets, and capabilitySets " \ "fields of the Confirm Active PDU Data (section 2.2.1.13.2.1)." #define ERRINFO_CAPABILITY_SET_TOO_SMALL_STRING \ "There is not enough data to read the capabilitySetType and the lengthCapability fields in a received Capability Set (section 2.2.1.13.1.1.1)." #define ERRINFO_CAPABILITY_SET_TOO_LARGE_STRING \ "A Capability Set (section 2.2.1.13.1.1.1) has been received with a lengthCapability " \ "field that contains a value greater than the total length of the data received." #define ERRINFO_NO_CURSOR_CACHE_STRING \ "(a) Both the colorPointerCacheSize and pointerCacheSize fields in the Pointer Capability Set (section 2.2.7.1.5) are set to zero.\n" \ "(b) The pointerCacheSize field in the Pointer Capability Set (section 2.2.7.1.5) is not present, and the colorPointerCacheSize field is set to zero." #define ERRINFO_BAD_CAPABILITIES_STRING \ "The capabilities received from the client in the Confirm Active PDU (section 2.2.1.13.2) were not accepted by the server." #define ERRINFO_VIRTUAL_CHANNEL_DECOMPRESSION_STRING \ "An error occurred while using the bulk compressor (section 3.1.8 and [MS-RDPEGDI] section 3.1.8) to decompress a Virtual Channel PDU (section 2.2.6.1)" #define ERRINFO_INVALID_VC_COMPRESSION_TYPE_STRING \ "An invalid bulk compression package was specified in the flags field of the Channel PDU Header (section 2.2.6.1.1)." #define ERRINFO_INVALID_CHANNEL_ID_STRING \ "An invalid MCS channel ID was specified in the mcsPdu field of the Virtual Channel PDU (section 2.2.6.1)." #define ERRINFO_VCHANNELS_TOO_MANY_STRING \ "The client requested more than the maximum allowed 31 static virtual channels in the Client Network Data (section 2.2.1.3.4)." #define ERRINFO_REMOTEAPP_NOT_ENABLED_STRING \ "The INFO_RAIL flag (0x00008000) MUST be set in the flags field of the Info Packet (section 2.2.1.11.1.1) " \ "as the session on the remote server can only host remote applications." #define ERRINFO_CACHE_CAP_NOT_SET_STRING \ "The client sent a Persistent Key List PDU (section 2.2.1.17) without including the prerequisite Revision 2 Bitmap Cache " \ "Capability Set (section 2.2.7.1.4.2) in the Confirm Active PDU (section 2.2.1.13.2)." #define ERRINFO_BITMAP_CACHE_ERROR_PDU_BAD_LENGTH2_STRING \ "The NumInfoBlocks field in the Bitmap Cache Error PDU Data is inconsistent with the amount of data in the " \ "Info field ([MS-RDPEGDI] section 2.2.2.3.1.1)." #define ERRINFO_OFFSCREEN_CACHE_ERROR_PDU_BAD_LENGTH_STRING \ "There is not enough data to process an Offscreen Bitmap Cache Error PDU ([MS-RDPEGDI] section 2.2.2.3.2)." #define ERRINFO_DRAWNINEGRID_CACHE_ERROR_PDU_BAD_LENGTH_STRING \ "There is not enough data to process a DrawNineGrid Cache Error PDU ([MS-RDPEGDI] section 2.2.2.3.3)." #define ERRINFO_GDIPLUS_PDU_BAD_LENGTH_STRING \ "There is not enough data to process a GDI+ Error PDU ([MS-RDPEGDI] section 2.2.2.3.4)." #define ERRINFO_SECURITY_DATA_TOO_SHORT2_STRING \ "There is not enough data to read a Basic Security Header (section 2.2.8.1.1.2.1)." #define ERRINFO_SECURITY_DATA_TOO_SHORT3_STRING \ "There is not enough data to read a Non-FIPS Security Header (section 2.2.8.1.1.2.2) or FIPS Security Header (section 2.2.8.1.1.2.3)." #define ERRINFO_SECURITY_DATA_TOO_SHORT4_STRING \ "There is not enough data to read the basicSecurityHeader and length fields of the Security Exchange PDU Data (section 2.2.1.10.1)." #define ERRINFO_SECURITY_DATA_TOO_SHORT5_STRING \ "There is not enough data to read the CodePage, flags, cbDomain, cbUserName, cbPassword, cbAlternateShell, " \ "cbWorkingDir, Domain, UserName, Password, AlternateShell, and WorkingDir fields in the Info Packet (section 2.2.1.11.1.1)." #define ERRINFO_SECURITY_DATA_TOO_SHORT6_STRING \ "There is not enough data to read the CodePage, flags, cbDomain, cbUserName, cbPassword, cbAlternateShell, " \ "and cbWorkingDir fields in the Info Packet (section 2.2.1.11.1.1)." #define ERRINFO_SECURITY_DATA_TOO_SHORT7_STRING \ "There is not enough data to read the clientAddressFamily and cbClientAddress fields in the Extended Info Packet (section 2.2.1.11.1.1.1)." #define ERRINFO_SECURITY_DATA_TOO_SHORT8_STRING \ "There is not enough data to read the clientAddress field in the Extended Info Packet (section 2.2.1.11.1.1.1)." #define ERRINFO_SECURITY_DATA_TOO_SHORT9_STRING \ "There is not enough data to read the cbClientDir field in the Extended Info Packet (section 2.2.1.11.1.1.1)." #define ERRINFO_SECURITY_DATA_TOO_SHORT10_STRING \ "There is not enough data to read the clientDir field in the Extended Info Packet (section 2.2.1.11.1.1.1)." #define ERRINFO_SECURITY_DATA_TOO_SHORT11_STRING \ "There is not enough data to read the clientTimeZone field in the Extended Info Packet (section 2.2.1.11.1.1.1)." #define ERRINFO_SECURITY_DATA_TOO_SHORT12_STRING \ "There is not enough data to read the clientSessionId field in the Extended Info Packet (section 2.2.1.11.1.1.1)." #define ERRINFO_SECURITY_DATA_TOO_SHORT13_STRING \ "There is not enough data to read the performanceFlags field in the Extended Info Packet (section 2.2.1.11.1.1.1)." #define ERRINFO_SECURITY_DATA_TOO_SHORT14_STRING \ "There is not enough data to read the cbAutoReconnectLen field in the Extended Info Packet (section 2.2.1.11.1.1.1)." #define ERRINFO_SECURITY_DATA_TOO_SHORT15_STRING \ "There is not enough data to read the autoReconnectCookie field in the Extended Info Packet (section 2.2.1.11.1.1.1)." #define ERRINFO_SECURITY_DATA_TOO_SHORT16_STRING \ "The cbAutoReconnectLen field in the Extended Info Packet (section 2.2.1.11.1.1.1) contains a value " \ "which is larger than the maximum allowed length of 128 bytes." #define ERRINFO_SECURITY_DATA_TOO_SHORT17_STRING \ "There is not enough data to read the clientAddressFamily and cbClientAddress fields in the Extended Info Packet (section 2.2.1.11.1.1.1)." #define ERRINFO_SECURITY_DATA_TOO_SHORT18_STRING \ "There is not enough data to read the clientAddress field in the Extended Info Packet (section 2.2.1.11.1.1.1)." #define ERRINFO_SECURITY_DATA_TOO_SHORT19_STRING \ "There is not enough data to read the cbClientDir field in the Extended Info Packet (section 2.2.1.11.1.1.1)." #define ERRINFO_SECURITY_DATA_TOO_SHORT20_STRING \ "There is not enough data to read the clientDir field in the Extended Info Packet (section 2.2.1.11.1.1.1)." #define ERRINFO_SECURITY_DATA_TOO_SHORT21_STRING \ "There is not enough data to read the clientTimeZone field in the Extended Info Packet (section 2.2.1.11.1.1.1)." #define ERRINFO_SECURITY_DATA_TOO_SHORT22_STRING \ "There is not enough data to read the clientSessionId field in the Extended Info Packet (section 2.2.1.11.1.1.1)." #define ERRINFO_SECURITY_DATA_TOO_SHORT23_STRING \ "There is not enough data to read the Client Info PDU Data (section 2.2.1.11.1)." #define ERRINFO_BAD_MONITOR_DATA_STRING \ "The monitorCount field in the Client Monitor Data (section 2.2.1.3.6) is invalid." #define ERRINFO_VC_DECOMPRESSED_REASSEMBLE_FAILED_STRING \ "The server-side decompression buffer is invalid, or the size of the decompressed VC data exceeds " \ "the chunking size specified in the Virtual Channel Capability Set (section 2.2.7.1.10)." #define ERRINFO_VC_DATA_TOO_LONG_STRING \ "The size of a received Virtual Channel PDU (section 2.2.6.1) exceeds the chunking size specified " \ "in the Virtual Channel Capability Set (section 2.2.7.1.10)." #define ERRINFO_GRAPHICS_MODE_NOT_SUPPORTED_STRING \ "The graphics mode requested by the client is not supported by the server." #define ERRINFO_GRAPHICS_SUBSYSTEM_RESET_FAILED_STRING \ "The server-side graphics subsystem failed to reset." #define ERRINFO_UPDATE_SESSION_KEY_FAILED_STRING \ "An attempt to update the session keys while using Standard RDP Security mechanisms (section 5.3.7) failed." #define ERRINFO_DECRYPT_FAILED_STRING \ "(a) Decryption using Standard RDP Security mechanisms (section 5.3.6) failed.\n" \ "(b) Session key creation using Standard RDP Security mechanisms (section 5.3.5) failed." #define ERRINFO_ENCRYPT_FAILED_STRING \ "Encryption using Standard RDP Security mechanisms (section 5.3.6) failed." #define ERRINFO_ENCRYPTION_PACKAGE_MISMATCH_STRING \ "Failed to find a usable Encryption Method (section 5.3.2) in the encryptionMethods field of the Client Security Data (section 2.2.1.4.3)." #define ERRINFO_DECRYPT_FAILED2_STRING \ "Unencrypted data was encountered in a protocol stream which is meant to be encrypted with Standard RDP Security mechanisms (section 5.3.6)." /* Special codes */ #define ERRINFO_SUCCESS_STRING "Success." #define ERRINFO_NONE_STRING "" static const ERRINFO ERRINFO_CODES[] = { ERRINFO_DEFINE(SUCCESS), /* Protocol-independent codes */ ERRINFO_DEFINE(RPC_INITIATED_DISCONNECT), ERRINFO_DEFINE(RPC_INITIATED_LOGOFF), ERRINFO_DEFINE(IDLE_TIMEOUT), ERRINFO_DEFINE(LOGON_TIMEOUT), ERRINFO_DEFINE(DISCONNECTED_BY_OTHER_CONNECTION), ERRINFO_DEFINE(OUT_OF_MEMORY), ERRINFO_DEFINE(SERVER_DENIED_CONNECTION), ERRINFO_DEFINE(SERVER_INSUFFICIENT_PRIVILEGES), ERRINFO_DEFINE(SERVER_FRESH_CREDENTIALS_REQUIRED), ERRINFO_DEFINE(RPC_INITIATED_DISCONNECT_BY_USER), /* Protocol-independent licensing codes */ ERRINFO_DEFINE(LICENSE_INTERNAL), ERRINFO_DEFINE(LICENSE_NO_LICENSE_SERVER), ERRINFO_DEFINE(LICENSE_NO_LICENSE), ERRINFO_DEFINE(LICENSE_BAD_CLIENT_MSG), ERRINFO_DEFINE(LICENSE_HWID_DOESNT_MATCH_LICENSE), ERRINFO_DEFINE(LICENSE_BAD_CLIENT_LICENSE), ERRINFO_DEFINE(LICENSE_CANT_FINISH_PROTOCOL), ERRINFO_DEFINE(LICENSE_CLIENT_ENDED_PROTOCOL), ERRINFO_DEFINE(LICENSE_BAD_CLIENT_ENCRYPTION), ERRINFO_DEFINE(LICENSE_CANT_UPGRADE_LICENSE), ERRINFO_DEFINE(LICENSE_NO_REMOTE_CONNECTIONS), /* RDP specific codes */ ERRINFO_DEFINE(UNKNOWN_DATA_PDU_TYPE), ERRINFO_DEFINE(UNKNOWN_PDU_TYPE), ERRINFO_DEFINE(DATA_PDU_SEQUENCE), ERRINFO_DEFINE(CONTROL_PDU_SEQUENCE), ERRINFO_DEFINE(INVALID_CONTROL_PDU_ACTION), ERRINFO_DEFINE(INVALID_INPUT_PDU_TYPE), ERRINFO_DEFINE(INVALID_INPUT_PDU_MOUSE), ERRINFO_DEFINE(INVALID_REFRESH_RECT_PDU), ERRINFO_DEFINE(CREATE_USER_DATA_FAILED), ERRINFO_DEFINE(CONNECT_FAILED), ERRINFO_DEFINE(CONFIRM_ACTIVE_HAS_WRONG_SHAREID), ERRINFO_DEFINE(CONFIRM_ACTIVE_HAS_WRONG_ORIGINATOR), ERRINFO_DEFINE(PERSISTENT_KEY_PDU_BAD_LENGTH), ERRINFO_DEFINE(PERSISTENT_KEY_PDU_ILLEGAL_FIRST), ERRINFO_DEFINE(PERSISTENT_KEY_PDU_TOO_MANY_TOTAL_KEYS), ERRINFO_DEFINE(PERSISTENT_KEY_PDU_TOO_MANY_CACHE_KEYS), ERRINFO_DEFINE(INPUT_PDU_BAD_LENGTH), ERRINFO_DEFINE(BITMAP_CACHE_ERROR_PDU_BAD_LENGTH), ERRINFO_DEFINE(SECURITY_DATA_TOO_SHORT), ERRINFO_DEFINE(VCHANNEL_DATA_TOO_SHORT ), ERRINFO_DEFINE(SHARE_DATA_TOO_SHORT), ERRINFO_DEFINE(BAD_SUPPRESS_OUTPUT_PDU), ERRINFO_DEFINE(CONFIRM_ACTIVE_PDU_TOO_SHORT), ERRINFO_DEFINE(CAPABILITY_SET_TOO_SMALL), ERRINFO_DEFINE(CAPABILITY_SET_TOO_LARGE), ERRINFO_DEFINE(NO_CURSOR_CACHE), ERRINFO_DEFINE(BAD_CAPABILITIES), ERRINFO_DEFINE(VIRTUAL_CHANNEL_DECOMPRESSION), ERRINFO_DEFINE(INVALID_VC_COMPRESSION_TYPE), ERRINFO_DEFINE(INVALID_CHANNEL_ID), ERRINFO_DEFINE(VCHANNELS_TOO_MANY), ERRINFO_DEFINE(REMOTEAPP_NOT_ENABLED), ERRINFO_DEFINE(CACHE_CAP_NOT_SET), ERRINFO_DEFINE(BITMAP_CACHE_ERROR_PDU_BAD_LENGTH2), ERRINFO_DEFINE(OFFSCREEN_CACHE_ERROR_PDU_BAD_LENGTH), ERRINFO_DEFINE(DRAWNINEGRID_CACHE_ERROR_PDU_BAD_LENGTH), ERRINFO_DEFINE(GDIPLUS_PDU_BAD_LENGTH), ERRINFO_DEFINE(SECURITY_DATA_TOO_SHORT2), ERRINFO_DEFINE(SECURITY_DATA_TOO_SHORT3), ERRINFO_DEFINE(SECURITY_DATA_TOO_SHORT4), ERRINFO_DEFINE(SECURITY_DATA_TOO_SHORT5), ERRINFO_DEFINE(SECURITY_DATA_TOO_SHORT6), ERRINFO_DEFINE(SECURITY_DATA_TOO_SHORT7), ERRINFO_DEFINE(SECURITY_DATA_TOO_SHORT8), ERRINFO_DEFINE(SECURITY_DATA_TOO_SHORT9), ERRINFO_DEFINE(SECURITY_DATA_TOO_SHORT10), ERRINFO_DEFINE(SECURITY_DATA_TOO_SHORT11), ERRINFO_DEFINE(SECURITY_DATA_TOO_SHORT12), ERRINFO_DEFINE(SECURITY_DATA_TOO_SHORT13), ERRINFO_DEFINE(SECURITY_DATA_TOO_SHORT14), ERRINFO_DEFINE(SECURITY_DATA_TOO_SHORT15), ERRINFO_DEFINE(SECURITY_DATA_TOO_SHORT16), ERRINFO_DEFINE(SECURITY_DATA_TOO_SHORT17), ERRINFO_DEFINE(SECURITY_DATA_TOO_SHORT18), ERRINFO_DEFINE(SECURITY_DATA_TOO_SHORT19), ERRINFO_DEFINE(SECURITY_DATA_TOO_SHORT20), ERRINFO_DEFINE(SECURITY_DATA_TOO_SHORT21), ERRINFO_DEFINE(SECURITY_DATA_TOO_SHORT22), ERRINFO_DEFINE(SECURITY_DATA_TOO_SHORT23), ERRINFO_DEFINE(BAD_MONITOR_DATA), ERRINFO_DEFINE(VC_DECOMPRESSED_REASSEMBLE_FAILED), ERRINFO_DEFINE(VC_DATA_TOO_LONG), ERRINFO_DEFINE(GRAPHICS_MODE_NOT_SUPPORTED), ERRINFO_DEFINE(GRAPHICS_SUBSYSTEM_RESET_FAILED), ERRINFO_DEFINE(UPDATE_SESSION_KEY_FAILED), ERRINFO_DEFINE(DECRYPT_FAILED), ERRINFO_DEFINE(ENCRYPT_FAILED), ERRINFO_DEFINE(ENCRYPTION_PACKAGE_MISMATCH), ERRINFO_DEFINE(DECRYPT_FAILED2), ERRINFO_DEFINE(NONE) }; void rdp_print_errinfo(uint32 code) { const ERRINFO* errInfo; errInfo = &ERRINFO_CODES[0]; while (errInfo->code != ERRINFO_NONE) { if (code == errInfo->code) { printf("%s (0x%08X):\n%s\n", errInfo->name, code, errInfo->info); return; } errInfo++; } printf("ERRINFO_UNKNOWN 0x%08X: Unknown error.\n", code); } FreeRDP-1.0.2/libfreerdp-core/errinfo.h000066400000000000000000000137341207112532300176260ustar00rootroot00000000000000/** * FreeRDP: A Remote Desktop Protocol Client * Error Info * * Copyright 2011 Marc-Andre Moreau * * 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. */ #ifndef __ERRINFO_H #define __ERRINFO_H #include /* Protocol-independent codes */ #define ERRINFO_RPC_INITIATED_DISCONNECT 0x00000001 #define ERRINFO_RPC_INITIATED_LOGOFF 0x00000002 #define ERRINFO_IDLE_TIMEOUT 0x00000003 #define ERRINFO_LOGON_TIMEOUT 0x00000004 #define ERRINFO_DISCONNECTED_BY_OTHER_CONNECTION 0x00000005 #define ERRINFO_OUT_OF_MEMORY 0x00000006 #define ERRINFO_SERVER_DENIED_CONNECTION 0x00000007 #define ERRINFO_SERVER_INSUFFICIENT_PRIVILEGES 0x00000009 #define ERRINFO_SERVER_FRESH_CREDENTIALS_REQUIRED 0x0000000A #define ERRINFO_RPC_INITIATED_DISCONNECT_BY_USER 0x0000000B /* Protocol-independent licensing codes */ #define ERRINFO_LICENSE_INTERNAL 0x00000100 #define ERRINFO_LICENSE_NO_LICENSE_SERVER 0x00000101 #define ERRINFO_LICENSE_NO_LICENSE 0x00000102 #define ERRINFO_LICENSE_BAD_CLIENT_MSG 0x00000103 #define ERRINFO_LICENSE_HWID_DOESNT_MATCH_LICENSE 0x00000104 #define ERRINFO_LICENSE_BAD_CLIENT_LICENSE 0x00000105 #define ERRINFO_LICENSE_CANT_FINISH_PROTOCOL 0x00000106 #define ERRINFO_LICENSE_CLIENT_ENDED_PROTOCOL 0x00000107 #define ERRINFO_LICENSE_BAD_CLIENT_ENCRYPTION 0x00000108 #define ERRINFO_LICENSE_CANT_UPGRADE_LICENSE 0x00000109 #define ERRINFO_LICENSE_NO_REMOTE_CONNECTIONS 0x0000010A /* RDP specific codes */ #define ERRINFO_UNKNOWN_DATA_PDU_TYPE 0x000010C9 #define ERRINFO_UNKNOWN_PDU_TYPE 0x000010CA #define ERRINFO_DATA_PDU_SEQUENCE 0x000010CB #define ERRINFO_CONTROL_PDU_SEQUENCE 0x000010CD #define ERRINFO_INVALID_CONTROL_PDU_ACTION 0x000010CE #define ERRINFO_INVALID_INPUT_PDU_TYPE 0x000010CF #define ERRINFO_INVALID_INPUT_PDU_MOUSE 0x000010D0 #define ERRINFO_INVALID_REFRESH_RECT_PDU 0x000010D1 #define ERRINFO_CREATE_USER_DATA_FAILED 0x000010D2 #define ERRINFO_CONNECT_FAILED 0x000010D3 #define ERRINFO_CONFIRM_ACTIVE_HAS_WRONG_SHAREID 0x000010D4 #define ERRINFO_CONFIRM_ACTIVE_HAS_WRONG_ORIGINATOR 0x000010D5 #define ERRINFO_PERSISTENT_KEY_PDU_BAD_LENGTH 0x000010DA #define ERRINFO_PERSISTENT_KEY_PDU_ILLEGAL_FIRST 0x000010DB #define ERRINFO_PERSISTENT_KEY_PDU_TOO_MANY_TOTAL_KEYS 0x000010DC #define ERRINFO_PERSISTENT_KEY_PDU_TOO_MANY_CACHE_KEYS 0x000010DD #define ERRINFO_INPUT_PDU_BAD_LENGTH 0x000010DE #define ERRINFO_BITMAP_CACHE_ERROR_PDU_BAD_LENGTH 0x000010DF #define ERRINFO_SECURITY_DATA_TOO_SHORT 0x000010E0 #define ERRINFO_VCHANNEL_DATA_TOO_SHORT 0x000010E1 #define ERRINFO_SHARE_DATA_TOO_SHORT 0x000010E2 #define ERRINFO_BAD_SUPPRESS_OUTPUT_PDU 0x000010E3 #define ERRINFO_CONFIRM_ACTIVE_PDU_TOO_SHORT 0x000010E5 #define ERRINFO_CAPABILITY_SET_TOO_SMALL 0x000010E7 #define ERRINFO_CAPABILITY_SET_TOO_LARGE 0x000010E8 #define ERRINFO_NO_CURSOR_CACHE 0x000010E9 #define ERRINFO_BAD_CAPABILITIES 0x000010EA #define ERRINFO_VIRTUAL_CHANNEL_DECOMPRESSION 0x000010EC #define ERRINFO_INVALID_VC_COMPRESSION_TYPE 0x000010ED #define ERRINFO_INVALID_CHANNEL_ID 0x000010EF #define ERRINFO_VCHANNELS_TOO_MANY 0x000010F0 #define ERRINFO_REMOTEAPP_NOT_ENABLED 0x000010F3 #define ERRINFO_CACHE_CAP_NOT_SET 0x000010F4 #define ERRINFO_BITMAP_CACHE_ERROR_PDU_BAD_LENGTH2 0x000010F5 #define ERRINFO_OFFSCREEN_CACHE_ERROR_PDU_BAD_LENGTH 0x000010F6 #define ERRINFO_DRAWNINEGRID_CACHE_ERROR_PDU_BAD_LENGTH 0x000010F7 #define ERRINFO_GDIPLUS_PDU_BAD_LENGTH 0x000010F8 #define ERRINFO_SECURITY_DATA_TOO_SHORT2 0x00001111 #define ERRINFO_SECURITY_DATA_TOO_SHORT3 0x00001112 #define ERRINFO_SECURITY_DATA_TOO_SHORT4 0x00001113 #define ERRINFO_SECURITY_DATA_TOO_SHORT5 0x00001114 #define ERRINFO_SECURITY_DATA_TOO_SHORT6 0x00001115 #define ERRINFO_SECURITY_DATA_TOO_SHORT7 0x00001116 #define ERRINFO_SECURITY_DATA_TOO_SHORT8 0x00001117 #define ERRINFO_SECURITY_DATA_TOO_SHORT9 0x00001118 #define ERRINFO_SECURITY_DATA_TOO_SHORT10 0x00001119 #define ERRINFO_SECURITY_DATA_TOO_SHORT11 0x0000111A #define ERRINFO_SECURITY_DATA_TOO_SHORT12 0x0000111B #define ERRINFO_SECURITY_DATA_TOO_SHORT13 0x0000111C #define ERRINFO_SECURITY_DATA_TOO_SHORT14 0x0000111D #define ERRINFO_SECURITY_DATA_TOO_SHORT15 0x0000111E #define ERRINFO_SECURITY_DATA_TOO_SHORT16 0x0000111F #define ERRINFO_SECURITY_DATA_TOO_SHORT17 0x00001120 #define ERRINFO_SECURITY_DATA_TOO_SHORT18 0x00001121 #define ERRINFO_SECURITY_DATA_TOO_SHORT19 0x00001122 #define ERRINFO_SECURITY_DATA_TOO_SHORT20 0x00001123 #define ERRINFO_SECURITY_DATA_TOO_SHORT21 0x00001124 #define ERRINFO_SECURITY_DATA_TOO_SHORT22 0x00001125 #define ERRINFO_SECURITY_DATA_TOO_SHORT23 0x00001126 #define ERRINFO_BAD_MONITOR_DATA 0x00001129 #define ERRINFO_VC_DECOMPRESSED_REASSEMBLE_FAILED 0x0000112A #define ERRINFO_VC_DATA_TOO_LONG 0x0000112B #define ERRINFO_GRAPHICS_MODE_NOT_SUPPORTED 0x0000112D #define ERRINFO_GRAPHICS_SUBSYSTEM_RESET_FAILED 0x0000112E #define ERRINFO_UPDATE_SESSION_KEY_FAILED 0x00001191 #define ERRINFO_DECRYPT_FAILED 0x00001192 #define ERRINFO_ENCRYPT_FAILED 0x00001193 #define ERRINFO_ENCRYPTION_PACKAGE_MISMATCH 0x00001194 #define ERRINFO_DECRYPT_FAILED2 0x00001195 #define ERRINFO_SUCCESS 0x00000000 #define ERRINFO_NONE 0xFFFFFFFF struct _ERRINFO { uint32 code; char* name; char* info; }; typedef struct _ERRINFO ERRINFO; #define ERRINFO_DEFINE(_code) { ERRINFO_##_code , "ERRINFO_" #_code , ERRINFO_##_code##_STRING } void rdp_print_errinfo(uint32 code); #endif FreeRDP-1.0.2/libfreerdp-core/extension.c000066400000000000000000000123771207112532300201730ustar00rootroot00000000000000/** * FreeRDP: A Remote Desktop Protocol Client * FreeRDP Extension Plugin Interface * * Copyright 2010-2011 Vic Lee * Copyright 2011 Marc-Andre Moreau * * 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. */ #include #include #include #include #include #include #include "extension.h" #ifdef _WIN32 #define DLOPEN(f) LoadLibraryA(f) #define DLSYM(f, n) GetProcAddress(f, n) #define DLCLOSE(f) FreeLibrary(f) #define PATH_SEPARATOR '\\' #define PLUGIN_EXT "dll" #else #include #define DLOPEN(f) dlopen(f, RTLD_LOCAL | RTLD_LAZY) #define DLSYM(f, n) dlsym(f, n) #define DLCLOSE(f) dlclose(f) #define PATH_SEPARATOR '/' #ifdef __APPLE__ #define PLUGIN_EXT "dylib" #else #define PLUGIN_EXT "so" #endif #endif static uint32 FREERDP_CC extension_register_plugin(rdpExtPlugin* plugin) { rdpExtension* ext = (rdpExtension*) plugin->ext; if (ext->num_plugins >= FREERDP_EXT_MAX_COUNT) { printf("extension_register_extension: maximum number of plugins reached.\n"); return 1; } ext->plugins[ext->num_plugins++] = plugin; return 0; } static uint32 FREERDP_CC extension_register_pre_connect_hook(rdpExtPlugin* plugin, PFREERDP_EXTENSION_HOOK hook) { rdpExtension* ext = (rdpExtension*) plugin->ext; if (ext->num_pre_connect_hooks >= FREERDP_EXT_MAX_COUNT) { printf("extension_register_pre_connect_hook: maximum plugin reached.\n"); return 1; } ext->pre_connect_hooks[ext->num_pre_connect_hooks] = hook; ext->pre_connect_hooks_instances[ext->num_pre_connect_hooks] = plugin; ext->num_pre_connect_hooks++; return 0; } static uint32 FREERDP_CC extension_register_post_connect_hook(rdpExtPlugin* plugin, PFREERDP_EXTENSION_HOOK hook) { rdpExtension* ext = (rdpExtension*) plugin->ext; if (ext->num_post_connect_hooks >= FREERDP_EXT_MAX_COUNT) { printf("extension_register_post_connect_hook: maximum plugin reached.\n"); return 1; } ext->post_connect_hooks[ext->num_post_connect_hooks] = hook; ext->post_connect_hooks_instances[ext->num_post_connect_hooks] = plugin; ext->num_post_connect_hooks++; return 0; } static int extension_load_plugins(rdpExtension* extension) { int i; void* han; char path[256]; rdpSettings* settings; PFREERDP_EXTENSION_ENTRY entry; FREERDP_EXTENSION_ENTRY_POINTS entryPoints; settings = extension->instance->settings; entryPoints.ext = extension; entryPoints.pRegisterExtension = extension_register_plugin; entryPoints.pRegisterPreConnectHook = extension_register_pre_connect_hook; entryPoints.pRegisterPostConnectHook = extension_register_post_connect_hook; for (i = 0; settings->extensions[i].name[0]; i++) { if (strchr(settings->extensions[i].name, PATH_SEPARATOR) == NULL) snprintf(path, sizeof(path), EXT_PATH "/%s." PLUGIN_EXT, settings->extensions[i].name); else snprintf(path, sizeof(path), "%s", settings->extensions[i].name); han = DLOPEN(path); printf("extension_load_plugins: %s\n", path); if (han == NULL) { printf("extension_load_plugins: failed to load %s\n", path); continue; } entry = (PFREERDP_EXTENSION_ENTRY) DLSYM(han, FREERDP_EXT_EXPORT_FUNC_NAME); if (entry == NULL) { DLCLOSE(han); printf("extension_load_plugins: failed to find export function in %s\n", path); continue; } entryPoints.data = extension->instance->settings->extensions[i].data; if (entry(&entryPoints) != 0) { DLCLOSE(han); printf("extension_load_plugins: %s entry returns error.\n", path); continue; } } return 0; } static int extension_init_plugins(rdpExtension* extension) { int i; for (i = 0; i < extension->num_plugins; i++) extension->plugins[i]->init(extension->plugins[i], extension->instance); return 0; } static int extension_uninit_plugins(rdpExtension* extension) { int i; for (i = 0; i < extension->num_plugins; i++) extension->plugins[i]->uninit(extension->plugins[i], extension->instance); return 0; } int extension_pre_connect(rdpExtension* extension) { int i; for (i = 0; i < extension->num_pre_connect_hooks; i++) extension->pre_connect_hooks[i](extension->pre_connect_hooks_instances[i], extension->instance); return 0; } int extension_post_connect(rdpExtension* ext) { int i; for (i = 0; i < ext->num_post_connect_hooks; i++) ext->post_connect_hooks[i](ext->post_connect_hooks_instances[i], ext->instance); return 0; } rdpExtension* extension_new(freerdp* instance) { rdpExtension* extension = NULL; if (instance != NULL) { extension = xnew(rdpExtension); extension->instance = instance; extension_load_plugins(extension); extension_init_plugins(extension); } return extension; } void extension_free(rdpExtension* extension) { if (extension != NULL) { extension_uninit_plugins(extension); xfree(extension); } } FreeRDP-1.0.2/libfreerdp-core/extension.h000066400000000000000000000032641207112532300201730ustar00rootroot00000000000000/** * FreeRDP: A Remote Desktop Protocol Client * FreeRDP Extension Plugin Interface * * Copyright 2010-2011 Vic Lee * Copyright 2011 Marc-Andre Moreau * * 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. */ #ifndef __EXTENSION_H #define __EXTENSION_H #include #include #include #ifdef _WIN32 #include #endif #define FREERDP_EXT_MAX_COUNT 16 struct rdp_extension { freerdp* instance; rdpExtPlugin* plugins[FREERDP_EXT_MAX_COUNT]; int num_plugins; PFREERDP_EXTENSION_HOOK pre_connect_hooks[FREERDP_EXT_MAX_COUNT]; rdpExtPlugin* pre_connect_hooks_instances[FREERDP_EXT_MAX_COUNT]; int num_pre_connect_hooks; PFREERDP_EXTENSION_HOOK post_connect_hooks[FREERDP_EXT_MAX_COUNT]; rdpExtPlugin* post_connect_hooks_instances[FREERDP_EXT_MAX_COUNT]; int num_post_connect_hooks; }; typedef struct rdp_extension rdpExtension; FREERDP_API int extension_pre_connect(rdpExtension* extension); FREERDP_API int extension_post_connect(rdpExtension* extension); FREERDP_API rdpExtension* extension_new(freerdp* instance); FREERDP_API void extension_free(rdpExtension* extension); #endif /* __EXTENSION_H */ FreeRDP-1.0.2/libfreerdp-core/fastpath.c000066400000000000000000000407551207112532300177720ustar00rootroot00000000000000/** * FreeRDP: A Remote Desktop Protocol Client * Fast Path * * Copyright 2011 Vic Lee * * 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. */ #include #include #include #include #include #include "orders.h" #include "per.h" #include "update.h" #include "surface.h" #include "fastpath.h" /** * Fast-Path packet format is defined in [MS-RDPBCGR] 2.2.9.1.2, which revises * server output packets from the first byte with the goal of improving * bandwidth. * * Slow-Path packet always starts with TPKT header, which has the first * byte 0x03, while Fast-Path packet starts with 2 zero bits in the first * two less significant bits of the first byte. */ #define FASTPATH_MAX_PACKET_SIZE 0x3FFF /* * The fastpath header may be two or three bytes long. * This function assumes that at least two bytes are available in the stream * and doesn't touch third byte. */ uint16 fastpath_header_length(STREAM* s) { uint8 length1; stream_seek_uint8(s); stream_read_uint8(s, length1); stream_rewind(s, 2); return ((length1 & 0x80) != 0 ? 3 : 2); } /** * Read a Fast-Path packet header.\n * @param s stream * @param encryptionFlags * @return length */ uint16 fastpath_read_header(rdpFastPath* fastpath, STREAM* s) { uint8 header; uint16 length; stream_read_uint8(s, header); if (fastpath != NULL) { fastpath->encryptionFlags = (header & 0xC0) >> 6; fastpath->numberEvents = (header & 0x3C) >> 2; } per_read_length(s, &length); return length; } INLINE void fastpath_read_update_header(STREAM* s, uint8* updateCode, uint8* fragmentation, uint8* compression) { uint8 updateHeader; stream_read_uint8(s, updateHeader); *updateCode = updateHeader & 0x0F; *fragmentation = (updateHeader >> 4) & 0x03; *compression = (updateHeader >> 6) & 0x03; } INLINE void fastpath_write_update_header(STREAM* s, uint8 updateCode, uint8 fragmentation, uint8 compression) { uint8 updateHeader = 0; updateHeader |= updateCode & 0x0F; updateHeader |= (fragmentation & 0x03) << 4; updateHeader |= (compression & 0x03) << 6; stream_write_uint8(s, updateHeader); } uint16 fastpath_read_header_rdp(rdpFastPath* fastpath, STREAM* s) { uint8 header; uint16 length; stream_read_uint8(s, header); if (fastpath != NULL) { fastpath->encryptionFlags = (header & 0xC0) >> 6; fastpath->numberEvents = (header & 0x3C) >> 2; } per_read_length(s, &length); return length - stream_get_length(s); } static void fastpath_recv_orders(rdpFastPath* fastpath, STREAM* s) { rdpUpdate* update = fastpath->rdp->update; uint16 numberOrders; stream_read_uint16(s, numberOrders); /* numberOrders (2 bytes) */ while (numberOrders > 0) { update_recv_order(update, s); numberOrders--; } } static void fastpath_recv_update_common(rdpFastPath* fastpath, STREAM* s) { uint16 updateType; rdpUpdate* update = fastpath->rdp->update; rdpContext* context = update->context; stream_read_uint16(s, updateType); /* updateType (2 bytes) */ switch (updateType) { case UPDATE_TYPE_BITMAP: update_read_bitmap(update, s, &update->bitmap_update); IFCALL(update->BitmapUpdate, context, &update->bitmap_update); break; case UPDATE_TYPE_PALETTE: update_read_palette(update, s, &update->palette_update); IFCALL(update->Palette, context, &update->palette_update); break; } } static void fastpath_recv_update_synchronize(rdpFastPath* fastpath, STREAM* s) { stream_seek_uint16(s); /* size (2 bytes), must be set to zero */ } static void fastpath_recv_update(rdpFastPath* fastpath, uint8 updateCode, uint32 size, STREAM* s) { rdpUpdate* update = fastpath->rdp->update; rdpContext* context = fastpath->rdp->update->context; rdpPointerUpdate* pointer = update->pointer; switch (updateCode) { case FASTPATH_UPDATETYPE_ORDERS: fastpath_recv_orders(fastpath, s); break; case FASTPATH_UPDATETYPE_BITMAP: case FASTPATH_UPDATETYPE_PALETTE: fastpath_recv_update_common(fastpath, s); break; case FASTPATH_UPDATETYPE_SYNCHRONIZE: fastpath_recv_update_synchronize(fastpath, s); IFCALL(update->Synchronize, context); break; case FASTPATH_UPDATETYPE_SURFCMDS: update_recv_surfcmds(update, size, s); break; case FASTPATH_UPDATETYPE_PTR_NULL: pointer->pointer_system.type = SYSPTR_NULL; IFCALL(pointer->PointerSystem, context, &pointer->pointer_system); break; case FASTPATH_UPDATETYPE_PTR_DEFAULT: update->pointer->pointer_system.type = SYSPTR_DEFAULT; IFCALL(pointer->PointerSystem, context, &pointer->pointer_system); break; case FASTPATH_UPDATETYPE_PTR_POSITION: update_read_pointer_position(s, &pointer->pointer_position); IFCALL(pointer->PointerPosition, context, &pointer->pointer_position); break; case FASTPATH_UPDATETYPE_COLOR: update_read_pointer_color(s, &pointer->pointer_color); IFCALL(pointer->PointerColor, context, &pointer->pointer_color); break; case FASTPATH_UPDATETYPE_CACHED: update_read_pointer_cached(s, &pointer->pointer_cached); IFCALL(pointer->PointerCached, context, &pointer->pointer_cached); break; case FASTPATH_UPDATETYPE_POINTER: update_read_pointer_new(s, &pointer->pointer_new); IFCALL(pointer->PointerNew, context, &pointer->pointer_new); break; default: DEBUG_WARN("unknown updateCode 0x%X", updateCode); break; } } static void fastpath_recv_update_data(rdpFastPath* fastpath, STREAM* s) { uint16 size; int next_pos; uint32 totalSize; uint8 updateCode; uint8 fragmentation; uint8 compression; uint8 compressionFlags; STREAM* update_stream; STREAM* comp_stream; rdpRdp *rdp; uint32 roff; uint32 rlen; rdp = fastpath->rdp; fastpath_read_update_header(s, &updateCode, &fragmentation, &compression); if (compression == FASTPATH_OUTPUT_COMPRESSION_USED) stream_read_uint8(s, compressionFlags); else compressionFlags = 0; stream_read_uint16(s, size); next_pos = stream_get_pos(s) + size; comp_stream = s; if (compressionFlags & PACKET_COMPRESSED) { if (decompress_rdp(rdp, s->p, size, compressionFlags, &roff, &rlen)) { comp_stream = stream_new(0); comp_stream->data = rdp->mppc->history_buf + roff; comp_stream->p = comp_stream->data; comp_stream->size = rlen; size = comp_stream->size; } else { printf("decompress_rdp() failed\n"); stream_seek(s, size); } } update_stream = NULL; if (fragmentation == FASTPATH_FRAGMENT_SINGLE) { totalSize = size; update_stream = comp_stream; } else { if (fragmentation == FASTPATH_FRAGMENT_FIRST) stream_set_pos(fastpath->updateData, 0); stream_check_size(fastpath->updateData, size); stream_copy(fastpath->updateData, comp_stream, size); if (fragmentation == FASTPATH_FRAGMENT_LAST) { update_stream = fastpath->updateData; totalSize = stream_get_length(update_stream); stream_set_pos(update_stream, 0); } } if (update_stream) fastpath_recv_update(fastpath, updateCode, totalSize, update_stream); stream_set_pos(s, next_pos); if (comp_stream != s) xfree(comp_stream); } boolean fastpath_recv_updates(rdpFastPath* fastpath, STREAM* s) { rdpUpdate* update = fastpath->rdp->update; IFCALL(update->BeginPaint, update->context); while (stream_get_left(s) >= 3) { fastpath_recv_update_data(fastpath, s); } IFCALL(update->EndPaint, update->context); return true; } static boolean fastpath_read_input_event_header(STREAM* s, uint8* eventFlags, uint8* eventCode) { uint8 eventHeader; if (stream_get_left(s) < 1) return false; stream_read_uint8(s, eventHeader); /* eventHeader (1 byte) */ *eventFlags = (eventHeader & 0x1F); *eventCode = (eventHeader >> 5); return true; } static boolean fastpath_recv_input_event_scancode(rdpFastPath* fastpath, STREAM* s, uint8 eventFlags) { uint16 flags; uint16 code; if (stream_get_left(s) < 1) return false; stream_read_uint8(s, code); /* keyCode (1 byte) */ flags = 0; if ((eventFlags & FASTPATH_INPUT_KBDFLAGS_RELEASE)) flags |= KBD_FLAGS_RELEASE; else flags |= KBD_FLAGS_DOWN; if ((eventFlags & FASTPATH_INPUT_KBDFLAGS_EXTENDED)) flags |= KBD_FLAGS_EXTENDED; IFCALL(fastpath->rdp->input->KeyboardEvent, fastpath->rdp->input, flags, code); return true; } static boolean fastpath_recv_input_event_mouse(rdpFastPath* fastpath, STREAM* s, uint8 eventFlags) { uint16 pointerFlags; uint16 xPos; uint16 yPos; if (stream_get_left(s) < 6) return false; stream_read_uint16(s, pointerFlags); /* pointerFlags (2 bytes) */ stream_read_uint16(s, xPos); /* xPos (2 bytes) */ stream_read_uint16(s, yPos); /* yPos (2 bytes) */ IFCALL(fastpath->rdp->input->MouseEvent, fastpath->rdp->input, pointerFlags, xPos, yPos); return true; } static boolean fastpath_recv_input_event_mousex(rdpFastPath* fastpath, STREAM* s, uint8 eventFlags) { uint16 pointerFlags; uint16 xPos; uint16 yPos; if (stream_get_left(s) < 6) return false; stream_read_uint16(s, pointerFlags); /* pointerFlags (2 bytes) */ stream_read_uint16(s, xPos); /* xPos (2 bytes) */ stream_read_uint16(s, yPos); /* yPos (2 bytes) */ IFCALL(fastpath->rdp->input->ExtendedMouseEvent, fastpath->rdp->input, pointerFlags, xPos, yPos); return true; } static boolean fastpath_recv_input_event_sync(rdpFastPath* fastpath, STREAM* s, uint8 eventFlags) { IFCALL(fastpath->rdp->input->SynchronizeEvent, fastpath->rdp->input, eventFlags); return true; } static boolean fastpath_recv_input_event_unicode(rdpFastPath* fastpath, STREAM* s, uint8 eventFlags) { uint16 unicodeCode; uint16 flags; if (stream_get_left(s) < 2) return false; stream_read_uint16(s, unicodeCode); /* unicodeCode (2 bytes) */ flags = 0; if ((eventFlags & FASTPATH_INPUT_KBDFLAGS_RELEASE)) flags |= KBD_FLAGS_RELEASE; else flags |= KBD_FLAGS_DOWN; IFCALL(fastpath->rdp->input->UnicodeKeyboardEvent, fastpath->rdp->input, flags, unicodeCode); return true; } static boolean fastpath_recv_input_event(rdpFastPath* fastpath, STREAM* s) { uint8 eventFlags; uint8 eventCode; if (!fastpath_read_input_event_header(s, &eventFlags, &eventCode)) return false; switch (eventCode) { case FASTPATH_INPUT_EVENT_SCANCODE: if (!fastpath_recv_input_event_scancode(fastpath, s, eventFlags)) return false; break; case FASTPATH_INPUT_EVENT_MOUSE: if (!fastpath_recv_input_event_mouse(fastpath, s, eventFlags)) return false; break; case FASTPATH_INPUT_EVENT_MOUSEX: if (!fastpath_recv_input_event_mousex(fastpath, s, eventFlags)) return false; break; case FASTPATH_INPUT_EVENT_SYNC: if (!fastpath_recv_input_event_sync(fastpath, s, eventFlags)) return false; break; case FASTPATH_INPUT_EVENT_UNICODE: if (!fastpath_recv_input_event_unicode(fastpath, s, eventFlags)) return false; break; default: printf("Unknown eventCode %d\n", eventCode); break; } return true; } boolean fastpath_recv_inputs(rdpFastPath* fastpath, STREAM* s) { uint8 i; if (fastpath->numberEvents == 0) { /** * If numberEvents is not provided in fpInputHeader, it will be provided * as one additional byte here. */ if (stream_get_left(s) < 1) return false; stream_read_uint8(s, fastpath->numberEvents); /* eventHeader (1 byte) */ } for (i = 0; i < fastpath->numberEvents; i++) { if (!fastpath_recv_input_event(fastpath, s)) return false; } return true; } static uint32 fastpath_get_sec_bytes(rdpRdp* rdp) { uint32 sec_bytes; if (rdp->do_crypt) { sec_bytes = 8; if (rdp->settings->encryption_method == ENCRYPTION_METHOD_FIPS) sec_bytes += 4; } else sec_bytes = 0; return sec_bytes; } STREAM* fastpath_input_pdu_init(rdpFastPath* fastpath, uint8 eventFlags, uint8 eventCode) { rdpRdp *rdp; STREAM* s; rdp = fastpath->rdp; s = transport_send_stream_init(rdp->transport, 256); stream_seek(s, 3); /* fpInputHeader, length1 and length2 */ if (rdp->do_crypt) { rdp->sec_flags |= SEC_ENCRYPT; if (rdp->do_secure_checksum) rdp->sec_flags |= SEC_SECURE_CHECKSUM; } stream_seek(s, fastpath_get_sec_bytes(rdp)); stream_write_uint8(s, eventFlags | (eventCode << 5)); /* eventHeader (1 byte) */ return s; } boolean fastpath_send_input_pdu(rdpFastPath* fastpath, STREAM* s) { rdpRdp *rdp; uint16 length; uint8 eventHeader; int sec_bytes; rdp = fastpath->rdp; length = stream_get_length(s); if (length >= (2 << 14)) { printf("Maximum FastPath PDU length is 32767\n"); return false; } eventHeader = FASTPATH_INPUT_ACTION_FASTPATH; eventHeader |= (1 << 2); /* numberEvents */ if (rdp->sec_flags & SEC_ENCRYPT) eventHeader |= (FASTPATH_INPUT_ENCRYPTED << 6); if (rdp->sec_flags & SEC_SECURE_CHECKSUM) eventHeader |= (FASTPATH_INPUT_SECURE_CHECKSUM << 6); stream_set_pos(s, 0); stream_write_uint8(s, eventHeader); sec_bytes = fastpath_get_sec_bytes(fastpath->rdp); /* * We always encode length in two bytes, eventhough we could use * only one byte if length <= 0x7F. It is just easier that way, * because we can leave room for fixed-length header, store all * the data first and then store the header. */ stream_write_uint16_be(s, 0x8000 | length); if (sec_bytes > 0) { uint8* fpInputEvents; uint16 fpInputEvents_length; fpInputEvents = stream_get_tail(s) + sec_bytes; fpInputEvents_length = length - 3 - sec_bytes; if (rdp->sec_flags & SEC_SECURE_CHECKSUM) security_salted_mac_signature(rdp, fpInputEvents, fpInputEvents_length, true, stream_get_tail(s)); else security_mac_signature(rdp, fpInputEvents, fpInputEvents_length, stream_get_tail(s)); security_encrypt(fpInputEvents, fpInputEvents_length, rdp); } rdp->sec_flags = 0; stream_set_pos(s, length); if (transport_write(fastpath->rdp->transport, s) < 0) return false; return true; } STREAM* fastpath_update_pdu_init(rdpFastPath* fastpath) { STREAM* s; s = transport_send_stream_init(fastpath->rdp->transport, FASTPATH_MAX_PACKET_SIZE); stream_seek(s, 3); /* fpOutputHeader, length1 and length2 */ stream_seek(s, fastpath_get_sec_bytes(fastpath->rdp)); stream_seek(s, 3); /* updateHeader, size */ return s; } boolean fastpath_send_update_pdu(rdpFastPath* fastpath, uint8 updateCode, STREAM* s) { rdpRdp *rdp; uint8* bm; uint8* ptr; int fragment; int sec_bytes; uint16 length; boolean result; uint16 pduLength; uint16 maxLength; uint32 totalLength; uint8 fragmentation; uint8 header; STREAM* update; result = true; rdp = fastpath->rdp; sec_bytes = fastpath_get_sec_bytes(rdp); maxLength = FASTPATH_MAX_PACKET_SIZE - 6 - sec_bytes; totalLength = stream_get_length(s) - 6 - sec_bytes; stream_set_pos(s, 0); update = stream_new(0); for (fragment = 0; totalLength > 0; fragment++) { length = MIN(maxLength, totalLength); totalLength -= length; pduLength = length + 6 + sec_bytes; if (totalLength == 0) fragmentation = (fragment == 0) ? FASTPATH_FRAGMENT_SINGLE : FASTPATH_FRAGMENT_LAST; else fragmentation = (fragment == 0) ? FASTPATH_FRAGMENT_FIRST : FASTPATH_FRAGMENT_NEXT; stream_get_mark(s, bm); header = 0; if (sec_bytes > 0) header |= (FASTPATH_OUTPUT_ENCRYPTED << 6); stream_write_uint8(s, header); /* fpOutputHeader (1 byte) */ stream_write_uint8(s, 0x80 | (pduLength >> 8)); /* length1 */ stream_write_uint8(s, pduLength & 0xFF); /* length2 */ if (sec_bytes > 0) stream_seek(s, sec_bytes); fastpath_write_update_header(s, updateCode, fragmentation, 0); stream_write_uint16(s, length); stream_attach(update, bm, pduLength); stream_seek(update, pduLength); if (sec_bytes > 0) { ptr = bm + 3 + sec_bytes; if (rdp->sec_flags & SEC_SECURE_CHECKSUM) security_salted_mac_signature(rdp, ptr, length + 3, true, bm + 3); else security_mac_signature(rdp, ptr, length + 3, bm + 3); security_encrypt(ptr, length + 3, rdp); } if (transport_write(fastpath->rdp->transport, update) < 0) { stream_detach(update); result = false; break; } stream_detach(update); /* Reserve 6+sec_bytes bytes for the next fragment header, if any. */ stream_seek(s, length - 6 - sec_bytes); } stream_free(update); return result; } rdpFastPath* fastpath_new(rdpRdp* rdp) { rdpFastPath* fastpath; fastpath = xnew(rdpFastPath); fastpath->rdp = rdp; fastpath->updateData = stream_new(4096); return fastpath; } void fastpath_free(rdpFastPath* fastpath) { stream_free(fastpath->updateData); xfree(fastpath); } FreeRDP-1.0.2/libfreerdp-core/fastpath.h000066400000000000000000000062241207112532300177700ustar00rootroot00000000000000/** * FreeRDP: A Remote Desktop Protocol Client * Fast Path * * Copyright 2011 Vic Lee * * 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. */ #ifndef __FASTPATH_H #define __FASTPATH_H #include "rdp.h" #include typedef struct rdp_fastpath rdpFastPath; enum FASTPATH_INPUT_ACTION_TYPE { FASTPATH_INPUT_ACTION_FASTPATH = 0x0, FASTPATH_INPUT_ACTION_X224 = 0x3 }; enum FASTPATH_OUTPUT_ACTION_TYPE { FASTPATH_OUTPUT_ACTION_FASTPATH = 0x0, FASTPATH_OUTPUT_ACTION_X224 = 0x3 }; enum FASTPATH_INPUT_ENCRYPTION_FLAGS { FASTPATH_INPUT_SECURE_CHECKSUM = 0x1, FASTPATH_INPUT_ENCRYPTED = 0x2 }; enum FASTPATH_OUTPUT_ENCRYPTION_FLAGS { FASTPATH_OUTPUT_SECURE_CHECKSUM = 0x1, FASTPATH_OUTPUT_ENCRYPTED = 0x2 }; enum FASTPATH_UPDATETYPE { FASTPATH_UPDATETYPE_ORDERS = 0x0, FASTPATH_UPDATETYPE_BITMAP = 0x1, FASTPATH_UPDATETYPE_PALETTE = 0x2, FASTPATH_UPDATETYPE_SYNCHRONIZE = 0x3, FASTPATH_UPDATETYPE_SURFCMDS = 0x4, FASTPATH_UPDATETYPE_PTR_NULL = 0x5, FASTPATH_UPDATETYPE_PTR_DEFAULT = 0x6, FASTPATH_UPDATETYPE_PTR_POSITION = 0x8, FASTPATH_UPDATETYPE_COLOR = 0x9, FASTPATH_UPDATETYPE_CACHED = 0xA, FASTPATH_UPDATETYPE_POINTER = 0xB }; enum FASTPATH_FRAGMENT { FASTPATH_FRAGMENT_SINGLE = 0x0, FASTPATH_FRAGMENT_LAST = 0x1, FASTPATH_FRAGMENT_FIRST = 0x2, FASTPATH_FRAGMENT_NEXT = 0x3 }; enum FASTPATH_OUTPUT_COMPRESSION { FASTPATH_OUTPUT_COMPRESSION_USED = 0x2 }; /* FastPath Input Events */ enum FASTPATH_INPUT_EVENT_CODE { FASTPATH_INPUT_EVENT_SCANCODE = 0x0, FASTPATH_INPUT_EVENT_MOUSE = 0x1, FASTPATH_INPUT_EVENT_MOUSEX = 0x2, FASTPATH_INPUT_EVENT_SYNC = 0x3, FASTPATH_INPUT_EVENT_UNICODE = 0x4 }; /* FastPath Keyboard Event Flags */ enum FASTPATH_INPUT_KBDFLAGS { FASTPATH_INPUT_KBDFLAGS_RELEASE = 0x01, FASTPATH_INPUT_KBDFLAGS_EXTENDED = 0x02 }; struct rdp_fastpath { rdpRdp* rdp; uint8 encryptionFlags; uint8 numberEvents; STREAM* updateData; }; uint16 fastpath_header_length(STREAM* s); uint16 fastpath_read_header(rdpFastPath* fastpath, STREAM* s); uint16 fastpath_read_header_rdp(rdpFastPath* fastpath, STREAM* s); boolean fastpath_recv_updates(rdpFastPath* fastpath, STREAM* s); boolean fastpath_recv_inputs(rdpFastPath* fastpath, STREAM* s); STREAM* fastpath_input_pdu_init(rdpFastPath* fastpath, uint8 eventFlags, uint8 eventCode); boolean fastpath_send_input_pdu(rdpFastPath* fastpath, STREAM* s); STREAM* fastpath_update_pdu_init(rdpFastPath* fastpath); boolean fastpath_send_update_pdu(rdpFastPath* fastpath, uint8 updateCode, STREAM* s); boolean fastpath_send_surfcmd_frame_marker(rdpFastPath* fastpath, uint16 frameAction, uint32 frameId); rdpFastPath* fastpath_new(rdpRdp* rdp); void fastpath_free(rdpFastPath* fastpath); #endif FreeRDP-1.0.2/libfreerdp-core/freerdp.c000066400000000000000000000121441207112532300175760ustar00rootroot00000000000000/** * FreeRDP: A Remote Desktop Protocol Client * FreeRDP Core * * Copyright 2011 Marc-Andre Moreau * * 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. */ #include "rdp.h" #include "input.h" #include "update.h" #include "surface.h" #include "transport.h" #include "connection.h" #include "extension.h" #include #include boolean freerdp_connect(freerdp* instance) { rdpRdp* rdp; boolean status = false; rdp = instance->context->rdp; IFCALLRET(instance->PreConnect, status, instance); if (status != true) { printf("freerdp_pre_connect failed\n"); return false; } rdp->extension = extension_new(instance); extension_pre_connect(rdp->extension); status = rdp_client_connect(rdp); if (status) { if (instance->settings->dump_rfx) { instance->update->pcap_rfx = pcap_open(instance->settings->dump_rfx_file, true); if (instance->update->pcap_rfx) instance->update->dump_rfx = true; } extension_post_connect(rdp->extension); IFCALLRET(instance->PostConnect, status, instance); if (status != true) { printf("freerdp_post_connect failed\n"); return false; } if (instance->settings->play_rfx) { STREAM* s; rdpUpdate* update; pcap_record record; s = stream_new(1024); instance->update->pcap_rfx = pcap_open(instance->settings->play_rfx_file, false); if (instance->update->pcap_rfx) instance->update->play_rfx = true; update = instance->update; while (instance->update->play_rfx && pcap_has_next_record(update->pcap_rfx)) { pcap_get_next_record_header(update->pcap_rfx, &record); s->data = xrealloc(s->data, record.length); record.data = s->data; s->size = record.length; pcap_get_next_record_content(update->pcap_rfx, &record); stream_set_pos(s, 0); update->BeginPaint(update->context); update_recv_surfcmds(update, s->size, s); update->EndPaint(update->context); } xfree(s->data); return true; } } return status; } boolean freerdp_get_fds(freerdp* instance, void** rfds, int* rcount, void** wfds, int* wcount) { rdpRdp* rdp; rdp = instance->context->rdp; transport_get_fds(rdp->transport, rfds, rcount); return true; } boolean freerdp_check_fds(freerdp* instance) { int status; rdpRdp* rdp; rdp = instance->context->rdp; status = rdp_check_fds(rdp); if (status < 0) return false; return true; } void freerdp_send_keep_alive(freerdp* instance) { input_send_synchronize_event(instance->context->rdp->input, 0); } static int freerdp_send_channel_data(freerdp* instance, int channel_id, uint8* data, int size) { return rdp_send_channel_data(instance->context->rdp, channel_id, data, size); } boolean freerdp_disconnect(freerdp* instance) { rdpRdp* rdp; rdp = instance->context->rdp; transport_disconnect(rdp->transport); return true; } boolean freerdp_shall_disconnect(freerdp* instance) { return instance->context->rdp->disconnect; } void freerdp_get_version(int* major, int* minor, int* revision) { if (major != NULL) *major = FREERDP_VERSION_MAJOR; if (minor != NULL) *minor = FREERDP_VERSION_MINOR; if (revision != NULL) *revision = FREERDP_VERSION_REVISION; } void freerdp_context_new(freerdp* instance) { rdpRdp* rdp; rdp = rdp_new(instance); instance->input = rdp->input; instance->update = rdp->update; instance->settings = rdp->settings; instance->context = (rdpContext*) xzalloc(instance->context_size); instance->context->graphics = graphics_new(instance->context); instance->context->instance = instance; instance->context->rdp = rdp; instance->update->context = instance->context; instance->update->pointer->context = instance->context; instance->update->primary->context = instance->context; instance->update->secondary->context = instance->context; instance->update->altsec->context = instance->context; instance->input->context = instance->context; IFCALL(instance->ContextNew, instance, instance->context); } void freerdp_context_free(freerdp* instance) { if (instance->context == NULL) return; IFCALL(instance->ContextFree, instance, instance->context); rdp_free(instance->context->rdp); graphics_free(instance->context->graphics); xfree(instance->context); instance->context = NULL; } uint32 freerdp_error_info(freerdp* instance) { return instance->context->rdp->errorInfo; } freerdp* freerdp_new() { freerdp* instance; instance = xzalloc(sizeof(freerdp)); if (instance != NULL) { instance->context_size = sizeof(rdpContext); instance->SendChannelData = freerdp_send_channel_data; } return instance; } void freerdp_free(freerdp* instance) { if (instance) { xfree(instance); } } FreeRDP-1.0.2/libfreerdp-core/gcc.c000066400000000000000000000770601207112532300167130ustar00rootroot00000000000000/** * FreeRDP: A Remote Desktop Protocol Client * T.124 Generic Conference Control (GCC) * * Copyright 2011 Marc-Andre Moreau * * 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. */ #include #include "gcc.h" #include "certificate.h" /** * T.124 GCC is defined in: * * http://www.itu.int/rec/T-REC-T.124-199802-S/en * ITU-T T.124 (02/98): Generic Conference Control */ /** * ConnectData ::= SEQUENCE * { * t124Identifier Key, * connectPDU OCTET_STRING * } * * Key ::= CHOICE * { * object OBJECT_IDENTIFIER, * h221NonStandard H221NonStandardIdentifier * } * * ConnectGCCPDU ::= CHOICE * { * conferenceCreateRequest ConferenceCreateRequest, * conferenceCreateResponse ConferenceCreateResponse, * conferenceQueryRequest ConferenceQueryRequest, * conferenceQueryResponse ConferenceQueryResponse, * conferenceJoinRequest ConferenceJoinRequest, * conferenceJoinResponse ConferenceJoinResponse, * conferenceInviteRequest ConferenceInviteRequest, * conferenceInviteResponse ConferenceInviteResponse, * ... * } * * ConferenceCreateRequest ::= SEQUENCE * { * conferenceName ConferenceName, * convenerPassword Password OPTIONAL, * password Password OPTIONAL, * lockedConference BOOLEAN, * listedConference BOOLEAN, * conductibleConference BOOLEAN, * terminationMethod TerminationMethod, * conductorPrivileges SET OF Privilege OPTIONAL, * conductedPrivileges SET OF Privilege OPTIONAL, * nonConductedPrivileges SET OF Privilege OPTIONAL, * conferenceDescription TextString OPTIONAL, * callerIdentifier TextString OPTIONAL, * userData UserData OPTIONAL, * ..., * conferencePriority ConferencePriority OPTIONAL, * conferenceMode ConferenceMode OPTIONAL * } * * ConferenceCreateResponse ::= SEQUENCE * { * nodeID UserID, * tag INTEGER, * result ENUMERATED * { * success (0), * userRejected (1), * resourcesNotAvailable (2), * rejectedForSymmetryBreaking (3), * lockedConferenceNotSupported (4) * }, * userData UserData OPTIONAL, * ... * } * * ConferenceName ::= SEQUENCE * { * numeric SimpleNumericString * text SimpleTextString OPTIONAL, * ... * } * * SimpleNumericString ::= NumericString (SIZE (1..255)) (FROM ("0123456789")) * * UserData ::= SET OF SEQUENCE * { * key Key, * value OCTET_STRING OPTIONAL * } * * H221NonStandardIdentifier ::= OCTET STRING (SIZE (4..255)) * * UserID ::= DynamicChannelID * * ChannelID ::= INTEGER (1..65535) * StaticChannelID ::= INTEGER (1..1000) * DynamicChannelID ::= INTEGER (1001..65535) * */ /* * OID = 0.0.20.124.0.1 * { itu-t(0) recommendation(0) t(20) t124(124) version(0) 1 } * v.1 of ITU-T Recommendation T.124 (Feb 1998): "Generic Conference Control" */ uint8 t124_02_98_oid[6] = { 0, 0, 20, 124, 0, 1 }; uint8 h221_cs_key[4] = "Duca"; uint8 h221_sc_key[4] = "McDn"; /** * Read a GCC Conference Create Request.\n * @msdn{cc240836} * @param s stream * @param settings rdp settings */ boolean gcc_read_conference_create_request(STREAM* s, rdpSettings* settings) { uint16 length; uint8 choice; uint8 number; uint8 selection; /* ConnectData */ if (!per_read_choice(s, &choice)) return false; if (!per_read_object_identifier(s, t124_02_98_oid)) return false; /* ConnectData::connectPDU (OCTET_STRING) */ if (!per_read_length(s, &length)) return false; /* ConnectGCCPDU */ if (!per_read_choice(s, &choice)) return false; if (!per_read_selection(s, &selection)) return false; /* ConferenceCreateRequest::conferenceName */ if (!per_read_numeric_string(s, 1)) /* ConferenceName::numeric */ return false; if (!per_read_padding(s, 1)) /* padding */ return false; /* UserData (SET OF SEQUENCE) */ if (!per_read_number_of_sets(s, &number) || number != 1) /* one set of UserData */ return false; if (!per_read_choice(s, &choice) || choice != 0xC0) /* UserData::value present + select h221NonStandard (1) */ return false; /* h221NonStandard */ if (!per_read_octet_string(s, h221_cs_key, 4, 4)) /* h221NonStandard, client-to-server H.221 key, "Duca" */ return false; /* userData::value (OCTET_STRING) */ if (!per_read_length(s, &length)) return false; if (stream_get_left(s) < length) return false; if (!gcc_read_client_data_blocks(s, settings, length)) return false; return true; } /** * Write a GCC Conference Create Request.\n * @msdn{cc240836} * @param s stream * @param user_data client data blocks */ void gcc_write_conference_create_request(STREAM* s, STREAM* user_data) { /* ConnectData */ per_write_choice(s, 0); /* From Key select object (0) of type OBJECT_IDENTIFIER */ per_write_object_identifier(s, t124_02_98_oid); /* ITU-T T.124 (02/98) OBJECT_IDENTIFIER */ /* ConnectData::connectPDU (OCTET_STRING) */ per_write_length(s, stream_get_length(user_data) + 14); /* connectPDU length */ /* ConnectGCCPDU */ per_write_choice(s, 0); /* From ConnectGCCPDU select conferenceCreateRequest (0) of type ConferenceCreateRequest */ per_write_selection(s, 0x08); /* select optional userData from ConferenceCreateRequest */ /* ConferenceCreateRequest::conferenceName */ per_write_numeric_string(s, (uint8*)"1", 1, 1); /* ConferenceName::numeric */ per_write_padding(s, 1); /* padding */ /* UserData (SET OF SEQUENCE) */ per_write_number_of_sets(s, 1); /* one set of UserData */ per_write_choice(s, 0xC0); /* UserData::value present + select h221NonStandard (1) */ /* h221NonStandard */ per_write_octet_string(s, h221_cs_key, 4, 4); /* h221NonStandard, client-to-server H.221 key, "Duca" */ /* userData::value (OCTET_STRING) */ per_write_octet_string(s, user_data->data, stream_get_length(user_data), 0); /* array of client data blocks */ } boolean gcc_read_conference_create_response(STREAM* s, rdpSettings* settings) { uint16 length; uint32 tag; uint16 nodeID; uint8 result; uint8 choice; uint8 number; /* ConnectData */ per_read_choice(s, &choice); per_read_object_identifier(s, t124_02_98_oid); /* ConnectData::connectPDU (OCTET_STRING) */ per_read_length(s, &length); /* ConnectGCCPDU */ per_read_choice(s, &choice); /* ConferenceCreateResponse::nodeID (UserID) */ per_read_integer16(s, &nodeID, 1001); /* ConferenceCreateResponse::tag (INTEGER) */ per_read_integer(s, &tag); /* ConferenceCreateResponse::result (ENUMERATED) */ per_read_enumerated(s, &result, MCS_Result_enum_length); /* number of UserData sets */ per_read_number_of_sets(s, &number); /* UserData::value present + select h221NonStandard (1) */ per_read_choice(s, &choice); /* h221NonStandard */ if (!per_read_octet_string(s, h221_sc_key, 4, 4)) /* h221NonStandard, server-to-client H.221 key, "McDn" */ return false; /* userData (OCTET_STRING) */ per_read_length(s, &length); if (!gcc_read_server_data_blocks(s, settings, length)) { printf("gcc_read_conference_create_response: gcc_read_server_data_blocks failed\n"); return false; } return true; } void gcc_write_conference_create_response(STREAM* s, STREAM* user_data) { /* ConnectData */ per_write_choice(s, 0); per_write_object_identifier(s, t124_02_98_oid); /* ConnectData::connectPDU (OCTET_STRING) */ per_write_length(s, stream_get_length(user_data) + 2); /* ConnectGCCPDU */ per_write_choice(s, 0x14); /* ConferenceCreateResponse::nodeID (UserID) */ per_write_integer16(s, 0x79F3, 1001); /* ConferenceCreateResponse::tag (INTEGER) */ per_write_integer(s, 1); /* ConferenceCreateResponse::result (ENUMERATED) */ per_write_enumerated(s, 0, MCS_Result_enum_length); /* number of UserData sets */ per_write_number_of_sets(s, 1); /* UserData::value present + select h221NonStandard (1) */ per_write_choice(s, 0xC0); /* h221NonStandard */ per_write_octet_string(s, h221_sc_key, 4, 4); /* h221NonStandard, server-to-client H.221 key, "McDn" */ /* userData (OCTET_STRING) */ per_write_octet_string(s, user_data->data, stream_get_length(user_data), 0); /* array of server data blocks */ } boolean gcc_read_client_data_blocks(STREAM* s, rdpSettings* settings, int length) { uint16 type; uint16 blockLength; int pos; while (length > 0) { pos = stream_get_pos(s); gcc_read_user_data_header(s, &type, &blockLength); switch (type) { case CS_CORE: if (!gcc_read_client_core_data(s, settings, blockLength - 4)) return false; break; case CS_SECURITY: if (!gcc_read_client_security_data(s, settings, blockLength - 4)) return false; break; case CS_NET: if (!gcc_read_client_network_data(s, settings, blockLength - 4)) return false; break; case CS_CLUSTER: if (!gcc_read_client_cluster_data(s, settings, blockLength - 4)) return false; break; case CS_MONITOR: if (!gcc_read_client_monitor_data(s, settings, blockLength - 4)) return false; break; default: break; } length -= blockLength; stream_set_pos(s, pos + blockLength); } return true; } void gcc_write_client_data_blocks(STREAM* s, rdpSettings* settings) { gcc_write_client_core_data(s, settings); gcc_write_client_cluster_data(s, settings); gcc_write_client_security_data(s, settings); gcc_write_client_network_data(s, settings); /* extended client data supported */ if (settings->negotiationFlags) gcc_write_client_monitor_data(s, settings); } boolean gcc_read_server_data_blocks(STREAM* s, rdpSettings* settings, int length) { uint16 type; uint16 offset = 0; uint16 blockLength; uint8* holdp; while (offset < length) { holdp = s->p; if (!gcc_read_user_data_header(s, &type, &blockLength)) { printf("gcc_read_server_data_blocks: gcc_read_user_data_header failed\n"); return false; } switch (type) { case SC_CORE: if (!gcc_read_server_core_data(s, settings)) { printf("gcc_read_server_data_blocks: gcc_read_server_core_data failed\n"); return false; } break; case SC_SECURITY: if (!gcc_read_server_security_data(s, settings)) { printf("gcc_read_server_data_blocks: gcc_read_server_security_data failed\n"); return false; } break; case SC_NET: if (!gcc_read_server_network_data(s, settings)) { printf("gcc_read_server_data_blocks: gcc_read_server_network_data failed\n"); return false; } break; default: printf("gcc_read_server_data_blocks: ignoring type=%hu\n", type); break; } offset += blockLength; s->p = holdp + blockLength; } return true; } void gcc_write_server_data_blocks(STREAM* s, rdpSettings* settings) { gcc_write_server_core_data(s, settings); gcc_write_server_network_data(s, settings); gcc_write_server_security_data(s, settings); } boolean gcc_read_user_data_header(STREAM* s, uint16* type, uint16* length) { stream_read_uint16(s, *type); /* type */ stream_read_uint16(s, *length); /* length */ if (*length < 4) return false; if (stream_get_left(s) < *length - 4) return false; return true; } /** * Write a user data header (TS_UD_HEADER).\n * @msdn{cc240509} * @param s stream * @param type data block type * @param length data block length */ void gcc_write_user_data_header(STREAM* s, uint16 type, uint16 length) { stream_write_uint16(s, type); /* type */ stream_write_uint16(s, length); /* length */ } /** * Read a client core data block (TS_UD_CS_CORE).\n * @msdn{cc240510} * @param s stream * @param settings rdp settings */ boolean gcc_read_client_core_data(STREAM* s, rdpSettings* settings, uint16 blockLength) { uint32 version; uint16 colorDepth = 0; uint16 postBeta2ColorDepth = 0; uint16 highColorDepth = 0; uint16 supportedColorDepths = 0; uint16 earlyCapabilityFlags = 0; uint32 serverSelectedProtocol = 0; char* str; /* Length of all required fields, until imeFileName */ if (blockLength < 128) return false; stream_read_uint32(s, version); /* version */ settings->rdp_version = (version == RDP_VERSION_4 ? 4 : 7); stream_read_uint16(s, settings->width); /* desktopWidth */ stream_read_uint16(s, settings->height); /* desktopHeight */ stream_read_uint16(s, colorDepth); /* colorDepth */ stream_seek_uint16(s); /* SASSequence (Secure Access Sequence) */ stream_read_uint32(s, settings->kbd_layout); /* keyboardLayout */ stream_read_uint32(s, settings->client_build); /* clientBuild */ /* clientName (32 bytes, null-terminated unicode, truncated to 15 characters) */ str = freerdp_uniconv_in(settings->uniconv, stream_get_tail(s), 32); stream_seek(s, 32); snprintf(settings->client_hostname, sizeof(settings->client_hostname), "%s", str); xfree(str); stream_read_uint32(s, settings->kbd_type); /* keyboardType */ stream_read_uint32(s, settings->kbd_subtype); /* keyboardSubType */ stream_read_uint32(s, settings->kbd_fn_keys); /* keyboardFunctionKey */ stream_seek(s, 64); /* imeFileName */ blockLength -= 128; /** * The following fields are all optional. If one field is present, all of the preceding * fields MUST also be present. If one field is not present, all of the subsequent fields * MUST NOT be present. * We must check the bytes left before reading each field. */ do { if (blockLength < 2) break; stream_read_uint16(s, postBeta2ColorDepth); /* postBeta2ColorDepth */ blockLength -= 2; if (blockLength < 2) break; stream_seek_uint16(s); /* clientProductID */ blockLength -= 2; if (blockLength < 4) break; stream_seek_uint32(s); /* serialNumber */ blockLength -= 4; if (blockLength < 2) break; stream_read_uint16(s, highColorDepth); /* highColorDepth */ blockLength -= 2; if (blockLength < 2) break; stream_read_uint16(s, supportedColorDepths); /* supportedColorDepths */ blockLength -= 2; if (blockLength < 2) break; stream_read_uint16(s, earlyCapabilityFlags); /* earlyCapabilityFlags */ blockLength -= 2; if (blockLength < 64) break; str = freerdp_uniconv_in(settings->uniconv, stream_get_tail(s), 64); stream_seek(s, 64); snprintf(settings->client_product_id, sizeof(settings->client_product_id), "%s", str); xfree(str); blockLength -= 64; if (blockLength < 1) break; stream_read_uint8(s, settings->performance_flags); /* connectionType */ blockLength -= 1; if (blockLength < 1) break; stream_seek_uint8(s); /* pad1octet */ blockLength -= 1; if (blockLength < 4) break; stream_read_uint32(s, serverSelectedProtocol); /* serverSelectedProtocol */ blockLength -= 4; if (settings->selected_protocol != serverSelectedProtocol) return false; } while (0); if (highColorDepth > 0) settings->color_depth = highColorDepth; else if (postBeta2ColorDepth > 0) { switch (postBeta2ColorDepth) { case RNS_UD_COLOR_4BPP: settings->color_depth = 4; break; case RNS_UD_COLOR_8BPP: settings->color_depth = 8; break; case RNS_UD_COLOR_16BPP_555: settings->color_depth = 15; break; case RNS_UD_COLOR_16BPP_565: settings->color_depth = 16; break; case RNS_UD_COLOR_24BPP: settings->color_depth = 24; break; default: return false; } } else { switch (colorDepth) { case RNS_UD_COLOR_4BPP: settings->color_depth = 4; break; case RNS_UD_COLOR_8BPP: settings->color_depth = 8; break; default: return false; } } return true; } /** * Write a client core data block (TS_UD_CS_CORE).\n * @msdn{cc240510} * @param s stream * @param settings rdp settings */ void gcc_write_client_core_data(STREAM* s, rdpSettings* settings) { uint32 version; char* clientName; size_t clientNameLength; uint8 connectionType; uint16 highColorDepth; uint16 supportedColorDepths; uint16 earlyCapabilityFlags; char* clientDigProductId; size_t clientDigProductIdLength; gcc_write_user_data_header(s, CS_CORE, 216); version = settings->rdp_version >= 5 ? RDP_VERSION_5_PLUS : RDP_VERSION_4; clientName = freerdp_uniconv_out(settings->uniconv, settings->client_hostname, &clientNameLength); clientDigProductId = freerdp_uniconv_out(settings->uniconv, settings->client_product_id, &clientDigProductIdLength); stream_write_uint32(s, version); /* version */ stream_write_uint16(s, settings->width); /* desktopWidth */ stream_write_uint16(s, settings->height); /* desktopHeight */ stream_write_uint16(s, RNS_UD_COLOR_8BPP); /* colorDepth, ignored because of postBeta2ColorDepth */ stream_write_uint16(s, RNS_UD_SAS_DEL); /* SASSequence (Secure Access Sequence) */ stream_write_uint32(s, settings->kbd_layout); /* keyboardLayout */ stream_write_uint32(s, settings->client_build); /* clientBuild */ /* clientName (32 bytes, null-terminated unicode, truncated to 15 characters) */ if (clientNameLength > 30) { clientNameLength = 30; clientName[clientNameLength] = 0; clientName[clientNameLength + 1] = 0; } stream_write(s, clientName, clientNameLength + 2); stream_write_zero(s, 32 - clientNameLength - 2); xfree(clientName); stream_write_uint32(s, settings->kbd_type); /* keyboardType */ stream_write_uint32(s, settings->kbd_subtype); /* keyboardSubType */ stream_write_uint32(s, settings->kbd_fn_keys); /* keyboardFunctionKey */ stream_write_zero(s, 64); /* imeFileName */ stream_write_uint16(s, RNS_UD_COLOR_8BPP); /* postBeta2ColorDepth */ stream_write_uint16(s, 1); /* clientProductID */ stream_write_uint32(s, 0); /* serialNumber (should be initialized to 0) */ highColorDepth = MIN(settings->color_depth, 24); supportedColorDepths = RNS_UD_24BPP_SUPPORT | RNS_UD_16BPP_SUPPORT | RNS_UD_15BPP_SUPPORT; connectionType = settings->connection_type; earlyCapabilityFlags = RNS_UD_CS_SUPPORT_ERRINFO_PDU; if (settings->rfx_codec) connectionType = CONNECTION_TYPE_LAN; if (connectionType != 0) earlyCapabilityFlags |= RNS_UD_CS_VALID_CONNECTION_TYPE; if (settings->color_depth == 32) { supportedColorDepths |= RNS_UD_32BPP_SUPPORT; earlyCapabilityFlags |= RNS_UD_CS_WANT_32BPP_SESSION; } stream_write_uint16(s, highColorDepth); /* highColorDepth */ stream_write_uint16(s, supportedColorDepths); /* supportedColorDepths */ stream_write_uint16(s, earlyCapabilityFlags); /* earlyCapabilityFlags */ /* clientDigProductId (64 bytes, null-terminated unicode, truncated to 30 characters) */ if (clientDigProductIdLength > 62) { clientDigProductIdLength = 62; clientDigProductId[clientDigProductIdLength] = 0; clientDigProductId[clientDigProductIdLength + 1] = 0; } stream_write(s, clientDigProductId, clientDigProductIdLength + 2); stream_write_zero(s, 64 - clientDigProductIdLength - 2); xfree(clientDigProductId); stream_write_uint8(s, connectionType); /* connectionType */ stream_write_uint8(s, 0); /* pad1octet */ stream_write_uint32(s, settings->selected_protocol); /* serverSelectedProtocol */ } boolean gcc_read_server_core_data(STREAM* s, rdpSettings* settings) { uint32 version; uint32 clientRequestedProtocols; stream_read_uint32(s, version); /* version */ stream_read_uint32(s, clientRequestedProtocols); /* clientRequestedProtocols */ if (version == RDP_VERSION_4 && settings->rdp_version > 4) settings->rdp_version = 4; else if (version == RDP_VERSION_5_PLUS && settings->rdp_version < 5) settings->rdp_version = 7; return true; } void gcc_write_server_core_data(STREAM* s, rdpSettings* settings) { gcc_write_user_data_header(s, SC_CORE, 12); stream_write_uint32(s, settings->rdp_version == 4 ? RDP_VERSION_4 : RDP_VERSION_5_PLUS); stream_write_uint32(s, settings->requested_protocols); /* clientRequestedProtocols */ } /** * Read a client security data block (TS_UD_CS_SEC).\n * @msdn{cc240511} * @param s stream * @param settings rdp settings */ boolean gcc_read_client_security_data(STREAM* s, rdpSettings* settings, uint16 blockLength) { if (blockLength < 8) return false; if (settings->encryption) { stream_read_uint32(s, settings->encryption_method); /* encryptionMethods */ if (settings->encryption_method == 0) stream_read_uint32(s, settings->encryption_method); /* extEncryptionMethods */ } else { stream_seek(s, 8); } return true; } /** * Write a client security data block (TS_UD_CS_SEC).\n * @msdn{cc240511} * @param s stream * @param settings rdp settings */ void gcc_write_client_security_data(STREAM* s, rdpSettings* settings) { gcc_write_user_data_header(s, CS_SECURITY, 12); if (settings->encryption) { stream_write_uint32(s, settings->encryption_method); /* encryptionMethods */ stream_write_uint32(s, 0); /* extEncryptionMethods */ } else { /* French locale, disable encryption */ stream_write_uint32(s, 0); /* encryptionMethods */ stream_write_uint32(s, settings->encryption_method); /* extEncryptionMethods */ } } boolean gcc_read_server_security_data(STREAM* s, rdpSettings* settings) { uint8* data; uint32 length; uint32 serverRandomLen; uint32 serverCertLen; stream_read_uint32(s, settings->encryption_method); /* encryptionMethod */ stream_read_uint32(s, settings->encryption_level); /* encryptionLevel */ if (settings->encryption_method == 0 && settings->encryption_level == 0) { /* serverRandom and serverRandom must not be present */ settings->encryption = false; settings->encryption_method = ENCRYPTION_METHOD_NONE; settings->encryption_level = ENCRYPTION_LEVEL_NONE; return true; } stream_read_uint32(s, serverRandomLen); /* serverRandomLen */ stream_read_uint32(s, serverCertLen); /* serverCertLen */ if (serverRandomLen > 0) { /* serverRandom */ freerdp_blob_alloc(settings->server_random, serverRandomLen); stream_read(s, settings->server_random->data, serverRandomLen); } else { return false; } if (serverCertLen > 0) { /* serverCertificate */ freerdp_blob_alloc(settings->server_certificate, serverCertLen); stream_read(s, settings->server_certificate->data, serverCertLen); certificate_free(settings->server_cert); settings->server_cert = certificate_new(); data = settings->server_certificate->data; length = settings->server_certificate->length; if (!certificate_read_server_certificate(settings->server_cert, data, length)) return false; } else { return false; } return true; } static const uint8 initial_signature[] = { 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x00, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x01 }; void gcc_write_server_security_data(STREAM* s, rdpSettings* settings) { CryptoMd5 md5; uint8* sigData; int expLen, keyLen, sigDataLen; uint8 encryptedSignature[TSSK_KEY_LENGTH]; uint8 signature[sizeof(initial_signature)]; uint32 headerLen, serverRandomLen, serverCertLen, wPublicKeyBlobLen; if (!settings->encryption) { settings->encryption_method = ENCRYPTION_METHOD_NONE; settings->encryption_level = ENCRYPTION_LEVEL_NONE; } else if ((settings->encryption_method & ENCRYPTION_METHOD_FIPS) != 0) { settings->encryption_method = ENCRYPTION_METHOD_FIPS; } else if ((settings->encryption_method & ENCRYPTION_METHOD_128BIT) != 0) { settings->encryption_method = ENCRYPTION_METHOD_128BIT; } else if ((settings->encryption_method & ENCRYPTION_METHOD_40BIT) != 0) { settings->encryption_method = ENCRYPTION_METHOD_40BIT; } if (settings->encryption_method != ENCRYPTION_METHOD_NONE) settings->encryption_level = ENCRYPTION_LEVEL_CLIENT_COMPATIBLE; headerLen = 12; keyLen = 0; wPublicKeyBlobLen = 0; serverRandomLen = 0; serverCertLen = 0; if (settings->encryption_method != ENCRYPTION_METHOD_NONE || settings->encryption_level != ENCRYPTION_LEVEL_NONE) { serverRandomLen = 32; keyLen = settings->server_key->modulus.length; expLen = sizeof(settings->server_key->exponent); wPublicKeyBlobLen = 4; /* magic (RSA1) */ wPublicKeyBlobLen += 4; /* keylen */ wPublicKeyBlobLen += 4; /* bitlen */ wPublicKeyBlobLen += 4; /* datalen */ wPublicKeyBlobLen += expLen; wPublicKeyBlobLen += keyLen; wPublicKeyBlobLen += 8; /* 8 bytes of zero padding */ serverCertLen = 4; /* dwVersion */ serverCertLen += 4; /* dwSigAlgId */ serverCertLen += 4; /* dwKeyAlgId */ serverCertLen += 2; /* wPublicKeyBlobType */ serverCertLen += 2; /* wPublicKeyBlobLen */ serverCertLen += wPublicKeyBlobLen; serverCertLen += 2; /* wSignatureBlobType */ serverCertLen += 2; /* wSignatureBlobLen */ serverCertLen += sizeof(encryptedSignature); /* SignatureBlob */ serverCertLen += 8; /* 8 bytes of zero padding */ headerLen += sizeof(serverRandomLen); headerLen += sizeof(serverCertLen); headerLen += serverRandomLen; headerLen += serverCertLen; } gcc_write_user_data_header(s, SC_SECURITY, headerLen); stream_write_uint32(s, settings->encryption_method); /* encryptionMethod */ stream_write_uint32(s, settings->encryption_level); /* encryptionLevel */ if (settings->encryption_method == ENCRYPTION_METHOD_NONE && settings->encryption_level == ENCRYPTION_LEVEL_NONE) { return; } stream_write_uint32(s, serverRandomLen); /* serverRandomLen */ stream_write_uint32(s, serverCertLen); /* serverCertLen */ freerdp_blob_alloc(settings->server_random, serverRandomLen); crypto_nonce(settings->server_random->data, serverRandomLen); stream_write(s, settings->server_random->data, serverRandomLen); sigData = stream_get_tail(s); stream_write_uint32(s, CERT_CHAIN_VERSION_1); /* dwVersion (4 bytes) */ stream_write_uint32(s, SIGNATURE_ALG_RSA); /* dwSigAlgId */ stream_write_uint32(s, KEY_EXCHANGE_ALG_RSA); /* dwKeyAlgId */ stream_write_uint16(s, BB_RSA_KEY_BLOB); /* wPublicKeyBlobType */ stream_write_uint16(s, wPublicKeyBlobLen); /* wPublicKeyBlobLen */ stream_write(s, "RSA1", 4); /* magic */ stream_write_uint32(s, keyLen + 8); /* keylen */ stream_write_uint32(s, keyLen * 8); /* bitlen */ stream_write_uint32(s, keyLen - 1); /* datalen */ stream_write(s, settings->server_key->exponent, expLen); stream_write(s, settings->server_key->modulus.data, keyLen); stream_write_zero(s, 8); sigDataLen = stream_get_tail(s) - sigData; stream_write_uint16(s, BB_RSA_SIGNATURE_BLOB); /* wSignatureBlobType */ stream_write_uint16(s, keyLen + 8); /* wSignatureBlobLen */ memcpy(signature, initial_signature, sizeof(initial_signature)); md5 = crypto_md5_init(); crypto_md5_update(md5, sigData, sigDataLen); crypto_md5_final(md5, signature); crypto_rsa_private_encrypt(signature, sizeof(signature), TSSK_KEY_LENGTH, tssk_modulus, tssk_privateExponent, encryptedSignature); stream_write(s, encryptedSignature, sizeof(encryptedSignature)); stream_write_zero(s, 8); } /** * Read a client network data block (TS_UD_CS_NET).\n * @msdn{cc240512} * @param s stream * @param settings rdp settings */ boolean gcc_read_client_network_data(STREAM* s, rdpSettings* settings, uint16 blockLength) { int i; if (blockLength < 4) return false; stream_read_uint32(s, settings->num_channels); /* channelCount */ if (blockLength < 4 + settings->num_channels * 12) return false; if (settings->num_channels > 16) return false; /* channelDefArray */ for (i = 0; i < settings->num_channels; i++) { /* CHANNEL_DEF */ stream_read(s, settings->channels[i].name, 8); /* name (8 bytes) */ stream_read_uint32(s, settings->channels[i].options); /* options (4 bytes) */ settings->channels[i].channel_id = MCS_GLOBAL_CHANNEL_ID + 1 + i; } return true; } /** * Write a client network data block (TS_UD_CS_NET).\n * @msdn{cc240512} * @param s stream * @param settings rdp settings */ void gcc_write_client_network_data(STREAM* s, rdpSettings* settings) { int i; uint16 length; if (settings->num_channels > 0) { length = settings->num_channels * 12 + 8; gcc_write_user_data_header(s, CS_NET, length); stream_write_uint32(s, settings->num_channels); /* channelCount */ /* channelDefArray */ for (i = 0; i < settings->num_channels; i++) { /* CHANNEL_DEF */ stream_write(s, settings->channels[i].name, 8); /* name (8 bytes) */ stream_write_uint32(s, settings->channels[i].options); /* options (4 bytes) */ } } } boolean gcc_read_server_network_data(STREAM* s, rdpSettings* settings) { int i; uint16 MCSChannelId; uint16 channelCount; uint16 channelId; stream_read_uint16(s, MCSChannelId); /* MCSChannelId */ stream_read_uint16(s, channelCount); /* channelCount */ if (channelCount != settings->num_channels) { printf("requested %d channels, got %d instead\n", settings->num_channels, channelCount); } for (i = 0; i < channelCount; i++) { stream_read_uint16(s, channelId); /* channelId */ settings->channels[i].channel_id = channelId; } if (channelCount % 2 == 1) stream_seek(s, 2); /* padding */ return true; } void gcc_write_server_network_data(STREAM* s, rdpSettings* settings) { int i; gcc_write_user_data_header(s, SC_NET, 8 + settings->num_channels * 2 + (settings->num_channels % 2 == 1 ? 2 : 0)); stream_write_uint16(s, MCS_GLOBAL_CHANNEL_ID); /* MCSChannelId */ stream_write_uint16(s, settings->num_channels); /* channelCount */ for (i = 0; i < settings->num_channels; i++) { stream_write_uint16(s, settings->channels[i].channel_id); } if (settings->num_channels % 2 == 1) stream_write_uint16(s, 0); } /** * Read a client cluster data block (TS_UD_CS_CLUSTER).\n * @msdn{cc240514} * @param s stream * @param settings rdp settings */ boolean gcc_read_client_cluster_data(STREAM* s, rdpSettings* settings, uint16 blockLength) { uint32 flags; if (blockLength < 8) return false; stream_read_uint32(s, flags); /* flags */ if ((flags | REDIRECTED_SESSIONID_FIELD_VALID)) stream_read_uint32(s, settings->redirected_session_id); /* redirectedSessionID */ return true; } /** * Write a client cluster data block (TS_UD_CS_CLUSTER).\n * @msdn{cc240514} * @param s stream * @param settings rdp settings */ void gcc_write_client_cluster_data(STREAM* s, rdpSettings* settings) { uint32 flags; gcc_write_user_data_header(s, CS_CLUSTER, 12); flags = REDIRECTION_SUPPORTED | (REDIRECTION_VERSION4 << 2); if (settings->console_session || settings->redirected_session_id) flags |= REDIRECTED_SESSIONID_FIELD_VALID; stream_write_uint32(s, flags); /* flags */ stream_write_uint32(s, settings->redirected_session_id); /* redirectedSessionID */ } /** * Read a client monitor data block (TS_UD_CS_MONITOR).\n * @msdn{dd305336} * @param s stream * @param settings rdp settings */ boolean gcc_read_client_monitor_data(STREAM* s, rdpSettings* settings, uint16 blockLength) { printf("CS_MONITOR\n"); return true; } /** * Write a client monitor data block (TS_UD_CS_MONITOR).\n * @msdn{dd305336} * @param s stream * @param settings rdp settings */ void gcc_write_client_monitor_data(STREAM* s, rdpSettings* settings) { int i; uint16 length; uint32 left, top, right, bottom, flags; if (settings->num_monitors > 1) { length = (20 * settings->num_monitors) + 12; gcc_write_user_data_header(s, CS_MONITOR, length); stream_write_uint32(s, 0); /* flags */ stream_write_uint32(s, settings->num_monitors); /* monitorCount */ for (i = 0; i < settings->num_monitors; i++) { left = settings->monitors[i].x; top = settings->monitors[i].y; right = settings->monitors[i].x + settings->monitors[i].width - 1; bottom = settings->monitors[i].y + settings->monitors[i].height - 1; flags = settings->monitors[i].is_primary ? MONITOR_PRIMARY : 0; stream_write_uint32(s, left); /* left */ stream_write_uint32(s, top); /* top */ stream_write_uint32(s, right); /* right */ stream_write_uint32(s, bottom); /* bottom */ stream_write_uint32(s, flags); /* flags */ } } } FreeRDP-1.0.2/libfreerdp-core/gcc.h000066400000000000000000000105021207112532300167040ustar00rootroot00000000000000/** * FreeRDP: A Remote Desktop Protocol Client * T.124 Generic Conference Control (GCC) * * Copyright 2011 Marc-Andre Moreau * * 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. */ #ifndef __GCC_H #define __GCC_H #include "per.h" #include "mcs.h" #include #include #include /* Client to Server (CS) data blocks */ #define CS_CORE 0xC001 #define CS_SECURITY 0xC002 #define CS_NET 0xC003 #define CS_CLUSTER 0xC004 #define CS_MONITOR 0xC005 /* Server to Client (SC) data blocks */ #define SC_CORE 0x0C01 #define SC_SECURITY 0x0C02 #define SC_NET 0x0C03 /* RDP version */ #define RDP_VERSION_4 0x00080001 #define RDP_VERSION_5_PLUS 0x00080004 /* Color depth */ #define RNS_UD_COLOR_4BPP 0xCA00 #define RNS_UD_COLOR_8BPP 0xCA01 #define RNS_UD_COLOR_16BPP_555 0xCA02 #define RNS_UD_COLOR_16BPP_565 0xCA03 #define RNS_UD_COLOR_24BPP 0xCA04 /* Secure Access Sequence */ #define RNS_UD_SAS_DEL 0xAA03 /* Supported Color Depths */ #define RNS_UD_24BPP_SUPPORT 0x0001 #define RNS_UD_16BPP_SUPPORT 0x0002 #define RNS_UD_15BPP_SUPPORT 0x0004 #define RNS_UD_32BPP_SUPPORT 0x0008 /* Early Capability Flags */ #define RNS_UD_CS_SUPPORT_ERRINFO_PDU 0x0001 #define RNS_UD_CS_WANT_32BPP_SESSION 0x0002 #define RNS_UD_CS_SUPPORT_STATUSINFO_PDU 0x0004 #define RNS_UD_CS_STRONG_ASYMMETRIC_KEYS 0x0008 #define RNS_UD_CS_VALID_CONNECTION_TYPE 0x0020 #define RNS_UD_CS_SUPPORT_MONITOR_LAYOUT_PDU 0x0040 /* Cluster Information Flags */ #define REDIRECTION_SUPPORTED 0x00000001 #define REDIRECTED_SESSIONID_FIELD_VALID 0x00000002 #define REDIRECTED_SMARTCARD 0x00000040 #define REDIRECTION_VERSION1 0x00 #define REDIRECTION_VERSION2 0x01 #define REDIRECTION_VERSION3 0x02 #define REDIRECTION_VERSION4 0x03 #define REDIRECTION_VERSION5 0x04 /* Monitor Flags */ #define MONITOR_PRIMARY 0x00000001 boolean gcc_read_conference_create_request(STREAM* s, rdpSettings* settings); void gcc_write_conference_create_request(STREAM* s, STREAM* user_data); boolean gcc_read_conference_create_response(STREAM* s, rdpSettings* settings); void gcc_write_conference_create_response(STREAM* s, STREAM* user_data); boolean gcc_read_client_data_blocks(STREAM* s, rdpSettings *settings, int length); void gcc_write_client_data_blocks(STREAM* s, rdpSettings *settings); boolean gcc_read_server_data_blocks(STREAM* s, rdpSettings *settings, int length); void gcc_write_server_data_blocks(STREAM* s, rdpSettings *settings); boolean gcc_read_user_data_header(STREAM* s, uint16* type, uint16* length); void gcc_write_user_data_header(STREAM* s, uint16 type, uint16 length); boolean gcc_read_client_core_data(STREAM* s, rdpSettings *settings, uint16 blockLength); void gcc_write_client_core_data(STREAM* s, rdpSettings *settings); boolean gcc_read_server_core_data(STREAM* s, rdpSettings *settings); void gcc_write_server_core_data(STREAM* s, rdpSettings *settings); boolean gcc_read_client_security_data(STREAM* s, rdpSettings *settings, uint16 blockLength); void gcc_write_client_security_data(STREAM* s, rdpSettings *settings); boolean gcc_read_server_security_data(STREAM* s, rdpSettings *settings); void gcc_write_server_security_data(STREAM* s, rdpSettings *settings); boolean gcc_read_client_network_data(STREAM* s, rdpSettings *settings, uint16 blockLength); void gcc_write_client_network_data(STREAM* s, rdpSettings *settings); boolean gcc_read_server_network_data(STREAM* s, rdpSettings *settings); void gcc_write_server_network_data(STREAM* s, rdpSettings *settings); boolean gcc_read_client_cluster_data(STREAM* s, rdpSettings *settings, uint16 blockLength); void gcc_write_client_cluster_data(STREAM* s, rdpSettings *settings); boolean gcc_read_client_monitor_data(STREAM* s, rdpSettings *settings, uint16 blockLength); void gcc_write_client_monitor_data(STREAM* s, rdpSettings *settings); #endif /* __GCC_H */ FreeRDP-1.0.2/libfreerdp-core/graphics.c000066400000000000000000000124331207112532300177500ustar00rootroot00000000000000/** * FreeRDP: A Remote Desktop Protocol Client * Graphical Objects * * Copyright 2011 Marc-Andre Moreau * * 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. */ #include #include /* Bitmap Class */ rdpBitmap* Bitmap_Alloc(rdpContext* context) { rdpBitmap* bitmap; rdpGraphics* graphics; graphics = context->graphics; bitmap = (rdpBitmap*) xmalloc(graphics->Bitmap_Prototype->size); if (bitmap != NULL) { memcpy(bitmap, context->graphics->Bitmap_Prototype, sizeof(rdpBitmap)); bitmap->data = NULL; } return bitmap; } void Bitmap_New(rdpContext* context, rdpBitmap* bitmap) { } void Bitmap_Free(rdpContext* context, rdpBitmap* bitmap) { if (bitmap != NULL) { bitmap->Free(context, bitmap); if (bitmap->data != NULL) xfree(bitmap->data); xfree(bitmap); } } void Bitmap_SetRectangle(rdpContext* context, rdpBitmap* bitmap, uint16 left, uint16 top, uint16 right, uint16 bottom) { bitmap->left = left; bitmap->top = top; bitmap->right = right; bitmap->bottom = bottom; } void Bitmap_SetDimensions(rdpContext* context, rdpBitmap* bitmap, uint16 width, uint16 height) { bitmap->width = width; bitmap->height = height; } /* static method */ void Bitmap_SetSurface(rdpContext* context, rdpBitmap* bitmap, boolean primary) { context->graphics->Bitmap_Prototype->SetSurface(context, bitmap, primary); } void graphics_register_bitmap(rdpGraphics* graphics, rdpBitmap* bitmap) { memcpy(graphics->Bitmap_Prototype, bitmap, sizeof(rdpBitmap)); } /* Pointer Class */ rdpPointer* Pointer_Alloc(rdpContext* context) { rdpPointer* pointer; rdpGraphics* graphics; graphics = context->graphics; pointer = (rdpPointer*) xmalloc(graphics->Pointer_Prototype->size); if (pointer != NULL) { memcpy(pointer, context->graphics->Pointer_Prototype, sizeof(rdpPointer)); } return pointer; } void Pointer_New(rdpContext* context, rdpPointer* pointer) { } void Pointer_Free(rdpContext* context, rdpPointer* pointer) { if (pointer != NULL) { pointer->Free(context, pointer); if (pointer->xorMaskData) xfree(pointer->xorMaskData); if (pointer->andMaskData) xfree(pointer->andMaskData); xfree(pointer); } } /* static method */ void Pointer_Set(rdpContext* context, rdpPointer* pointer) { context->graphics->Pointer_Prototype->Set(context, pointer); } void graphics_register_pointer(rdpGraphics* graphics, rdpPointer* pointer) { memcpy(graphics->Pointer_Prototype, pointer, sizeof(rdpPointer)); } /* Glyph Class */ rdpGlyph* Glyph_Alloc(rdpContext* context) { rdpGlyph* glyph; rdpGraphics* graphics; graphics = context->graphics; glyph = (rdpGlyph*) xmalloc(graphics->Glyph_Prototype->size); if (glyph != NULL) { memcpy(glyph, context->graphics->Glyph_Prototype, sizeof(rdpGlyph)); } return glyph; } void Glyph_New(rdpContext* context, rdpGlyph* glyph) { context->graphics->Glyph_Prototype->New(context, glyph); } void Glyph_Free(rdpContext* context, rdpGlyph* glyph) { context->graphics->Glyph_Prototype->Free(context, glyph); } void Glyph_Draw(rdpContext* context, rdpGlyph* glyph, int x, int y) { context->graphics->Glyph_Prototype->Draw(context, glyph, x, y); } void Glyph_BeginDraw(rdpContext* context, int x, int y, int width, int height, uint32 bgcolor, uint32 fgcolor) { context->graphics->Glyph_Prototype->BeginDraw(context, x, y, width, height, bgcolor, fgcolor); } void Glyph_EndDraw(rdpContext* context, int x, int y, int width, int height, uint32 bgcolor, uint32 fgcolor) { context->graphics->Glyph_Prototype->EndDraw(context, x, y, width, height, bgcolor, fgcolor); } void graphics_register_glyph(rdpGraphics* graphics, rdpGlyph* glyph) { memcpy(graphics->Glyph_Prototype, glyph, sizeof(rdpGlyph)); } /* Graphics Module */ rdpGraphics* graphics_new(rdpContext* context) { rdpGraphics* graphics; graphics = (rdpGraphics*) xzalloc(sizeof(rdpGraphics)); if (graphics != NULL) { graphics->context = context; graphics->Bitmap_Prototype = (rdpBitmap*) xzalloc(sizeof(rdpBitmap)); graphics->Bitmap_Prototype->size = sizeof(rdpBitmap); graphics->Bitmap_Prototype->New = Bitmap_New; graphics->Bitmap_Prototype->Free = Bitmap_Free; graphics->Pointer_Prototype = (rdpPointer*) xzalloc(sizeof(rdpPointer)); graphics->Pointer_Prototype->size = sizeof(rdpPointer); graphics->Pointer_Prototype->New = Pointer_New; graphics->Pointer_Prototype->Free = Pointer_Free; graphics->Glyph_Prototype = (rdpGlyph*) xzalloc(sizeof(rdpGlyph)); graphics->Glyph_Prototype->size = sizeof(rdpGlyph); graphics->Glyph_Prototype->New = Glyph_New; graphics->Glyph_Prototype->Free = Glyph_Free; } return graphics; } void graphics_free(rdpGraphics* graphics) { if (graphics != NULL) { xfree(graphics->Bitmap_Prototype); xfree(graphics->Pointer_Prototype); xfree(graphics->Glyph_Prototype); xfree(graphics); } } FreeRDP-1.0.2/libfreerdp-core/info.c000066400000000000000000000475161207112532300171150ustar00rootroot00000000000000/** * FreeRDP: A Remote Desktop Protocol Client * RDP Client Info * * Copyright 2011 Marc-Andre Moreau * * 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. */ #include "info.h" #define INFO_TYPE_LOGON 0x00000000 #define INFO_TYPE_LOGON_LONG 0x00000001 #define INFO_TYPE_LOGON_PLAIN_NOTIFY 0x00000002 #define INFO_TYPE_LOGON_EXTENDED_INF 0x00000003 /* static const char* const INFO_TYPE_LOGON_STRINGS[] = { "Logon Info V1", "Logon Info V2", "Logon Plain Notify", "Logon Extended Info" }; */ /** * Read SYSTEM_TIME structure (TS_SYSTEMTIME).\n * @msdn{cc240478} * @param s stream * @param system_time system time structure */ void rdp_read_system_time(STREAM* s, SYSTEM_TIME* system_time) { stream_read_uint16(s, system_time->wYear); /* wYear, must be set to 0 */ stream_read_uint16(s, system_time->wMonth); /* wMonth */ stream_read_uint16(s, system_time->wDayOfWeek); /* wDayOfWeek */ stream_read_uint16(s, system_time->wDay); /* wDay */ stream_read_uint16(s, system_time->wHour); /* wHour */ stream_read_uint16(s, system_time->wMinute); /* wMinute */ stream_read_uint16(s, system_time->wSecond); /* wSecond */ stream_read_uint16(s, system_time->wMilliseconds); /* wMilliseconds */ } /** * Write SYSTEM_TIME structure (TS_SYSTEMTIME).\n * @msdn{cc240478} * @param s stream * @param system_time system time structure */ void rdp_write_system_time(STREAM* s, SYSTEM_TIME* system_time) { stream_write_uint16(s, system_time->wYear); /* wYear, must be set to 0 */ stream_write_uint16(s, system_time->wMonth); /* wMonth */ stream_write_uint16(s, system_time->wDayOfWeek); /* wDayOfWeek */ stream_write_uint16(s, system_time->wDay); /* wDay */ stream_write_uint16(s, system_time->wHour); /* wHour */ stream_write_uint16(s, system_time->wMinute); /* wMinute */ stream_write_uint16(s, system_time->wSecond); /* wSecond */ stream_write_uint16(s, system_time->wMilliseconds); /* wMilliseconds */ } /** * Get client time zone information.\n * @param s stream * @param settings settings */ void rdp_get_client_time_zone(STREAM* s, rdpSettings* settings) { time_t t; struct tm* local_time; TIME_ZONE_INFO* clientTimeZone; time(&t); local_time = localtime(&t); clientTimeZone = settings->client_time_zone; #if defined(sun) if(local_time->tm_isdst > 0) clientTimeZone->bias = (uint32) (altzone / 3600); else clientTimeZone->bias = (uint32) (timezone / 3600); #elif defined(HAVE_TM_GMTOFF) if(local_time->tm_gmtoff >= 0) clientTimeZone->bias = (uint32) (local_time->tm_gmtoff / 60); else clientTimeZone->bias = (uint32) ((-1 * local_time->tm_gmtoff) / 60 + 720); #else clientTimeZone->bias = 0; #endif if(local_time->tm_isdst > 0) { clientTimeZone->standardBias = clientTimeZone->bias - 60; clientTimeZone->daylightBias = clientTimeZone->bias; } else { clientTimeZone->standardBias = clientTimeZone->bias; clientTimeZone->daylightBias = clientTimeZone->bias + 60; } strftime(clientTimeZone->standardName, 32, "%Z, Standard Time", local_time); clientTimeZone->standardName[31] = 0; strftime(clientTimeZone->daylightName, 32, "%Z, Summer Time", local_time); clientTimeZone->daylightName[31] = 0; } /** * Read client time zone information (TS_TIME_ZONE_INFORMATION).\n * @msdn{cc240477} * @param s stream * @param settings settings */ boolean rdp_read_client_time_zone(STREAM* s, rdpSettings* settings) { char* str; TIME_ZONE_INFO* clientTimeZone; if (stream_get_left(s) < 172) return false; clientTimeZone = settings->client_time_zone; stream_read_uint32(s, clientTimeZone->bias); /* Bias */ /* standardName (64 bytes) */ str = freerdp_uniconv_in(settings->uniconv, stream_get_tail(s), 64); stream_seek(s, 64); strncpy(clientTimeZone->standardName, str, sizeof(clientTimeZone->standardName)); xfree(str); rdp_read_system_time(s, &clientTimeZone->standardDate); /* StandardDate */ stream_read_uint32(s, clientTimeZone->standardBias); /* StandardBias */ /* daylightName (64 bytes) */ str = freerdp_uniconv_in(settings->uniconv, stream_get_tail(s), 64); stream_seek(s, 64); strncpy(clientTimeZone->daylightName, str, sizeof(clientTimeZone->daylightName)); xfree(str); rdp_read_system_time(s, &clientTimeZone->daylightDate); /* DaylightDate */ stream_read_uint32(s, clientTimeZone->daylightBias); /* DaylightBias */ return true; } /** * Write client time zone information (TS_TIME_ZONE_INFORMATION).\n * @msdn{cc240477} * @param s stream * @param settings settings */ void rdp_write_client_time_zone(STREAM* s, rdpSettings* settings) { size_t length; uint8* standardName; uint8* daylightName; size_t standardNameLength; size_t daylightNameLength; TIME_ZONE_INFO* clientTimeZone; rdp_get_client_time_zone(s, settings); clientTimeZone = settings->client_time_zone; standardName = (uint8*) freerdp_uniconv_out(settings->uniconv, clientTimeZone->standardName, &length); standardNameLength = length; daylightName = (uint8*) freerdp_uniconv_out(settings->uniconv, clientTimeZone->daylightName, &length); daylightNameLength = length; if (standardNameLength > 62) standardNameLength = 62; if (daylightNameLength > 62) daylightNameLength = 62; stream_write_uint32(s, clientTimeZone->bias); /* Bias */ /* standardName (64 bytes) */ stream_write(s, standardName, standardNameLength); stream_write_zero(s, 64 - standardNameLength); rdp_write_system_time(s, &clientTimeZone->standardDate); /* StandardDate */ stream_write_uint32(s, clientTimeZone->standardBias); /* StandardBias */ /* daylightName (64 bytes) */ stream_write(s, daylightName, daylightNameLength); stream_write_zero(s, 64 - daylightNameLength); rdp_write_system_time(s, &clientTimeZone->daylightDate); /* DaylightDate */ stream_write_uint32(s, clientTimeZone->daylightBias); /* DaylightBias */ xfree(standardName); xfree(daylightName); } /** * Read Server Auto Reconnect Cookie (ARC_SC_PRIVATE_PACKET).\n * @msdn{cc240540} * @param s stream * @param settings settings */ void rdp_read_server_auto_reconnect_cookie(STREAM* s, rdpSettings* settings) { ARC_SC_PRIVATE_PACKET* autoReconnectCookie; autoReconnectCookie = settings->server_auto_reconnect_cookie; stream_read_uint32(s, autoReconnectCookie->cbLen); /* cbLen (4 bytes) */ stream_read_uint32(s, autoReconnectCookie->version); /* version (4 bytes) */ stream_read_uint32(s, autoReconnectCookie->logonId); /* LogonId (4 bytes) */ stream_read(s, autoReconnectCookie->arcRandomBits, 16); /* arcRandomBits (16 bytes) */ } /** * Read Client Auto Reconnect Cookie (ARC_CS_PRIVATE_PACKET).\n * @msdn{cc240541} * @param s stream * @param settings settings */ boolean rdp_read_client_auto_reconnect_cookie(STREAM* s, rdpSettings* settings) { ARC_CS_PRIVATE_PACKET* autoReconnectCookie; autoReconnectCookie = settings->client_auto_reconnect_cookie; if (stream_get_left(s) < 28) return false; stream_read_uint32(s, autoReconnectCookie->cbLen); /* cbLen (4 bytes) */ stream_read_uint32(s, autoReconnectCookie->version); /* version (4 bytes) */ stream_read_uint32(s, autoReconnectCookie->logonId); /* LogonId (4 bytes) */ stream_read(s, autoReconnectCookie->securityVerifier, 16); /* SecurityVerifier */ return true; } /** * Write Client Auto Reconnect Cookie (ARC_CS_PRIVATE_PACKET).\n * @msdn{cc240541} * @param s stream * @param settings settings */ void rdp_write_client_auto_reconnect_cookie(STREAM* s, rdpSettings* settings) { ARC_CS_PRIVATE_PACKET* autoReconnectCookie; autoReconnectCookie = settings->client_auto_reconnect_cookie; stream_write_uint32(s, autoReconnectCookie->cbLen); /* cbLen (4 bytes) */ stream_write_uint32(s, autoReconnectCookie->version); /* version (4 bytes) */ stream_write_uint32(s, autoReconnectCookie->logonId); /* LogonId (4 bytes) */ stream_write(s, autoReconnectCookie->securityVerifier, 16); /* SecurityVerifier */ } /** * Read Extended Info Packet (TS_EXTENDED_INFO_PACKET).\n * @msdn{cc240476} * @param s stream * @param settings settings */ boolean rdp_read_extended_info_packet(STREAM* s, rdpSettings* settings) { uint16 clientAddressFamily; uint16 cbClientAddress; uint16 cbClientDir; uint16 cbAutoReconnectLen; stream_read_uint16(s, clientAddressFamily); /* clientAddressFamily */ stream_read_uint16(s, cbClientAddress); /* cbClientAddress */ settings->ipv6 = (clientAddressFamily == ADDRESS_FAMILY_INET6 ? true : false); if (stream_get_left(s) < cbClientAddress) return false; settings->ip_address = freerdp_uniconv_in(settings->uniconv, stream_get_tail(s), cbClientAddress); stream_seek(s, cbClientAddress); stream_read_uint16(s, cbClientDir); /* cbClientDir */ if (stream_get_left(s) < cbClientDir) return false; if (settings->client_dir) xfree(settings->client_dir); settings->client_dir = freerdp_uniconv_in(settings->uniconv, stream_get_tail(s), cbClientDir); stream_seek(s, cbClientDir); if (!rdp_read_client_time_zone(s, settings)) return false; stream_seek_uint32(s); /* clientSessionId, should be set to 0 */ stream_read_uint32(s, settings->performance_flags); /* performanceFlags */ stream_read_uint16(s, cbAutoReconnectLen); /* cbAutoReconnectLen */ if (cbAutoReconnectLen > 0) return rdp_read_client_auto_reconnect_cookie(s, settings); /* autoReconnectCookie */ /* reserved1 (2 bytes) */ /* reserved2 (2 bytes) */ return true; } /** * Write Extended Info Packet (TS_EXTENDED_INFO_PACKET).\n * @msdn{cc240476} * @param s stream * @param settings settings */ void rdp_write_extended_info_packet(STREAM* s, rdpSettings* settings) { size_t length; uint16 clientAddressFamily; uint8* clientAddress; uint16 cbClientAddress; uint8* clientDir; uint16 cbClientDir; uint16 cbAutoReconnectLen; clientAddressFamily = settings->ipv6 ? ADDRESS_FAMILY_INET6 : ADDRESS_FAMILY_INET; clientAddress = (uint8*) freerdp_uniconv_out(settings->uniconv, settings->ip_address, &length); cbClientAddress = length; clientDir = (uint8*) freerdp_uniconv_out(settings->uniconv, settings->client_dir, &length); cbClientDir = length; cbAutoReconnectLen = settings->client_auto_reconnect_cookie->cbLen; stream_write_uint16(s, clientAddressFamily); /* clientAddressFamily */ stream_write_uint16(s, cbClientAddress + 2); /* cbClientAddress */ if (cbClientAddress > 0) stream_write(s, clientAddress, cbClientAddress); /* clientAddress */ stream_write_uint16(s, 0); stream_write_uint16(s, cbClientDir + 2); /* cbClientDir */ if (cbClientDir > 0) stream_write(s, clientDir, cbClientDir); /* clientDir */ stream_write_uint16(s, 0); rdp_write_client_time_zone(s, settings); /* clientTimeZone */ stream_write_uint32(s, 0); /* clientSessionId, should be set to 0 */ stream_write_uint32(s, settings->performance_flags); /* performanceFlags */ stream_write_uint16(s, cbAutoReconnectLen); /* cbAutoReconnectLen */ if (cbAutoReconnectLen > 0) rdp_write_client_auto_reconnect_cookie(s, settings); /* autoReconnectCookie */ /* reserved1 (2 bytes) */ /* reserved2 (2 bytes) */ xfree(clientAddress); xfree(clientDir); } /** * Read Info Packet (TS_INFO_PACKET).\n * @msdn{cc240475} * @param s stream * @param settings settings */ boolean rdp_read_info_packet(STREAM* s, rdpSettings* settings) { uint32 flags; uint16 cbDomain; uint16 cbUserName; uint16 cbPassword; uint16 cbAlternateShell; uint16 cbWorkingDir; stream_seek_uint32(s); /* CodePage */ stream_read_uint32(s, flags); /* flags */ settings->autologon = ((flags & INFO_AUTOLOGON) ? true : false); settings->remote_app = ((flags & INFO_RAIL) ? true : false); settings->console_audio = ((flags & INFO_REMOTECONSOLEAUDIO) ? true : false); settings->compression = ((flags & INFO_COMPRESSION) ? true : false); stream_read_uint16(s, cbDomain); /* cbDomain */ stream_read_uint16(s, cbUserName); /* cbUserName */ stream_read_uint16(s, cbPassword); /* cbPassword */ stream_read_uint16(s, cbAlternateShell); /* cbAlternateShell */ stream_read_uint16(s, cbWorkingDir); /* cbWorkingDir */ if (stream_get_left(s) < cbDomain + 2) return false; if (cbDomain > 0) { settings->domain = freerdp_uniconv_in(settings->uniconv, stream_get_tail(s), cbDomain); stream_seek(s, cbDomain); } stream_seek(s, 2); if (stream_get_left(s) < cbUserName + 2) return false; if (cbUserName > 0) { settings->username = freerdp_uniconv_in(settings->uniconv, stream_get_tail(s), cbUserName); stream_seek(s, cbUserName); } stream_seek(s, 2); if (stream_get_left(s) < cbPassword + 2) return false; if (cbPassword > 0) { settings->password = freerdp_uniconv_in(settings->uniconv, stream_get_tail(s), cbPassword); stream_seek(s, cbPassword); } stream_seek(s, 2); if (stream_get_left(s) < cbAlternateShell + 2) return false; if (cbAlternateShell > 0) { settings->shell = freerdp_uniconv_in(settings->uniconv, stream_get_tail(s), cbAlternateShell); stream_seek(s, cbAlternateShell); } stream_seek(s, 2); if (stream_get_left(s) < cbWorkingDir + 2) return false; if (cbWorkingDir > 0) { settings->directory = freerdp_uniconv_in(settings->uniconv, stream_get_tail(s), cbWorkingDir); stream_seek(s, cbWorkingDir); } stream_seek(s, 2); if (settings->rdp_version >= 5) return rdp_read_extended_info_packet(s, settings); /* extraInfo */ return true; } /** * Write Info Packet (TS_INFO_PACKET).\n * @msdn{cc240475} * @param s stream * @param settings settings */ void rdp_write_info_packet(STREAM* s, rdpSettings* settings) { size_t length; uint32 flags; uint8* domain; uint16 cbDomain; uint8* userName; uint16 cbUserName; uint8* password; uint16 cbPassword; uint8* alternateShell; uint16 cbAlternateShell; uint8* workingDir; uint16 cbWorkingDir; boolean usedPasswordCookie = false; flags = INFO_MOUSE | INFO_UNICODE | INFO_LOGONERRORS | INFO_LOGONNOTIFY | INFO_MAXIMIZESHELL | INFO_ENABLEWINDOWSKEY | INFO_DISABLECTRLALTDEL; if (settings->audio_capture) flags |= RNS_INFO_AUDIOCAPTURE; if (!settings->audio_playback) flags |= INFO_NOAUDIOPLAYBACK; if (settings->autologon) flags |= INFO_AUTOLOGON; if (settings->remote_app) flags |= INFO_RAIL; if (settings->console_audio) flags |= INFO_REMOTECONSOLEAUDIO; if (settings->compression) flags |= INFO_COMPRESSION | INFO_PACKET_COMPR_TYPE_64K; domain = (uint8*)freerdp_uniconv_out(settings->uniconv, settings->domain, &length); cbDomain = length; userName = (uint8*)freerdp_uniconv_out(settings->uniconv, settings->username, &length); cbUserName = length; if (settings->password_cookie && settings->password_cookie->length > 0) { usedPasswordCookie = true; password = (uint8*)settings->password_cookie->data; cbPassword = settings->password_cookie->length - 2; /* Strip double zero termination */ } else { password = (uint8*)freerdp_uniconv_out(settings->uniconv, settings->password, &length); cbPassword = length; } alternateShell = (uint8*)freerdp_uniconv_out(settings->uniconv, settings->shell, &length); cbAlternateShell = length; workingDir = (uint8*)freerdp_uniconv_out(settings->uniconv, settings->directory, &length); cbWorkingDir = length; stream_write_uint32(s, 0); /* CodePage */ stream_write_uint32(s, flags); /* flags */ stream_write_uint16(s, cbDomain); /* cbDomain */ stream_write_uint16(s, cbUserName); /* cbUserName */ stream_write_uint16(s, cbPassword); /* cbPassword */ stream_write_uint16(s, cbAlternateShell); /* cbAlternateShell */ stream_write_uint16(s, cbWorkingDir); /* cbWorkingDir */ if (cbDomain > 0) stream_write(s, domain, cbDomain); stream_write_uint16(s, 0); if (cbUserName > 0) stream_write(s, userName, cbUserName); stream_write_uint16(s, 0); if (cbPassword > 0) stream_write(s, password, cbPassword); stream_write_uint16(s, 0); if (cbAlternateShell > 0) stream_write(s, alternateShell, cbAlternateShell); stream_write_uint16(s, 0); if (cbWorkingDir > 0) stream_write(s, workingDir, cbWorkingDir); stream_write_uint16(s, 0); xfree(domain); xfree(userName); xfree(alternateShell); xfree(workingDir); if (!usedPasswordCookie) xfree(password); if (settings->rdp_version >= 5) rdp_write_extended_info_packet(s, settings); /* extraInfo */ } /** * Read Client Info PDU (CLIENT_INFO_PDU).\n * @msdn{cc240474} * @param rdp RDP module * @param s stream */ boolean rdp_recv_client_info(rdpRdp* rdp, STREAM* s) { uint16 length; uint16 channelId; uint16 securityFlags; if (!rdp_read_header(rdp, s, &length, &channelId)) return false; rdp_read_security_header(s, &securityFlags); if ((securityFlags & SEC_INFO_PKT) == 0) return false; if (rdp->settings->encryption) { if (securityFlags & SEC_REDIRECTION_PKT) { printf("Error: SEC_REDIRECTION_PKT unsupported\n"); return false; } if (securityFlags & SEC_ENCRYPT) { if (!rdp_decrypt(rdp, s, length - 4, securityFlags)) { printf("rdp_decrypt failed\n"); return false; } } } return rdp_read_info_packet(s, rdp->settings); } /** * Send Client Info PDU (CLIENT_INFO_PDU).\n * @msdn{cc240474} * @param rdp RDP module */ boolean rdp_send_client_info(rdpRdp* rdp) { STREAM* s; //rdp->settings->crypt_flags |= SEC_INFO_PKT; rdp->sec_flags |= SEC_INFO_PKT; s = rdp_send_stream_init(rdp); rdp_write_info_packet(s, rdp->settings); return rdp_send(rdp, s, MCS_GLOBAL_CHANNEL_ID); } void rdp_recv_logon_info_v1(rdpRdp* rdp, STREAM* s) { uint32 cbDomain; uint32 cbUserName; stream_read_uint32(s, cbDomain); /* cbDomain (4 bytes) */ stream_seek(s, 52); /* domain (52 bytes) */ stream_read_uint32(s, cbUserName); /* cbUserName (4 bytes) */ stream_seek(s, 512); /* userName (512 bytes) */ stream_seek_uint32(s); /* sessionId (4 bytes) */ } void rdp_recv_logon_info_v2(rdpRdp* rdp, STREAM* s) { uint32 cbDomain; uint32 cbUserName; stream_seek_uint16(s); /* version (2 bytes) */ stream_seek_uint32(s); /* size (4 bytes) */ stream_seek_uint32(s); /* sessionId (4 bytes) */ stream_read_uint32(s, cbDomain); /* cbDomain (4 bytes) */ stream_read_uint32(s, cbUserName); /* cbUserName (4 bytes) */ stream_seek(s, 558); /* pad */ stream_seek(s, cbDomain); /* domain */ stream_seek(s, cbUserName); /* userName */ } void rdp_recv_logon_plain_notify(rdpRdp* rdp, STREAM* s) { stream_seek(s, 576); /* pad */ } void rdp_recv_logon_error_info(rdpRdp* rdp, STREAM* s) { uint32 errorNotificationType; uint32 errorNotificationData; stream_read_uint32(s, errorNotificationType); /* errorNotificationType (4 bytes) */ stream_read_uint32(s, errorNotificationData); /* errorNotificationData (4 bytes) */ } void rdp_recv_logon_info_extended(rdpRdp* rdp, STREAM* s) { uint32 cbFieldData; uint32 fieldsPresent; uint16 Length; stream_read_uint16(s, Length); /* The total size in bytes of this structure */ stream_read_uint32(s, fieldsPresent); /* fieldsPresent (4 bytes) */ /* logonFields */ if (fieldsPresent & LOGON_EX_AUTORECONNECTCOOKIE) { stream_read_uint32(s, cbFieldData); /* cbFieldData (4 bytes) */ rdp_read_server_auto_reconnect_cookie(s, rdp->settings); } if (fieldsPresent & LOGON_EX_LOGONERRORS) { stream_read_uint32(s, cbFieldData); /* cbFieldData (4 bytes) */ rdp_recv_logon_error_info(rdp, s); } stream_seek(s, 570); /* pad */ } boolean rdp_recv_save_session_info(rdpRdp* rdp, STREAM* s) { uint32 infoType; stream_read_uint32(s, infoType); /* infoType (4 bytes) */ //printf("%s\n", INFO_TYPE_LOGON_STRINGS[infoType]); switch (infoType) { case INFO_TYPE_LOGON: rdp_recv_logon_info_v1(rdp, s); break; case INFO_TYPE_LOGON_LONG: rdp_recv_logon_info_v2(rdp, s); break; case INFO_TYPE_LOGON_PLAIN_NOTIFY: rdp_recv_logon_plain_notify(rdp, s); break; case INFO_TYPE_LOGON_EXTENDED_INF: rdp_recv_logon_info_extended(rdp, s); break; default: break; } return true; } FreeRDP-1.0.2/libfreerdp-core/info.h000066400000000000000000000066471207112532300171220ustar00rootroot00000000000000/** * FreeRDP: A Remote Desktop Protocol Client * RDP Client Info * * Copyright 2011 Marc-Andre Moreau * * 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. */ #ifndef __INFO_H #define __INFO_H #include "rdp.h" #include #include /* Client Address Family */ #define ADDRESS_FAMILY_INET 0x0002 #define ADDRESS_FAMILY_INET6 0x0017 /* Client Info Packet Flags */ #define INFO_MOUSE 0x00000001 #define INFO_DISABLECTRLALTDEL 0x00000002 #define INFO_AUTOLOGON 0x00000008 #define INFO_UNICODE 0x00000010 #define INFO_MAXIMIZESHELL 0x00000020 #define INFO_LOGONNOTIFY 0x00000040 #define INFO_COMPRESSION 0x00000080 #define INFO_ENABLEWINDOWSKEY 0x00000100 #define INFO_REMOTECONSOLEAUDIO 0x00002000 #define INFO_FORCE_ENCRYPTED_CS_PDU 0x00004000 #define INFO_RAIL 0x00008000 #define INFO_LOGONERRORS 0x00010000 #define INFO_MOUSE_HAS_WHEEL 0x00020000 #define INFO_PASSWORD_IS_SC_PIN 0x00040000 #define INFO_NOAUDIOPLAYBACK 0x00080000 #define INFO_USING_SAVED_CREDS 0x00100000 #define RNS_INFO_AUDIOCAPTURE 0x00200000 #define RNS_INFO_VIDEO_DISABLE 0x00400000 #define INFO_CompressionTypeMask 0x00001E00 #define INFO_PACKET_COMPR_TYPE_8K 0x00000100 #define INFO_PACKET_COMPR_TYPE_64K 0x00000200 #define INFO_PACKET_COMPR_TYPE_RDP6 0x00000400 #define INFO_PACKET_COMPR_TYPE_RDP61 0x00000600 /* Logon Information Types */ #define INFO_TYPE_LOGON 0x00000000 #define INFO_TYPE_LOGON_LONG 0x00000001 #define INFO_TYPE_LOGON_PLAIN_NOTIFY 0x00000002 #define INFO_TYPE_LOGON_EXTENDED_INF 0x00000003 /* Extended Logon Info */ #define LOGON_EX_AUTORECONNECTCOOKIE 0x00000001 #define LOGON_EX_LOGONERRORS 0x00000002 /* Logon Error Info */ #define LOGON_FAILED_BAD_PASSWORD 0x00000000 #define LOGON_FAILED_UPDATE_PASSWORD 0x00000001 #define LOGON_FAILED_OTHER 0x00000002 #define LOGON_WARNING 0x00000003 void rdp_read_system_time(STREAM* s, SYSTEM_TIME* system_time); void rdp_write_system_time(STREAM* s, SYSTEM_TIME* system_time); void rdp_get_client_time_zone(STREAM* s, rdpSettings* settings); boolean rdp_read_client_time_zone(STREAM* s, rdpSettings* settings); void rdp_write_client_time_zone(STREAM* s, rdpSettings* settings); void rdp_read_server_auto_reconnect_cookie(STREAM* s, rdpSettings* settings); boolean rdp_read_client_auto_reconnect_cookie(STREAM* s, rdpSettings* settings); void rdp_write_client_auto_reconnect_cookie(STREAM* s, rdpSettings* settings); void rdp_write_auto_reconnect_cookie(STREAM* s, rdpSettings* settings); boolean rdp_read_extended_info_packet(STREAM* s, rdpSettings* settings); void rdp_write_extended_info_packet(STREAM* s, rdpSettings* settings); boolean rdp_read_info_packet(STREAM* s, rdpSettings* settings); void rdp_write_info_packet(STREAM* s, rdpSettings* settings); boolean rdp_recv_client_info(rdpRdp* rdp, STREAM* s); boolean rdp_send_client_info(rdpRdp* rdp); boolean rdp_recv_save_session_info(rdpRdp* rdp, STREAM* s); #endif /* __INFO_H */ FreeRDP-1.0.2/libfreerdp-core/input.c000066400000000000000000000260411207112532300173070ustar00rootroot00000000000000/** * FreeRDP: A Remote Desktop Protocol Client * Input PDUs * * Copyright 2011 Marc-Andre Moreau * * 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. */ #include "input.h" void rdp_write_client_input_pdu_header(STREAM* s, uint16 number) { stream_write_uint16(s, 1); /* numberEvents (2 bytes) */ stream_write_uint16(s, 0); /* pad2Octets (2 bytes) */ } void rdp_write_input_event_header(STREAM* s, uint32 time, uint16 type) { stream_write_uint32(s, time); /* eventTime (4 bytes) */ stream_write_uint16(s, type); /* messageType (2 bytes) */ } STREAM* rdp_client_input_pdu_init(rdpRdp* rdp, uint16 type) { STREAM* s; s = rdp_data_pdu_init(rdp); rdp_write_client_input_pdu_header(s, 1); rdp_write_input_event_header(s, 0, type); return s; } void rdp_send_client_input_pdu(rdpRdp* rdp, STREAM* s) { rdp_send_data_pdu(rdp, s, DATA_PDU_TYPE_INPUT, rdp->mcs->user_id); } void input_write_synchronize_event(STREAM* s, uint32 flags) { stream_write_uint16(s, 0); /* pad2Octets (2 bytes) */ stream_write_uint32(s, flags); /* toggleFlags (4 bytes) */ } void input_send_synchronize_event(rdpInput* input, uint32 flags) { STREAM* s; rdpRdp* rdp = input->context->rdp; s = rdp_client_input_pdu_init(rdp, INPUT_EVENT_SYNC); input_write_synchronize_event(s, flags); rdp_send_client_input_pdu(rdp, s); } void input_write_keyboard_event(STREAM* s, uint16 flags, uint16 code) { stream_write_uint16(s, flags); /* keyboardFlags (2 bytes) */ stream_write_uint16(s, code); /* keyCode (2 bytes) */ stream_write_uint16(s, 0); /* pad2Octets (2 bytes) */ } void input_send_keyboard_event(rdpInput* input, uint16 flags, uint16 code) { STREAM* s; rdpRdp* rdp = input->context->rdp; s = rdp_client_input_pdu_init(rdp, INPUT_EVENT_SCANCODE); input_write_keyboard_event(s, flags, code); rdp_send_client_input_pdu(rdp, s); } void input_write_unicode_keyboard_event(STREAM* s, uint16 flags, uint16 code) { stream_write_uint16(s, flags); /* keyboardFlags (2 bytes) */ stream_write_uint16(s, code); /* unicodeCode (2 bytes) */ stream_write_uint16(s, 0); /* pad2Octets (2 bytes) */ } void input_send_unicode_keyboard_event(rdpInput* input, uint16 flags, uint16 code) { STREAM* s; uint16 keyboardFlags = 0; rdpRdp* rdp = input->context->rdp; /* * According to the specification, the slow path Unicode Keyboard Event * (TS_UNICODE_KEYBOARD_EVENT) contains KBD_FLAGS_RELEASE flag when key * is released, but contains no flags when it is pressed. * This is different from the slow path Keyboard Event * (TS_KEYBOARD_EVENT) which does contain KBD_FLAGS_DOWN flag when the * key is pressed. * There is no KBD_FLAGS_EXTENDED flag in TS_UNICODE_KEYBOARD_EVENT. */ keyboardFlags |= (flags & KBD_FLAGS_RELEASE) ? KBD_FLAGS_RELEASE : 0; s = rdp_client_input_pdu_init(rdp, INPUT_EVENT_UNICODE); input_write_unicode_keyboard_event(s, flags, code); rdp_send_client_input_pdu(rdp, s); } void input_write_mouse_event(STREAM* s, uint16 flags, uint16 x, uint16 y) { stream_write_uint16(s, flags); /* pointerFlags (2 bytes) */ stream_write_uint16(s, x); /* xPos (2 bytes) */ stream_write_uint16(s, y); /* yPos (2 bytes) */ } void input_send_mouse_event(rdpInput* input, uint16 flags, uint16 x, uint16 y) { STREAM* s; rdpRdp* rdp = input->context->rdp; s = rdp_client_input_pdu_init(rdp, INPUT_EVENT_MOUSE); input_write_mouse_event(s, flags, x, y); rdp_send_client_input_pdu(rdp, s); } void input_write_extended_mouse_event(STREAM* s, uint16 flags, uint16 x, uint16 y) { stream_write_uint16(s, flags); /* pointerFlags (2 bytes) */ stream_write_uint16(s, x); /* xPos (2 bytes) */ stream_write_uint16(s, y); /* yPos (2 bytes) */ } void input_send_extended_mouse_event(rdpInput* input, uint16 flags, uint16 x, uint16 y) { STREAM* s; rdpRdp* rdp = input->context->rdp; s = rdp_client_input_pdu_init(rdp, INPUT_EVENT_MOUSEX); input_write_extended_mouse_event(s, flags, x, y); rdp_send_client_input_pdu(rdp, s); } void input_send_fastpath_synchronize_event(rdpInput* input, uint32 flags) { STREAM* s; rdpRdp* rdp = input->context->rdp; /* The FastPath Synchronization eventFlags has identical values as SlowPath */ s = fastpath_input_pdu_init(rdp->fastpath, (uint8) flags, FASTPATH_INPUT_EVENT_SYNC); fastpath_send_input_pdu(rdp->fastpath, s); } void input_send_fastpath_keyboard_event(rdpInput* input, uint16 flags, uint16 code) { STREAM* s; uint8 eventFlags = 0; rdpRdp* rdp = input->context->rdp; eventFlags |= (flags & KBD_FLAGS_RELEASE) ? FASTPATH_INPUT_KBDFLAGS_RELEASE : 0; eventFlags |= (flags & KBD_FLAGS_EXTENDED) ? FASTPATH_INPUT_KBDFLAGS_EXTENDED : 0; s = fastpath_input_pdu_init(rdp->fastpath, eventFlags, FASTPATH_INPUT_EVENT_SCANCODE); stream_write_uint8(s, code); /* keyCode (1 byte) */ fastpath_send_input_pdu(rdp->fastpath, s); } void input_send_fastpath_unicode_keyboard_event(rdpInput* input, uint16 flags, uint16 code) { STREAM* s; uint8 eventFlags = 0; rdpRdp* rdp = input->context->rdp; eventFlags |= (flags & KBD_FLAGS_RELEASE) ? FASTPATH_INPUT_KBDFLAGS_RELEASE : 0; s = fastpath_input_pdu_init(rdp->fastpath, eventFlags, FASTPATH_INPUT_EVENT_UNICODE); stream_write_uint16(s, code); /* unicodeCode (2 bytes) */ fastpath_send_input_pdu(rdp->fastpath, s); } void input_send_fastpath_mouse_event(rdpInput* input, uint16 flags, uint16 x, uint16 y) { STREAM* s; rdpRdp* rdp = input->context->rdp; s = fastpath_input_pdu_init(rdp->fastpath, 0, FASTPATH_INPUT_EVENT_MOUSE); input_write_mouse_event(s, flags, x, y); fastpath_send_input_pdu(rdp->fastpath, s); } void input_send_fastpath_extended_mouse_event(rdpInput* input, uint16 flags, uint16 x, uint16 y) { STREAM* s; rdpRdp* rdp = input->context->rdp; s = fastpath_input_pdu_init(rdp->fastpath, 0, FASTPATH_INPUT_EVENT_MOUSEX); input_write_extended_mouse_event(s, flags, x, y); fastpath_send_input_pdu(rdp->fastpath, s); } static boolean input_recv_sync_event(rdpInput* input, STREAM* s) { uint32 toggleFlags; if (stream_get_left(s) < 6) return false; stream_seek(s, 2); /* pad2Octets (2 bytes) */ stream_read_uint32(s, toggleFlags); /* toggleFlags (4 bytes) */ IFCALL(input->SynchronizeEvent, input, toggleFlags); return true; } static boolean input_recv_keyboard_event(rdpInput* input, STREAM* s) { uint16 keyboardFlags, keyCode; if (stream_get_left(s) < 6) return false; stream_read_uint16(s, keyboardFlags); /* keyboardFlags (2 bytes) */ stream_read_uint16(s, keyCode); /* keyCode (2 bytes) */ stream_seek(s, 2); /* pad2Octets (2 bytes) */ IFCALL(input->KeyboardEvent, input, keyboardFlags, keyCode); return true; } static boolean input_recv_unicode_keyboard_event(rdpInput* input, STREAM* s) { uint16 keyboardFlags, unicodeCode; if (stream_get_left(s) < 6) return false; stream_read_uint16(s, keyboardFlags); /* keyboardFlags (2 bytes) */ stream_read_uint16(s, unicodeCode); /* unicodeCode (2 bytes) */ stream_seek(s, 2); /* pad2Octets (2 bytes) */ /* * According to the specification, the slow path Unicode Keyboard Event * (TS_UNICODE_KEYBOARD_EVENT) contains KBD_FLAGS_RELEASE flag when key * is released, but contains no flags when it is pressed. * This is different from the slow path Keyboard Event * (TS_KEYBOARD_EVENT) which does contain KBD_FLAGS_DOWN flag when the * key is pressed. * Set the KBD_FLAGS_DOWN flag if the KBD_FLAGS_RELEASE flag is missing. */ if ((keyboardFlags & KBD_FLAGS_RELEASE) == 0) keyboardFlags |= KBD_FLAGS_DOWN; IFCALL(input->UnicodeKeyboardEvent, input, keyboardFlags, unicodeCode); return true; } static boolean input_recv_mouse_event(rdpInput* input, STREAM* s) { uint16 pointerFlags, xPos, yPos; if (stream_get_left(s) < 6) return false; stream_read_uint16(s, pointerFlags); /* pointerFlags (2 bytes) */ stream_read_uint16(s, xPos); /* xPos (2 bytes) */ stream_read_uint16(s, yPos); /* yPos (2 bytes) */ IFCALL(input->MouseEvent, input, pointerFlags, xPos, yPos); return true; } static boolean input_recv_extended_mouse_event(rdpInput* input, STREAM* s) { uint16 pointerFlags, xPos, yPos; if (stream_get_left(s) < 6) return false; stream_read_uint16(s, pointerFlags); /* pointerFlags (2 bytes) */ stream_read_uint16(s, xPos); /* xPos (2 bytes) */ stream_read_uint16(s, yPos); /* yPos (2 bytes) */ IFCALL(input->ExtendedMouseEvent, input, pointerFlags, xPos, yPos); return true; } static boolean input_recv_event(rdpInput* input, STREAM* s) { uint16 messageType; if (stream_get_left(s) < 4) return false; stream_seek(s, 4); /* eventTime (4 bytes), ignored by the server */ stream_read_uint16(s, messageType); /* messageType (2 bytes) */ switch (messageType) { case INPUT_EVENT_SYNC: if (!input_recv_sync_event(input, s)) return false; break; case INPUT_EVENT_SCANCODE: if (!input_recv_keyboard_event(input, s)) return false; break; case INPUT_EVENT_UNICODE: if (!input_recv_unicode_keyboard_event(input, s)) return false; break; case INPUT_EVENT_MOUSE: if (!input_recv_mouse_event(input, s)) return false; break; case INPUT_EVENT_MOUSEX: if (!input_recv_extended_mouse_event(input, s)) return false; break; default: printf("Unknown messageType %u\n", messageType); /* Each input event uses 6 bytes. */ stream_seek(s, 6); break; } return true; } boolean input_recv(rdpInput* input, STREAM* s) { uint16 i, numberEvents; if (stream_get_left(s) < 4) return false; stream_read_uint16(s, numberEvents); /* numberEvents (2 bytes) */ stream_seek(s, 2); /* pad2Octets (2 bytes) */ /* Each input event uses 6 exactly bytes. */ if (stream_get_left(s) < 6 * numberEvents) return false; for (i = 0; i < numberEvents; i++) { if (!input_recv_event(input, s)) return false; } return true; } void input_register_client_callbacks(rdpInput* input) { rdpRdp* rdp = input->context->rdp; if (rdp->settings->fastpath_input) { input->SynchronizeEvent = input_send_fastpath_synchronize_event; input->KeyboardEvent = input_send_fastpath_keyboard_event; input->UnicodeKeyboardEvent = input_send_fastpath_unicode_keyboard_event; input->MouseEvent = input_send_fastpath_mouse_event; input->ExtendedMouseEvent = input_send_fastpath_extended_mouse_event; } else { input->SynchronizeEvent = input_send_synchronize_event; input->KeyboardEvent = input_send_keyboard_event; input->UnicodeKeyboardEvent = input_send_unicode_keyboard_event; input->MouseEvent = input_send_mouse_event; input->ExtendedMouseEvent = input_send_extended_mouse_event; } } rdpInput* input_new(rdpRdp* rdp) { rdpInput* input; input = (rdpInput*) xzalloc(sizeof(rdpInput)); if (input != NULL) { } return input; } void input_free(rdpInput* input) { if (input != NULL) { xfree(input); } } FreeRDP-1.0.2/libfreerdp-core/input.h000066400000000000000000000041731207112532300173160ustar00rootroot00000000000000/** * FreeRDP: A Remote Desktop Protocol Client * Input PDUs * * Copyright 2011 Marc-Andre Moreau * * 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. */ #ifndef __INPUT_H #define __INPUT_H #include "rdp.h" #include "fastpath.h" #include #include #include #include /* Input Events */ #define INPUT_EVENT_SYNC 0x0000 #define INPUT_EVENT_SCANCODE 0x0004 #define INPUT_EVENT_UNICODE 0x0005 #define INPUT_EVENT_MOUSE 0x8001 #define INPUT_EVENT_MOUSEX 0x8002 #define RDP_CLIENT_INPUT_PDU_HEADER_LENGTH 4 void input_send_synchronize_event(rdpInput* input, uint32 flags); void input_send_keyboard_event(rdpInput* input, uint16 flags, uint16 code); void input_send_unicode_keyboard_event(rdpInput* input, uint16 flags, uint16 code); void input_send_mouse_event(rdpInput* input, uint16 flags, uint16 x, uint16 y); void input_send_extended_mouse_event(rdpInput* input, uint16 flags, uint16 x, uint16 y); void input_send_fastpath_synchronize_event(rdpInput* input, uint32 flags); void input_send_fastpath_keyboard_event(rdpInput* input, uint16 flags, uint16 code); void input_send_fastpath_unicode_keyboard_event(rdpInput* input, uint16 flags, uint16 code); void input_send_fastpath_mouse_event(rdpInput* input, uint16 flags, uint16 x, uint16 y); void input_send_fastpath_extended_mouse_event(rdpInput* input, uint16 flags, uint16 x, uint16 y); boolean input_recv(rdpInput* input, STREAM* s); void input_register_client_callbacks(rdpInput* input); rdpInput* input_new(rdpRdp* rdp); void input_free(rdpInput* input); #endif /* __INPUT_H */ FreeRDP-1.0.2/libfreerdp-core/license.c000066400000000000000000000601461207112532300175760ustar00rootroot00000000000000/** * FreeRDP: A Remote Desktop Protocol Client * RDP Licensing * * Copyright 2011 Marc-Andre Moreau * * 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. */ #include "redirection.h" #include "license.h" #ifdef WITH_DEBUG_LICENSE static const char* const LICENSE_MESSAGE_STRINGS[] = { "", "License Request", "Platform Challenge", "New License", "Upgrade License", "", "", "", "", "", "", "", "", "", "", "", "", "", "License Info", "New License Request", "", "Platform Challenge Response", "", "", "", "", "", "", "", "", "", "Error Alert" }; static const char* const error_codes[] = { "ERR_UNKNOWN", "ERR_INVALID_SERVER_CERTIFICATE", "ERR_NO_LICENSE", "ERR_INVALID_MAC", "ERR_INVALID_SCOPE", "ERR_UNKNOWN", "ERR_NO_LICENSE_SERVER", "STATUS_VALID_CLIENT", "ERR_INVALID_CLIENT", "ERR_UNKNOWN", "ERR_UNKNOWN", "ERR_INVALID_PRODUCT_ID", "ERR_INVALID_MESSAGE_LENGTH" }; static const char* const state_transitions[] = { "ST_UNKNOWN", "ST_TOTAL_ABORT", "ST_NO_TRANSITION", "ST_RESET_PHASE_TO_START", "ST_RESEND_LAST_MESSAGE" }; #endif /** * Read a licensing preamble.\n * @msdn{cc240480} * @param s stream * @param bMsgType license message type * @param flags message flags * @param wMsgSize message size */ void license_read_preamble(STREAM* s, uint8* bMsgType, uint8* flags, uint16* wMsgSize) { /* preamble (4 bytes) */ stream_read_uint8(s, *bMsgType); /* bMsgType (1 byte) */ stream_read_uint8(s, *flags); /* flags (1 byte) */ stream_read_uint16(s, *wMsgSize); /* wMsgSize (2 bytes) */ } /** * Write a licensing preamble.\n * @msdn{cc240480} * @param s stream * @param bMsgType license message type * @param flags message flags * @param wMsgSize message size */ void license_write_preamble(STREAM* s, uint8 bMsgType, uint8 flags, uint16 wMsgSize) { /* preamble (4 bytes) */ stream_write_uint8(s, bMsgType); /* bMsgType (1 byte) */ stream_write_uint8(s, flags); /* flags (1 byte) */ stream_write_uint16(s, wMsgSize); /* wMsgSize (2 bytes) */ } /** * Initialize a license packet stream.\n * @param license license module * @return stream */ STREAM* license_send_stream_init(rdpLicense* license) { STREAM* s; s = transport_send_stream_init(license->rdp->transport, 4096); stream_seek(s, LICENSE_PACKET_HEADER_MAX_LENGTH); return s; } /** * Send an RDP licensing packet.\n * @msdn{cc240479} * @param license license module * @param s stream */ boolean license_send(rdpLicense* license, STREAM* s, uint8 type) { int length; uint8 flags; uint16 wMsgSize; uint16 sec_flags; DEBUG_LICENSE("Sending %s Packet", LICENSE_MESSAGE_STRINGS[type & 0x1F]); length = stream_get_length(s); stream_set_pos(s, 0); sec_flags = SEC_LICENSE_PKT; wMsgSize = length - LICENSE_PACKET_HEADER_MAX_LENGTH + 4; /** * Using EXTENDED_ERROR_MSG_SUPPORTED here would cause mstsc to crash when * running in server mode! This flag seems to be incorrectly documented. */ flags = PREAMBLE_VERSION_3_0; rdp_write_header(license->rdp, s, length, MCS_GLOBAL_CHANNEL_ID); rdp_write_security_header(s, sec_flags); license_write_preamble(s, type, flags, wMsgSize); #ifdef WITH_DEBUG_LICENSE printf("Sending %s Packet, length %d\n", LICENSE_MESSAGE_STRINGS[type & 0x1F], wMsgSize); freerdp_hexdump(s->p - 4, wMsgSize); #endif stream_set_pos(s, length); if (transport_write(license->rdp->transport, s) < 0) return false; return true; } /** * Receive an RDP licensing packet.\n * @msdn{cc240479} * @param license license module * @param s stream */ boolean license_recv(rdpLicense* license, STREAM* s) { uint16 length; uint16 channelId; uint16 sec_flags; uint8 flags; uint8 bMsgType; uint16 wMsgSize; if (!rdp_read_header(license->rdp, s, &length, &channelId)) { printf("Incorrect RDP header.\n"); return false; } rdp_read_security_header(s, &sec_flags); if (!(sec_flags & SEC_LICENSE_PKT)) { stream_rewind(s, RDP_SECURITY_HEADER_LENGTH); if (rdp_recv_out_of_sequence_pdu(license->rdp, s) != true) { printf("Unexpected license packet.\n"); return false; } return true; } license_read_preamble(s, &bMsgType, &flags, &wMsgSize); /* preamble (4 bytes) */ DEBUG_LICENSE("Receiving %s Packet", LICENSE_MESSAGE_STRINGS[bMsgType & 0x1F]); switch (bMsgType) { case LICENSE_REQUEST: license_read_license_request_packet(license, s); license_send_new_license_request_packet(license); break; case PLATFORM_CHALLENGE: license_read_platform_challenge_packet(license, s); license_send_platform_challenge_response_packet(license); break; case NEW_LICENSE: license_read_new_license_packet(license, s); break; case UPGRADE_LICENSE: license_read_upgrade_license_packet(license, s); break; case ERROR_ALERT: license_read_error_alert_packet(license, s); break; default: printf("invalid bMsgType:%d\n", bMsgType); return false; } return true; } void license_generate_randoms(rdpLicense* license) { #if 0 crypto_nonce(license->client_random, CLIENT_RANDOM_LENGTH); /* ClientRandom */ crypto_nonce(license->premaster_secret, PREMASTER_SECRET_LENGTH); /* PremasterSecret */ #else memset(license->client_random, 0, CLIENT_RANDOM_LENGTH); /* ClientRandom */ memset(license->premaster_secret, 0, PREMASTER_SECRET_LENGTH); /* PremasterSecret */ #endif } /** * Generate License Cryptographic Keys. * @param license license module */ void license_generate_keys(rdpLicense* license) { security_master_secret(license->premaster_secret, license->client_random, license->server_random, license->master_secret); /* MasterSecret */ security_session_key_blob(license->master_secret, license->client_random, license->server_random, license->session_key_blob); /* SessionKeyBlob */ security_mac_salt_key(license->session_key_blob, license->client_random, license->server_random, license->mac_salt_key); /* MacSaltKey */ security_licensing_encryption_key(license->session_key_blob, license->client_random, license->server_random, license->licensing_encryption_key); /* LicensingEncryptionKey */ #ifdef WITH_DEBUG_LICENSE printf("ClientRandom:\n"); freerdp_hexdump(license->client_random, CLIENT_RANDOM_LENGTH); printf("ServerRandom:\n"); freerdp_hexdump(license->server_random, SERVER_RANDOM_LENGTH); printf("PremasterSecret:\n"); freerdp_hexdump(license->premaster_secret, PREMASTER_SECRET_LENGTH); printf("MasterSecret:\n"); freerdp_hexdump(license->master_secret, MASTER_SECRET_LENGTH); printf("SessionKeyBlob:\n"); freerdp_hexdump(license->session_key_blob, SESSION_KEY_BLOB_LENGTH); printf("MacSaltKey:\n"); freerdp_hexdump(license->mac_salt_key, MAC_SALT_KEY_LENGTH); printf("LicensingEncryptionKey:\n"); freerdp_hexdump(license->licensing_encryption_key, LICENSING_ENCRYPTION_KEY_LENGTH); #endif } /** * Generate Unique Hardware Identifier (CLIENT_HARDWARE_ID).\n * @param license license module */ void license_generate_hwid(rdpLicense* license) { CryptoMd5 md5; uint8* mac_address; memset(license->hwid, 0, HWID_LENGTH); mac_address = license->rdp->transport->tcp->mac_address; md5 = crypto_md5_init(); crypto_md5_update(md5, mac_address, 6); crypto_md5_final(md5, &license->hwid[HWID_PLATFORM_ID_LENGTH]); } void license_encrypt_premaster_secret(rdpLicense* license) { uint8* encrypted_premaster_secret; #if 0 int key_length; uint8* modulus; uint8* exponent; rdpCertificate *certificate; if (license->server_certificate->length) certificate = license->certificate; else certificate = license->rdp->settings->server_cert; exponent = certificate->cert_info.exponent; modulus = certificate->cert_info.modulus.data; key_length = certificate->cert_info.modulus.length; #ifdef WITH_DEBUG_LICENSE printf("modulus (%d bits):\n", key_length * 8); freerdp_hexdump(modulus, key_length); printf("exponent:\n"); freerdp_hexdump(exponent, 4); #endif encrypted_premaster_secret = (uint8*) xmalloc(MODULUS_MAX_SIZE); memset(encrypted_premaster_secret, 0, MODULUS_MAX_SIZE); crypto_rsa_public_encrypt(license->premaster_secret, PREMASTER_SECRET_LENGTH, key_length, modulus, exponent, encrypted_premaster_secret); license->encrypted_premaster_secret->type = BB_RANDOM_BLOB; license->encrypted_premaster_secret->length = PREMASTER_SECRET_LENGTH; license->encrypted_premaster_secret->data = encrypted_premaster_secret; #else encrypted_premaster_secret = (uint8*) xmalloc(MODULUS_MAX_SIZE); memset(encrypted_premaster_secret, 0, MODULUS_MAX_SIZE); license->encrypted_premaster_secret->type = BB_RANDOM_BLOB; license->encrypted_premaster_secret->length = PREMASTER_SECRET_LENGTH; license->encrypted_premaster_secret->data = encrypted_premaster_secret; #endif } void license_decrypt_platform_challenge(rdpLicense* license) { CryptoRc4 rc4; license->platform_challenge->data = (uint8*) xmalloc(license->encrypted_platform_challenge->length); license->platform_challenge->length = license->encrypted_platform_challenge->length; rc4 = crypto_rc4_init(license->licensing_encryption_key, LICENSING_ENCRYPTION_KEY_LENGTH); crypto_rc4(rc4, license->encrypted_platform_challenge->length, license->encrypted_platform_challenge->data, license->platform_challenge->data); #ifdef WITH_DEBUG_LICENSE printf("encrypted_platform challenge:\n"); freerdp_hexdump(license->encrypted_platform_challenge->data, license->encrypted_platform_challenge->length); printf("platform challenge:\n"); freerdp_hexdump(license->platform_challenge->data, license->platform_challenge->length); #endif crypto_rc4_free(rc4); } /** * Read Product Information (PRODUCT_INFO).\n * @msdn{cc241915} * @param s stream * @param productInfo product information */ void license_read_product_info(STREAM* s, PRODUCT_INFO* productInfo) { stream_read_uint32(s, productInfo->dwVersion); /* dwVersion (4 bytes) */ stream_read_uint32(s, productInfo->cbCompanyName); /* cbCompanyName (4 bytes) */ productInfo->pbCompanyName = (uint8*) xmalloc(productInfo->cbCompanyName); stream_read(s, productInfo->pbCompanyName, productInfo->cbCompanyName); stream_read_uint32(s, productInfo->cbProductId); /* cbProductId (4 bytes) */ productInfo->pbProductId = (uint8*) xmalloc(productInfo->cbProductId); stream_read(s, productInfo->pbProductId, productInfo->cbProductId); } /** * Allocate New Product Information (PRODUCT_INFO).\n * @msdn{cc241915} * @return new product information */ PRODUCT_INFO* license_new_product_info() { PRODUCT_INFO* productInfo; productInfo = (PRODUCT_INFO*) xmalloc(sizeof(PRODUCT_INFO)); productInfo->dwVersion = 0; productInfo->cbCompanyName = 0; productInfo->pbCompanyName = NULL; productInfo->cbProductId = 0; productInfo->pbProductId = NULL; return productInfo; } /** * Free Product Information (PRODUCT_INFO).\n * @msdn{cc241915} * @param productInfo product information */ void license_free_product_info(PRODUCT_INFO* productInfo) { if (productInfo->pbCompanyName != NULL) xfree(productInfo->pbCompanyName); if (productInfo->pbProductId != NULL) xfree(productInfo->pbProductId); xfree(productInfo); } /** * Read License Binary Blob (LICENSE_BINARY_BLOB).\n * @msdn{cc240481} * @param s stream * @param blob license binary blob */ void license_read_binary_blob(STREAM* s, LICENSE_BLOB* blob) { uint16 wBlobType; stream_read_uint16(s, wBlobType); /* wBlobType (2 bytes) */ stream_read_uint16(s, blob->length); /* wBlobLen (2 bytes) */ /* * Server can choose to not send data by setting len to 0. * If so, it may not bother to set the type, so shortcut the warning */ if (blob->type != BB_ANY_BLOB && blob->length == 0) return; if (blob->type != wBlobType && blob->type != BB_ANY_BLOB) { printf("license binary blob type (%x) does not match expected type (%x).\n", wBlobType, blob->type); } blob->type = wBlobType; blob->data = (uint8*) xmalloc(blob->length); stream_read(s, blob->data, blob->length); /* blobData */ } /** * Write License Binary Blob (LICENSE_BINARY_BLOB).\n * @msdn{cc240481} * @param s stream * @param blob license binary blob */ void license_write_binary_blob(STREAM* s, LICENSE_BLOB* blob) { stream_write_uint16(s, blob->type); /* wBlobType (2 bytes) */ stream_write_uint16(s, blob->length); /* wBlobLen (2 bytes) */ if (blob->length > 0) stream_write(s, blob->data, blob->length); /* blobData */ } void license_write_padded_binary_blob(STREAM* s, LICENSE_BLOB* blob) { uint16 pad_len; pad_len = 72 % blob->length; stream_write_uint16(s, blob->type); /* wBlobType (2 bytes) */ stream_write_uint16(s, blob->length + pad_len); /* wBlobLen (2 bytes) */ if (blob->length > 0) stream_write(s, blob->data, blob->length); /* blobData */ stream_write_zero(s, pad_len); } /** * Allocate New License Binary Blob (LICENSE_BINARY_BLOB).\n * @msdn{cc240481} * @return new license binary blob */ LICENSE_BLOB* license_new_binary_blob(uint16 type) { LICENSE_BLOB* blob; blob = (LICENSE_BLOB*) xmalloc(sizeof(LICENSE_BLOB)); blob->type = type; blob->length = 0; blob->data = NULL; return blob; } /** * Free License Binary Blob (LICENSE_BINARY_BLOB).\n * @msdn{cc240481} * @param blob license binary blob */ void license_free_binary_blob(LICENSE_BLOB* blob) { if (blob->data != NULL) xfree(blob->data); xfree(blob); } /** * Read License Scope List (SCOPE_LIST).\n * @msdn{cc241916} * @param s stream * @param scopeList scope list */ void license_read_scope_list(STREAM* s, SCOPE_LIST* scopeList) { uint32 i; uint32 scopeCount; stream_read_uint32(s, scopeCount); /* ScopeCount (4 bytes) */ scopeList->count = scopeCount; scopeList->array = (LICENSE_BLOB*) xmalloc(sizeof(LICENSE_BLOB) * scopeCount); /* ScopeArray */ for (i = 0; i < scopeCount; i++) { scopeList->array[i].type = BB_SCOPE_BLOB; license_read_binary_blob(s, &scopeList->array[i]); } } /** * Allocate New License Scope List (SCOPE_LIST).\n * @msdn{cc241916} * @return new scope list */ SCOPE_LIST* license_new_scope_list() { SCOPE_LIST* scopeList; scopeList = (SCOPE_LIST*) xmalloc(sizeof(SCOPE_LIST)); scopeList->count = 0; scopeList->array = NULL; return scopeList; } /** * Free License Scope List (SCOPE_LIST).\n * @msdn{cc241916} * @param scopeList scope list */ void license_free_scope_list(SCOPE_LIST* scopeList) { uint32 i; for (i = 0; i < scopeList->count; i++) { license_free_binary_blob(&scopeList->array[i]); } xfree(scopeList); } /** * Read a LICENSE_REQUEST packet.\n * @msdn{cc241914} * @param license license module * @param s stream */ void license_read_license_request_packet(rdpLicense* license, STREAM* s) { /* ServerRandom (32 bytes) */ stream_read(s, license->server_random, 32); /* ProductInfo */ license_read_product_info(s, license->product_info); /* KeyExchangeList */ license_read_binary_blob(s, license->key_exchange_list); /* ServerCertificate */ license_read_binary_blob(s, license->server_certificate); /* ScopeList */ license_read_scope_list(s, license->scope_list); /* Parse Server Certificate */ certificate_read_server_certificate(license->certificate, license->server_certificate->data, license->server_certificate->length); license_generate_keys(license); license_generate_hwid(license); license_encrypt_premaster_secret(license); } /** * Read a PLATFORM_CHALLENGE packet.\n * @msdn{cc241921} * @param license license module * @param s stream */ void license_read_platform_challenge_packet(rdpLicense* license, STREAM* s) { DEBUG_LICENSE("Receiving Platform Challenge Packet"); stream_seek(s, 4); /* ConnectFlags, Reserved (4 bytes) */ /* EncryptedPlatformChallenge */ license->encrypted_platform_challenge->type = BB_ANY_BLOB; license_read_binary_blob(s, license->encrypted_platform_challenge); license->encrypted_platform_challenge->type = BB_ENCRYPTED_DATA_BLOB; /* MACData (16 bytes) */ stream_seek(s, 16); license_decrypt_platform_challenge(license); } /** * Read a NEW_LICENSE packet.\n * @msdn{cc241926} * @param license license module * @param s stream */ void license_read_new_license_packet(rdpLicense* license, STREAM* s) { DEBUG_LICENSE("Receiving New License Packet"); license->state = LICENSE_STATE_COMPLETED; } /** * Read an UPGRADE_LICENSE packet.\n * @msdn{cc241924} * @param license license module * @param s stream */ void license_read_upgrade_license_packet(rdpLicense* license, STREAM* s) { DEBUG_LICENSE("Receiving Upgrade License Packet"); license->state = LICENSE_STATE_COMPLETED; } /** * Read an ERROR_ALERT packet.\n * @msdn{cc240482} * @param license license module * @param s stream */ void license_read_error_alert_packet(rdpLicense* license, STREAM* s) { uint32 dwErrorCode; uint32 dwStateTransition; stream_read_uint32(s, dwErrorCode); /* dwErrorCode (4 bytes) */ stream_read_uint32(s, dwStateTransition); /* dwStateTransition (4 bytes) */ license_read_binary_blob(s, license->error_info); /* bbErrorInfo */ #ifdef WITH_DEBUG_LICENSE printf("dwErrorCode: %s, dwStateTransition: %s\n", error_codes[dwErrorCode], state_transitions[dwStateTransition]); #endif if (dwErrorCode == STATUS_VALID_CLIENT) { license->state = LICENSE_STATE_COMPLETED; return; } switch (dwStateTransition) { case ST_TOTAL_ABORT: license->state = LICENSE_STATE_ABORTED; break; case ST_NO_TRANSITION: license->state = LICENSE_STATE_COMPLETED; break; case ST_RESET_PHASE_TO_START: license->state = LICENSE_STATE_AWAIT; break; case ST_RESEND_LAST_MESSAGE: break; default: break; } } /** * Write Platform ID.\n * @msdn{cc241918} * @param license license module * @param s stream */ void license_write_platform_id(rdpLicense* license, STREAM* s) { stream_write_uint8(s, 0); /* Client Operating System Version */ stream_write_uint8(s, 0); /* Independent Software Vendor (ISV) */ stream_write_uint16(s, 0); /* Client Software Build */ } /** * Write a NEW_LICENSE_REQUEST packet.\n * @msdn{cc241918} * @param license license module * @param s stream */ void license_write_new_license_request_packet(rdpLicense* license, STREAM* s) { stream_write_uint32(s, KEY_EXCHANGE_ALG_RSA); /* PreferredKeyExchangeAlg (4 bytes) */ license_write_platform_id(license, s); /* PlatformId (4 bytes) */ stream_write(s, license->client_random, 32); /* ClientRandom (32 bytes) */ license_write_padded_binary_blob(s, license->encrypted_premaster_secret); /* EncryptedPremasterSecret */ license_write_binary_blob(s, license->client_user_name); /* ClientUserName */ license_write_binary_blob(s, license->client_machine_name); /* ClientMachineName */ } /** * Send a NEW_LICENSE_REQUEST packet.\n * @msdn{cc241918} * @param license license module */ void license_send_new_license_request_packet(rdpLicense* license) { STREAM* s; char* username; s = license_send_stream_init(license); if (license->rdp->settings->username != NULL) username = license->rdp->settings->username; else username = "username"; license->client_user_name->data = (uint8*) username; license->client_user_name->length = strlen(username) + 1; license->client_machine_name->data = (uint8*) license->rdp->settings->client_hostname; license->client_machine_name->length = strlen(license->rdp->settings->client_hostname) + 1; license_write_new_license_request_packet(license, s); license_send(license, s, NEW_LICENSE_REQUEST); license->client_user_name->data = NULL; license->client_user_name->length = 0; license->client_machine_name->data = NULL; license->client_machine_name->length = 0; } /** * Write Client Challenge Response Packet.\n * @msdn{cc241922} * @param license license module * @param s stream * @param mac_data signature */ void license_write_platform_challenge_response_packet(rdpLicense* license, STREAM* s, uint8* mac_data) { /* EncryptedPlatformChallengeResponse */ license_write_binary_blob(s, license->encrypted_platform_challenge); /* EncryptedHWID */ license_write_binary_blob(s, license->encrypted_hwid); /* MACData */ stream_write(s, mac_data, 16); } /** * Send Client Challenge Response Packet.\n * @msdn{cc241922} * @param license license module */ void license_send_platform_challenge_response_packet(rdpLicense* license) { STREAM* s; int length; uint8* buffer; CryptoRc4 rc4; uint8 mac_data[16]; s = license_send_stream_init(license); DEBUG_LICENSE("Sending Platform Challenge Response Packet"); license->encrypted_platform_challenge->type = BB_DATA_BLOB; length = license->platform_challenge->length + HWID_LENGTH; buffer = (uint8*) xmalloc(length); memcpy(buffer, license->platform_challenge->data, license->platform_challenge->length); memcpy(&buffer[license->platform_challenge->length], license->hwid, HWID_LENGTH); security_mac_data(license->mac_salt_key, buffer, length, mac_data); xfree(buffer); buffer = (uint8*) xmalloc(HWID_LENGTH); rc4 = crypto_rc4_init(license->licensing_encryption_key, LICENSING_ENCRYPTION_KEY_LENGTH); crypto_rc4(rc4, HWID_LENGTH, license->hwid, buffer); crypto_rc4_free(rc4); #ifdef WITH_DEBUG_LICENSE printf("Licensing Encryption Key:\n"); freerdp_hexdump(license->licensing_encryption_key, 16); printf("HardwareID:\n"); freerdp_hexdump(license->hwid, 20); printf("Encrypted HardwareID:\n"); freerdp_hexdump(buffer, 20); #endif license->encrypted_hwid->type = BB_DATA_BLOB; license->encrypted_hwid->data = buffer; license->encrypted_hwid->length = HWID_LENGTH; license_write_platform_challenge_response_packet(license, s, mac_data); license_send(license, s, PLATFORM_CHALLENGE_RESPONSE); } /** * Send Server License Error - Valid Client Packet.\n * @msdn{cc241922} * @param license license module */ boolean license_send_valid_client_error_packet(rdpLicense* license) { STREAM* s; s = license_send_stream_init(license); stream_write_uint32(s, STATUS_VALID_CLIENT); /* dwErrorCode */ stream_write_uint32(s, ST_NO_TRANSITION); /* dwStateTransition */ license_write_binary_blob(s, license->error_info); license_send(license, s, ERROR_ALERT); return true; } /** * Instantiate new license module. * @param rdp RDP module * @return new license module */ rdpLicense* license_new(rdpRdp* rdp) { rdpLicense* license; license = (rdpLicense*) xzalloc(sizeof(rdpLicense)); if (license != NULL) { license->rdp = rdp; license->state = LICENSE_STATE_AWAIT; //license->certificate = certificate_new(rdp); license->certificate = certificate_new(); license->product_info = license_new_product_info(); license->error_info = license_new_binary_blob(BB_ERROR_BLOB); license->key_exchange_list = license_new_binary_blob(BB_KEY_EXCHG_ALG_BLOB); license->server_certificate = license_new_binary_blob(BB_CERTIFICATE_BLOB); license->client_user_name = license_new_binary_blob(BB_CLIENT_USER_NAME_BLOB); license->client_machine_name = license_new_binary_blob(BB_CLIENT_MACHINE_NAME_BLOB); license->platform_challenge = license_new_binary_blob(BB_ANY_BLOB); license->encrypted_platform_challenge = license_new_binary_blob(BB_ANY_BLOB); license->encrypted_premaster_secret = license_new_binary_blob(BB_ANY_BLOB); license->encrypted_hwid = license_new_binary_blob(BB_ENCRYPTED_DATA_BLOB); license->scope_list = license_new_scope_list(); license_generate_randoms(license); } return license; } /** * Free license module. * @param license license module to be freed */ void license_free(rdpLicense* license) { if (license != NULL) { certificate_free(license->certificate); license_free_product_info(license->product_info); license_free_binary_blob(license->error_info); license_free_binary_blob(license->key_exchange_list); license_free_binary_blob(license->server_certificate); license_free_binary_blob(license->client_user_name); license_free_binary_blob(license->client_machine_name); license_free_binary_blob(license->platform_challenge); license_free_binary_blob(license->encrypted_platform_challenge); license_free_binary_blob(license->encrypted_premaster_secret); license_free_binary_blob(license->encrypted_hwid); license_free_scope_list(license->scope_list); xfree(license); } } FreeRDP-1.0.2/libfreerdp-core/license.h000066400000000000000000000151371207112532300176030ustar00rootroot00000000000000/** * FreeRDP: A Remote Desktop Protocol Client * RDP Licensing * * Copyright 2011 Marc-Andre Moreau * * 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. */ #ifndef __LICENSE_H #define __LICENSE_H typedef struct rdp_license rdpLicense; #include "rdp.h" #include "crypto.h" #include "certificate.h" #include #include #include /* Licensing Packet Types */ #define LICENSE_REQUEST 0x01 #define PLATFORM_CHALLENGE 0x02 #define NEW_LICENSE 0x03 #define UPGRADE_LICENSE 0x04 #define LICENSE_INFO 0x12 #define NEW_LICENSE_REQUEST 0x13 #define PLATFORM_CHALLENGE_RESPONSE 0x15 #define ERROR_ALERT 0xFF #define LICENSE_PKT_CS_MASK (LICENSE_INFO | NEW_LICENSE_REQUEST | PLATFORM_CHALLENGE_RESPONSE | ERROR_ALERT) #define LICENSE_PKT_SC_MASK (LICENSE_REQUEST | PLATFORM_CHALLENGE | NEW_LICENSE | UPGRADE_LICENSE | ERROR_ALERT) #define LICENSE_PKT_MASK (LICENSE_PKT_CS_MASK | LICENSE_PKT_SC_MASK) #define LICENSE_PREAMBLE_LENGTH 4 #define LICENSE_PACKET_HEADER_MAX_LENGTH (RDP_PACKET_HEADER_MAX_LENGTH + RDP_SECURITY_HEADER_LENGTH + LICENSE_PREAMBLE_LENGTH) /* Cryptographic Lengths */ #define CLIENT_RANDOM_LENGTH 32 #define SERVER_RANDOM_LENGTH 32 #define MASTER_SECRET_LENGTH 48 #define PREMASTER_SECRET_LENGTH 48 #define SESSION_KEY_BLOB_LENGTH 48 #define MAC_SALT_KEY_LENGTH 16 #define LICENSING_ENCRYPTION_KEY_LENGTH 16 #define HWID_PLATFORM_ID_LENGTH 4 #define HWID_UNIQUE_DATA_LENGTH 16 #define HWID_LENGTH 20 #define LICENSING_PADDING_SIZE 8 /* Licensing Preamble Flags */ #define PREAMBLE_VERSION_2_0 0x02 #define PREAMBLE_VERSION_3_0 0x03 #define LicenseProtocolVersionMask 0x0F #define EXTENDED_ERROR_MSG_SUPPORTED 0x80 /* Licensing Binary Blob Types */ #define BB_ANY_BLOB 0x0000 #define BB_DATA_BLOB 0x0001 #define BB_RANDOM_BLOB 0x0002 #define BB_CERTIFICATE_BLOB 0x0003 #define BB_ERROR_BLOB 0x0004 #define BB_ENCRYPTED_DATA_BLOB 0x0009 #define BB_KEY_EXCHG_ALG_BLOB 0x000D #define BB_SCOPE_BLOB 0x000E #define BB_CLIENT_USER_NAME_BLOB 0x000F #define BB_CLIENT_MACHINE_NAME_BLOB 0x0010 /* Key Exchange Algorithms */ #define KEY_EXCHANGE_ALG_RSA 0x00000001 /* Licensing Error Codes */ #define ERR_INVALID_SERVER_CERTIFICATE 0x00000001 #define ERR_NO_LICENSE 0x00000002 #define ERR_INVALID_MAC 0x00000003 #define ERR_INVALID_SCOPE 0x00000004 #define ERR_NO_LICENSE_SERVER 0x00000006 #define STATUS_VALID_CLIENT 0x00000007 #define ERR_INVALID_CLIENT 0x00000008 #define ERR_INVALID_PRODUCT_ID 0x0000000B #define ERR_INVALID_MESSAGE_LENGTH 0x0000000C /* Licensing State Transition Codes */ #define ST_TOTAL_ABORT 0x00000001 #define ST_NO_TRANSITION 0x00000002 #define ST_RESET_PHASE_TO_START 0x00000003 #define ST_RESEND_LAST_MESSAGE 0x00000004 typedef struct { uint32 dwVersion; uint32 cbCompanyName; uint8* pbCompanyName; uint32 cbProductId; uint8* pbProductId; } PRODUCT_INFO; typedef struct { uint16 type; uint16 length; uint8* data; } LICENSE_BLOB; typedef struct { uint32 count; LICENSE_BLOB* array; } SCOPE_LIST; typedef enum { LICENSE_STATE_AWAIT, LICENSE_STATE_PROCESS, LICENSE_STATE_ABORTED, LICENSE_STATE_COMPLETED } LICENSE_STATE; struct rdp_license { LICENSE_STATE state; struct rdp_rdp* rdp; struct rdp_certificate* certificate; uint8 hwid[HWID_LENGTH]; uint8 modulus[MODULUS_MAX_SIZE]; uint8 exponent[EXPONENT_MAX_SIZE]; uint8 client_random[CLIENT_RANDOM_LENGTH]; uint8 server_random[SERVER_RANDOM_LENGTH]; uint8 master_secret[MASTER_SECRET_LENGTH]; uint8 premaster_secret[PREMASTER_SECRET_LENGTH]; uint8 session_key_blob[SESSION_KEY_BLOB_LENGTH]; uint8 mac_salt_key[MAC_SALT_KEY_LENGTH]; uint8 licensing_encryption_key[LICENSING_ENCRYPTION_KEY_LENGTH]; PRODUCT_INFO* product_info; LICENSE_BLOB* error_info; LICENSE_BLOB* key_exchange_list; LICENSE_BLOB* server_certificate; LICENSE_BLOB* client_user_name; LICENSE_BLOB* client_machine_name; LICENSE_BLOB* platform_challenge; LICENSE_BLOB* encrypted_premaster_secret; LICENSE_BLOB* encrypted_platform_challenge; LICENSE_BLOB* encrypted_hwid; SCOPE_LIST* scope_list; }; boolean license_recv(rdpLicense* license, STREAM* s); boolean license_send(rdpLicense* license, STREAM* s, uint8 type); STREAM* license_send_stream_init(rdpLicense* license); void license_generate_randoms(rdpLicense* license); void license_generate_keys(rdpLicense* license); void license_generate_hwid(rdpLicense* license); void license_encrypt_premaster_secret(rdpLicense* license); void license_decrypt_platform_challenge(rdpLicense* license); PRODUCT_INFO* license_new_product_info(); void license_free_product_info(PRODUCT_INFO* productInfo); void license_read_product_info(STREAM* s, PRODUCT_INFO* productInfo); LICENSE_BLOB* license_new_binary_blob(uint16 type); void license_free_binary_blob(LICENSE_BLOB* blob); void license_read_binary_blob(STREAM* s, LICENSE_BLOB* blob); void license_write_binary_blob(STREAM* s, LICENSE_BLOB* blob); SCOPE_LIST* license_new_scope_list(); void license_free_scope_list(SCOPE_LIST* scopeList); void license_read_scope_list(STREAM* s, SCOPE_LIST* scopeList); void license_read_license_request_packet(rdpLicense* license, STREAM* s); void license_read_platform_challenge_packet(rdpLicense* license, STREAM* s); void license_read_new_license_packet(rdpLicense* license, STREAM* s); void license_read_upgrade_license_packet(rdpLicense* license, STREAM* s); void license_read_error_alert_packet(rdpLicense* license, STREAM* s); void license_write_new_license_request_packet(rdpLicense* license, STREAM* s); void license_send_new_license_request_packet(rdpLicense* license); void license_write_platform_challenge_response_packet(rdpLicense* license, STREAM* s, uint8* mac_data); void license_send_platform_challenge_response_packet(rdpLicense* license); boolean license_send_valid_client_error_packet(rdpLicense* license); rdpLicense* license_new(rdpRdp* rdp); void license_free(rdpLicense* license); #ifdef WITH_DEBUG_LICENSE #define DEBUG_LICENSE(fmt, ...) DEBUG_CLASS(LICENSE, fmt, ## __VA_ARGS__) #else #define DEBUG_LICENSE(fmt, ...) DEBUG_NULL(fmt, ## __VA_ARGS__) #endif #endif /* __LICENSE_H */ FreeRDP-1.0.2/libfreerdp-core/listener.c000066400000000000000000000122161207112532300177740ustar00rootroot00000000000000/** * FreeRDP: A Remote Desktop Protocol client. * RDP Server Listener * * Copyright 2011 Vic Lee * * 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. */ #include #include #include #include #include #ifndef _WIN32 #include #include #include #include #include #include #include #else #define close(_fd) closesocket(_fd) #endif #include "listener.h" static boolean freerdp_listener_open(freerdp_listener* instance, const char* bind_address, uint16 port) { rdpListener* listener = (rdpListener*)instance->listener; int status; int sockfd; char servname[10]; struct addrinfo hints = { 0 }; struct addrinfo* res; struct addrinfo* ai; int option_value; void* sin_addr; char buf[50]; #ifdef _WIN32 u_long arg; #endif hints.ai_family = AF_UNSPEC; hints.ai_socktype = SOCK_STREAM; if (bind_address == NULL) hints.ai_flags = AI_PASSIVE; snprintf(servname, sizeof(servname), "%d", port); status = getaddrinfo(bind_address, servname, &hints, &res); if (status != 0) { perror("getaddrinfo"); return false; } for (ai = res; ai && listener->num_sockfds < 5; ai = ai->ai_next) { if (ai->ai_family != AF_INET && ai->ai_family != AF_INET6) continue; sockfd = socket(ai->ai_family, ai->ai_socktype, ai->ai_protocol); if (sockfd == -1) { perror("socket"); continue; } option_value = 1; if (setsockopt(sockfd, SOL_SOCKET, SO_REUSEADDR, (void*) &option_value, sizeof(option_value)) == -1) perror("setsockopt"); #ifndef _WIN32 fcntl(sockfd, F_SETFL, O_NONBLOCK); #else arg = 1; ioctlsocket(sockfd, FIONBIO, &arg); #endif status = bind(sockfd, ai->ai_addr, ai->ai_addrlen); if (status != 0) { perror("bind"); close(sockfd); continue; } status = listen(sockfd, 10); if (status != 0) { perror("listen"); close(sockfd); continue; } listener->sockfds[listener->num_sockfds++] = sockfd; if (ai->ai_family == AF_INET) sin_addr = &(((struct sockaddr_in*)ai->ai_addr)->sin_addr); else sin_addr = &(((struct sockaddr_in6*)ai->ai_addr)->sin6_addr); printf("Listening on %s port %s.\n", inet_ntop(ai->ai_family, sin_addr, buf, sizeof(buf)), servname); } freeaddrinfo(res); return (listener->num_sockfds > 0 ? true : false); } static void freerdp_listener_close(freerdp_listener* instance) { int i; rdpListener* listener = (rdpListener*)instance->listener; for (i = 0; i < listener->num_sockfds; i++) { close(listener->sockfds[i]); } listener->num_sockfds = 0; } static boolean freerdp_listener_get_fds(freerdp_listener* instance, void** rfds, int* rcount) { rdpListener* listener = (rdpListener*)instance->listener; int i; if (listener->num_sockfds < 1) return false; for (i = 0; i < listener->num_sockfds; i++) { rfds[*rcount] = (void*)(long)(listener->sockfds[i]); (*rcount)++; } return true; } static boolean freerdp_listener_check_fds(freerdp_listener* instance) { rdpListener* listener = (rdpListener*)instance->listener; struct sockaddr_storage peer_addr; socklen_t peer_addr_size; int peer_sockfd; int i; freerdp_peer* client; void* sin_addr; if (listener->num_sockfds < 1) return false; for (i = 0; i < listener->num_sockfds; i++) { peer_addr_size = sizeof(peer_addr); peer_sockfd = accept(listener->sockfds[i], (struct sockaddr *)&peer_addr, &peer_addr_size); if (peer_sockfd == -1) { #ifdef _WIN32 int wsa_error = WSAGetLastError(); /* No data available */ if (wsa_error == WSAEWOULDBLOCK) continue; #else if (errno == EAGAIN || errno == EWOULDBLOCK) continue; #endif perror("accept"); return false; } client = freerdp_peer_new(peer_sockfd); if (peer_addr.ss_family == AF_INET) sin_addr = &(((struct sockaddr_in*)&peer_addr)->sin_addr); else sin_addr = &(((struct sockaddr_in6*)&peer_addr)->sin6_addr); inet_ntop(peer_addr.ss_family, sin_addr, client->hostname, sizeof(client->hostname)); IFCALL(instance->PeerAccepted, instance, client); } return true; } freerdp_listener* freerdp_listener_new(void) { freerdp_listener* instance; rdpListener* listener; instance = xnew(freerdp_listener); instance->Open = freerdp_listener_open; instance->GetFileDescriptor = freerdp_listener_get_fds; instance->CheckFileDescriptor = freerdp_listener_check_fds; instance->Close = freerdp_listener_close; listener = xnew(rdpListener); listener->instance = instance; instance->listener = (void*)listener; return instance; } void freerdp_listener_free(freerdp_listener* instance) { rdpListener* listener; listener = (rdpListener*)instance->listener; xfree(listener); xfree(instance); } FreeRDP-1.0.2/libfreerdp-core/listener.h000066400000000000000000000016021207112532300177760ustar00rootroot00000000000000/** * FreeRDP: A Remote Desktop Protocol client. * RDP Server Listener * * Copyright 2011 Vic Lee * * 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. */ #ifndef __LISTENER_H #define __LISTENER_H typedef struct rdp_listener rdpListener; #include "rdp.h" #include struct rdp_listener { freerdp_listener* instance; int sockfds[5]; int num_sockfds; }; #endif FreeRDP-1.0.2/libfreerdp-core/mcs.c000066400000000000000000000473371207112532300167450ustar00rootroot00000000000000/** * FreeRDP: A Remote Desktop Protocol Client * T.125 Multipoint Communication Service (MCS) Protocol * * Copyright 2011 Marc-Andre Moreau * * 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. */ #include "gcc.h" #include "mcs.h" #include "tpdu.h" #include "tpkt.h" /** * T.125 MCS is defined in: * * http://www.itu.int/rec/T-REC-T.125-199802-I/ * ITU-T T.125 Multipoint Communication Service Protocol Specification */ /** * Connect-Initial ::= [APPLICATION 101] IMPLICIT SEQUENCE * { * callingDomainSelector OCTET_STRING, * calledDomainSelector OCTET_STRING, * upwardFlag BOOLEAN, * targetParameters DomainParameters, * minimumParameters DomainParameters, * maximumParameters DomainParameters, * userData OCTET_STRING * } * * DomainParameters ::= SEQUENCE * { * maxChannelIds INTEGER (0..MAX), * maxUserIds INTEGER (0..MAX), * maxTokenIds INTEGER (0..MAX), * numPriorities INTEGER (0..MAX), * minThroughput INTEGER (0..MAX), * maxHeight INTEGER (0..MAX), * maxMCSPDUsize INTEGER (0..MAX), * protocolVersion INTEGER (0..MAX) * } * * Connect-Response ::= [APPLICATION 102] IMPLICIT SEQUENCE * { * result Result, * calledConnectId INTEGER (0..MAX), * domainParameters DomainParameters, * userData OCTET_STRING * } * * Result ::= ENUMERATED * { * rt-successful (0), * rt-domain-merging (1), * rt-domain-not-hierarchical (2), * rt-no-such-channel (3), * rt-no-such-domain (4), * rt-no-such-user (5), * rt-not-admitted (6), * rt-other-user-id (7), * rt-parameters-unacceptable (8), * rt-token-not-available (9), * rt-token-not-possessed (10), * rt-too-many-channels (11), * rt-too-many-tokens (12), * rt-too-many-users (13), * rt-unspecified-failure (14), * rt-user-rejected (15) * } * * ErectDomainRequest ::= [APPLICATION 1] IMPLICIT SEQUENCE * { * subHeight INTEGER (0..MAX), * subInterval INTEGER (0..MAX) * } * * AttachUserRequest ::= [APPPLICATION 10] IMPLICIT SEQUENCE * { * } * * AttachUserConfirm ::= [APPLICATION 11] IMPLICIT SEQUENCE * { * result Result, * initiator UserId OPTIONAL * } * * ChannelJoinRequest ::= [APPLICATION 14] IMPLICIT SEQUENCE * { * initiator UserId, * channelId ChannelId * } * * ChannelJoinConfirm ::= [APPLICATION 15] IMPLICIT SEQUENCE * { * result Result, * initiator UserId, * requested ChannelId, * channelId ChannelId OPTIONAL * } * * SendDataRequest ::= [APPLICATION 25] IMPLICIT SEQUENCE * { * initiator UserId, * channelId ChannelId, * dataPriority DataPriority, * segmentation Segmentation, * userData OCTET_STRING * } * * DataPriority ::= CHOICE * { * top NULL, * high NULL, * medium NULL, * low NULL, * ... * } * * Segmentation ::= BIT_STRING * { * begin (0), * end (1) * } (SIZE(2)) * * SendDataIndication ::= SEQUENCE * { * initiator UserId, * channelId ChannelId, * reliability BOOLEAN, * domainReferenceID INTEGER (0..65535) OPTIONAL, * dataPriority DataPriority, * segmentation Segmentation, * userData OCTET_STRING, * totalDataSize INTEGER OPTIONAL, * nonStandard SEQUENCE OF NonStandardParameter OPTIONAL, * ... * } * */ static const uint8 callingDomainSelector[1] = "\x01"; static const uint8 calledDomainSelector[1] = "\x01"; /* static const char* const mcs_result_enumerated[] = { "rt-successful", "rt-domain-merging", "rt-domain-not-hierarchical", "rt-no-such-channel", "rt-no-such-domain", "rt-no-such-user", "rt-not-admitted", "rt-other-user-id", "rt-parameters-unacceptable", "rt-token-not-available", "rt-token-not-possessed", "rt-too-many-channels", "rt-too-many-tokens", "rt-too-many-users", "rt-unspecified-failure", "rt-user-rejected" }; */ /** * Read a DomainMCSPDU header. * @param s stream * @param domainMCSPDU DomainMCSPDU type * @param length TPKT length * @return */ boolean mcs_read_domain_mcspdu_header(STREAM* s, enum DomainMCSPDU* domainMCSPDU, uint16* length) { uint8 choice; enum DomainMCSPDU MCSPDU; *length = tpkt_read_header(s); if (tpdu_read_data(s) == 0) return false; MCSPDU = *domainMCSPDU; per_read_choice(s, &choice); *domainMCSPDU = (choice >> 2); if (*domainMCSPDU != MCSPDU) return false; return true; } /** * Write a DomainMCSPDU header. * @param s stream * @param domainMCSPDU DomainMCSPDU type * @param length TPKT length */ void mcs_write_domain_mcspdu_header(STREAM* s, enum DomainMCSPDU domainMCSPDU, uint16 length, uint8 options) { tpkt_write_header(s, length); tpdu_write_data(s); per_write_choice(s, (domainMCSPDU << 2) | options); } /** * Initialize MCS Domain Parameters. * @param domainParameters domain parameters * @param maxChannelIds max channel ids * @param maxUserIds max user ids * @param maxTokenIds max token ids * @param maxMCSPDUsize max MCS PDU size */ static void mcs_init_domain_parameters(DomainParameters* domainParameters, uint32 maxChannelIds, uint32 maxUserIds, uint32 maxTokenIds, uint32 maxMCSPDUsize) { domainParameters->maxChannelIds = maxChannelIds; domainParameters->maxUserIds = maxUserIds; domainParameters->maxTokenIds = maxTokenIds; domainParameters->maxMCSPDUsize = maxMCSPDUsize; domainParameters->numPriorities = 1; domainParameters->minThroughput = 0; domainParameters->maxHeight = 1; domainParameters->protocolVersion = 2; } /** * Read MCS Domain Parameters. * @param s stream * @param domainParameters domain parameters */ boolean mcs_read_domain_parameters(STREAM* s, DomainParameters* domainParameters) { int length; ber_read_sequence_tag(s, &length); ber_read_integer(s, &(domainParameters->maxChannelIds)); ber_read_integer(s, &(domainParameters->maxUserIds)); ber_read_integer(s, &(domainParameters->maxTokenIds)); ber_read_integer(s, &(domainParameters->numPriorities)); ber_read_integer(s, &(domainParameters->minThroughput)); ber_read_integer(s, &(domainParameters->maxHeight)); ber_read_integer(s, &(domainParameters->maxMCSPDUsize)); ber_read_integer(s, &(domainParameters->protocolVersion)); return true; } /** * Write MCS Domain Parameters. * @param s stream * @param domainParameters domain parameters */ void mcs_write_domain_parameters(STREAM* s, DomainParameters* domainParameters) { int length; STREAM* tmps; tmps = stream_new(stream_get_size(s)); ber_write_integer(tmps, domainParameters->maxChannelIds); ber_write_integer(tmps, domainParameters->maxUserIds); ber_write_integer(tmps, domainParameters->maxTokenIds); ber_write_integer(tmps, domainParameters->numPriorities); ber_write_integer(tmps, domainParameters->minThroughput); ber_write_integer(tmps, domainParameters->maxHeight); ber_write_integer(tmps, domainParameters->maxMCSPDUsize); ber_write_integer(tmps, domainParameters->protocolVersion); length = stream_get_length(tmps); ber_write_sequence_tag(s, length); stream_write(s, stream_get_head(tmps), length); stream_free(tmps); } /** * Print MCS Domain Parameters. * @param domainParameters domain parameters */ void mcs_print_domain_parameters(DomainParameters* domainParameters) { printf("DomainParameters {\n"); printf("\tmaxChannelIds:%d\n", domainParameters->maxChannelIds); printf("\tmaxUserIds:%d\n", domainParameters->maxUserIds); printf("\tmaxTokenIds:%d\n", domainParameters->maxTokenIds); printf("\tnumPriorities:%d\n", domainParameters->numPriorities); printf("\tminThroughput:%d\n", domainParameters->minThroughput); printf("\tmaxHeight:%d\n", domainParameters->maxHeight); printf("\tmaxMCSPDUsize:%d\n", domainParameters->maxMCSPDUsize); printf("\tprotocolVersion:%d\n", domainParameters->protocolVersion); printf("}\n"); } /** * Read an MCS Connect Initial PDU.\n * @msdn{cc240508} * @param mcs MCS module * @param s stream */ boolean mcs_recv_connect_initial(rdpMcs* mcs, STREAM* s) { int length; boolean upwardFlag; tpkt_read_header(s); if (tpdu_read_data(s) == 0) return false; if (!ber_read_application_tag(s, MCS_TYPE_CONNECT_INITIAL, &length)) return false; /* callingDomainSelector (OCTET_STRING) */ if (!ber_read_octet_string(s, &length)) return false; stream_seek(s, length); /* calledDomainSelector (OCTET_STRING) */ if (!ber_read_octet_string(s, &length)) return false; stream_seek(s, length); /* upwardFlag (BOOLEAN) */ if (!ber_read_boolean(s, &upwardFlag)) return false; /* targetParameters (DomainParameters) */ mcs_read_domain_parameters(s, &mcs->targetParameters); /* minimumParameters (DomainParameters) */ mcs_read_domain_parameters(s, &mcs->minimumParameters); /* maximumParameters (DomainParameters) */ mcs_read_domain_parameters(s, &mcs->maximumParameters); if (!ber_read_octet_string(s, &length)) return false; if (!gcc_read_conference_create_request(s, mcs->transport->settings)) return false; return true; } /** * Write an MCS Connect Initial PDU.\n * @msdn{cc240508} * @param s stream * @param mcs MCS module * @param user_data GCC Conference Create Request */ void mcs_write_connect_initial(STREAM* s, rdpMcs* mcs, STREAM* user_data) { int length; STREAM* tmps; tmps = stream_new(stream_get_size(s)); /* callingDomainSelector (OCTET_STRING) */ ber_write_octet_string(tmps, callingDomainSelector, sizeof(callingDomainSelector)); /* calledDomainSelector (OCTET_STRING) */ ber_write_octet_string(tmps, calledDomainSelector, sizeof(calledDomainSelector)); /* upwardFlag (BOOLEAN) */ ber_write_boolean(tmps, true); /* targetParameters (DomainParameters) */ mcs_write_domain_parameters(tmps, &mcs->targetParameters); /* minimumParameters (DomainParameters) */ mcs_write_domain_parameters(tmps, &mcs->minimumParameters); /* maximumParameters (DomainParameters) */ mcs_write_domain_parameters(tmps, &mcs->maximumParameters); /* userData (OCTET_STRING) */ ber_write_octet_string(tmps, user_data->data, stream_get_length(user_data)); length = stream_get_length(tmps); /* Connect-Initial (APPLICATION 101, IMPLICIT SEQUENCE) */ ber_write_application_tag(s, MCS_TYPE_CONNECT_INITIAL, length); stream_write(s, stream_get_head(tmps), length); stream_free(tmps); } /** * Write an MCS Connect Response PDU.\n * @msdn{cc240508} * @param s stream * @param mcs MCS module * @param user_data GCC Conference Create Response */ void mcs_write_connect_response(STREAM* s, rdpMcs* mcs, STREAM* user_data) { int length; STREAM* tmps; tmps = stream_new(stream_get_size(s)); ber_write_enumerated(tmps, 0, MCS_Result_enum_length); ber_write_integer(tmps, 0); /* calledConnectId */ mcs->domainParameters = mcs->targetParameters; mcs_write_domain_parameters(tmps, &(mcs->domainParameters)); /* userData (OCTET_STRING) */ ber_write_octet_string(tmps, user_data->data, stream_get_length(user_data)); length = stream_get_length(tmps); ber_write_application_tag(s, MCS_TYPE_CONNECT_RESPONSE, length); stream_write(s, stream_get_head(tmps), length); stream_free(tmps); } /** * Send MCS Connect Initial.\n * @msdn{cc240508} * @param mcs mcs module */ boolean mcs_send_connect_initial(rdpMcs* mcs) { STREAM* s; int length; uint8 *bm, *em; STREAM* gcc_CCrq; STREAM* client_data; int status; client_data = stream_new(512); gcc_write_client_data_blocks(client_data, mcs->transport->settings); gcc_CCrq = stream_new(512); gcc_write_conference_create_request(gcc_CCrq, client_data); length = stream_get_length(gcc_CCrq) + 7; s = transport_send_stream_init(mcs->transport, 1024); stream_get_mark(s, bm); stream_seek(s, 7); mcs_write_connect_initial(s, mcs, gcc_CCrq); stream_get_mark(s, em); length = (em - bm); stream_set_mark(s, bm); tpkt_write_header(s, length); tpdu_write_data(s); stream_set_mark(s, em); status = transport_write(mcs->transport, s); stream_free(gcc_CCrq); stream_free(client_data); return (status < 0 ? false : true); } /** * Read MCS Connect Response.\n * @msdn{cc240501} * @param mcs mcs module */ boolean mcs_recv_connect_response(rdpMcs* mcs, STREAM* s) { int length; uint8 result; uint32 calledConnectId; tpkt_read_header(s); if (tpdu_read_data(s) == 0) return false; ber_read_application_tag(s, MCS_TYPE_CONNECT_RESPONSE, &length); ber_read_enumerated(s, &result, MCS_Result_enum_length); ber_read_integer(s, &calledConnectId); if (!mcs_read_domain_parameters(s, &(mcs->domainParameters))) return false; ber_read_octet_string(s, &length); if (!gcc_read_conference_create_response(s, mcs->transport->settings)) { printf("mcs_recv_connect_response: gcc_read_conference_create_response failed\n"); return false; } return true; } /** * Send MCS Connect Response.\n * @msdn{cc240501} * @param mcs mcs module */ boolean mcs_send_connect_response(rdpMcs* mcs) { STREAM* s; int length; uint8 *bm, *em; STREAM* gcc_CCrsp; STREAM* server_data; server_data = stream_new(512); gcc_write_server_data_blocks(server_data, mcs->transport->settings); gcc_CCrsp = stream_new(512); gcc_write_conference_create_response(gcc_CCrsp, server_data); length = stream_get_length(gcc_CCrsp) + 7; s = transport_send_stream_init(mcs->transport, 1024); stream_get_mark(s, bm); stream_seek(s, 7); mcs_write_connect_response(s, mcs, gcc_CCrsp); stream_get_mark(s, em); length = (em - bm); stream_set_mark(s, bm); tpkt_write_header(s, length); tpdu_write_data(s); stream_set_mark(s, em); transport_write(mcs->transport, s); stream_free(gcc_CCrsp); stream_free(server_data); return true; } /** * Read MCS Erect Domain Request.\n * @msdn{cc240523} * @param mcs * @param s stream */ boolean mcs_recv_erect_domain_request(rdpMcs* mcs, STREAM* s) { uint16 length; enum DomainMCSPDU MCSPDU; MCSPDU = DomainMCSPDU_ErectDomainRequest; if (!mcs_read_domain_mcspdu_header(s, &MCSPDU, &length)) return false; return true; } /** * Send MCS Erect Domain Request.\n * @msdn{cc240523} * @param mcs */ boolean mcs_send_erect_domain_request(rdpMcs* mcs) { STREAM* s; uint16 length = 12; s = transport_send_stream_init(mcs->transport, length); mcs_write_domain_mcspdu_header(s, DomainMCSPDU_ErectDomainRequest, length, 0); per_write_integer(s, 0); /* subHeight (INTEGER) */ per_write_integer(s, 0); /* subInterval (INTEGER) */ if (transport_write(mcs->transport, s) < 0) return false; return true; } /** * Read MCS Attach User Request.\n * @msdn{cc240524} * @param mcs mcs module * @param s stream */ boolean mcs_recv_attach_user_request(rdpMcs* mcs, STREAM* s) { uint16 length; enum DomainMCSPDU MCSPDU; MCSPDU = DomainMCSPDU_AttachUserRequest; if (!mcs_read_domain_mcspdu_header(s, &MCSPDU, &length)) return false; return true; } /** * Send MCS Attach User Request.\n * @msdn{cc240524} * @param mcs mcs module */ boolean mcs_send_attach_user_request(rdpMcs* mcs) { STREAM* s; uint16 length = 8; s = transport_send_stream_init(mcs->transport, length); mcs_write_domain_mcspdu_header(s, DomainMCSPDU_AttachUserRequest, length, 0); if (transport_write(mcs->transport, s) < 0) return false; return true; } /** * Read MCS Attach User Confirm.\n * @msdn{cc240525} * @param mcs mcs module */ boolean mcs_recv_attach_user_confirm(rdpMcs* mcs, STREAM* s) { uint16 length; uint8 result; enum DomainMCSPDU MCSPDU; MCSPDU = DomainMCSPDU_AttachUserConfirm; if (!mcs_read_domain_mcspdu_header(s, &MCSPDU, &length)) return false; per_read_enumerated(s, &result, MCS_Result_enum_length); /* result */ per_read_integer16(s, &(mcs->user_id), MCS_BASE_CHANNEL_ID); /* initiator (UserId) */ return true; } /** * Send MCS Attach User Confirm.\n * @msdn{cc240525} * @param mcs mcs module */ boolean mcs_send_attach_user_confirm(rdpMcs* mcs) { STREAM* s; uint16 length = 11; s = transport_send_stream_init(mcs->transport, length); mcs_write_domain_mcspdu_header(s, DomainMCSPDU_AttachUserConfirm, length, 2); per_write_enumerated(s, 0, MCS_Result_enum_length); /* result */ mcs->user_id = 1002; per_write_integer16(s, mcs->user_id, MCS_BASE_CHANNEL_ID); /* initiator (UserId) */ transport_write(mcs->transport, s); return true; } /** * Read MCS Channel Join Request.\n * @msdn{cc240526} * @param mcs mcs module * @param s stream */ boolean mcs_recv_channel_join_request(rdpMcs* mcs, STREAM* s, uint16* channel_id) { uint16 length; enum DomainMCSPDU MCSPDU; uint16 user_id; MCSPDU = DomainMCSPDU_ChannelJoinRequest; if (!mcs_read_domain_mcspdu_header(s, &MCSPDU, &length)) return false; if (!per_read_integer16(s, &user_id, MCS_BASE_CHANNEL_ID)) return false; if (user_id != mcs->user_id) return false; if (!per_read_integer16(s, channel_id, 0)) return false; return true; } /** * Send MCS Channel Join Request.\n * @msdn{cc240526} * @param mcs mcs module * @param channel_id channel id */ boolean mcs_send_channel_join_request(rdpMcs* mcs, uint16 channel_id) { STREAM* s; uint16 length = 12; s = transport_send_stream_init(mcs->transport, 12); mcs_write_domain_mcspdu_header(s, DomainMCSPDU_ChannelJoinRequest, length, 0); per_write_integer16(s, mcs->user_id, MCS_BASE_CHANNEL_ID); per_write_integer16(s, channel_id, 0); if (transport_write(mcs->transport, s) < 0) return false; return true; } /** * Read MCS Channel Join Confirm.\n * @msdn{cc240527} * @param mcs mcs module */ boolean mcs_recv_channel_join_confirm(rdpMcs* mcs, STREAM* s, uint16* channel_id) { uint16 length; uint8 result; uint16 initiator; uint16 requested; enum DomainMCSPDU MCSPDU; MCSPDU = DomainMCSPDU_ChannelJoinConfirm; if (!mcs_read_domain_mcspdu_header(s, &MCSPDU, &length)) return false; per_read_enumerated(s, &result, MCS_Result_enum_length); /* result */ per_read_integer16(s, &initiator, MCS_BASE_CHANNEL_ID); /* initiator (UserId) */ per_read_integer16(s, &requested, 0); /* requested (ChannelId) */ per_read_integer16(s, channel_id, 0); /* channelId */ return true; } /** * Send MCS Channel Join Confirm.\n * @msdn{cc240527} * @param mcs mcs module */ boolean mcs_send_channel_join_confirm(rdpMcs* mcs, uint16 channel_id) { STREAM* s; uint16 length = 15; s = transport_send_stream_init(mcs->transport, 15); mcs_write_domain_mcspdu_header(s, DomainMCSPDU_ChannelJoinConfirm, length, 2); per_write_enumerated(s, 0, MCS_Result_enum_length); /* result */ per_write_integer16(s, mcs->user_id, MCS_BASE_CHANNEL_ID); /* initiator (UserId) */ per_write_integer16(s, channel_id, 0); /* requested (ChannelId) */ per_write_integer16(s, channel_id, 0); /* channelId */ transport_write(mcs->transport, s); return true; } /** * Send MCS Disconnect Provider Ultimatum PDU.\n * @param mcs mcs module */ boolean mcs_send_disconnect_provider_ultimatum(rdpMcs* mcs) { STREAM* s; uint16 length = 9; s = transport_send_stream_init(mcs->transport, 9); mcs_write_domain_mcspdu_header(s, DomainMCSPDU_DisconnectProviderUltimatum, length, 1); per_write_enumerated(s, 0, 0); /* reason */ transport_write(mcs->transport, s); return true; } /** * Instantiate new MCS module. * @param transport transport * @return new MCS module */ rdpMcs* mcs_new(rdpTransport* transport) { rdpMcs* mcs; mcs = (rdpMcs*) xzalloc(sizeof(rdpMcs)); if (mcs != NULL) { mcs->transport = transport; mcs_init_domain_parameters(&mcs->targetParameters, 34, 2, 0, 0xFFFF); mcs_init_domain_parameters(&mcs->minimumParameters, 1, 1, 1, 0x420); mcs_init_domain_parameters(&mcs->maximumParameters, 0xFFFF, 0xFC17, 0xFFFF, 0xFFFF); } return mcs; } /** * Free MCS module. * @param mcs MCS module to be freed */ void mcs_free(rdpMcs* mcs) { if (mcs != NULL) { xfree(mcs); } } FreeRDP-1.0.2/libfreerdp-core/mcs.h000066400000000000000000000123341207112532300167370ustar00rootroot00000000000000/** * FreeRDP: A Remote Desktop Protocol Client * T.125 Multipoint Communication Service (MCS) Protocol * * Copyright 2011 Marc-Andre Moreau * * 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. */ #ifndef __MCS_H #define __MCS_H #include "ber.h" #include "transport.h" #include #include #define MCS_BASE_CHANNEL_ID 1001 #define MCS_GLOBAL_CHANNEL_ID 1003 enum MCS_Result { MCS_Result_successful = 0, MCS_Result_domain_merging = 1, MCS_Result_domain_not_hierarchical = 2, MCS_Result_no_such_channel = 3, MCS_Result_no_such_domain = 4, MCS_Result_no_such_user = 5, MCS_Result_not_admitted = 6, MCS_Result_other_user_id = 7, MCS_Result_parameters_unacceptable = 8, MCS_Result_token_not_available = 9, MCS_Result_token_not_possessed = 10, MCS_Result_too_many_channels = 11, MCS_Result_too_many_tokens = 12, MCS_Result_too_many_users = 13, MCS_Result_unspecified_failure = 14, MCS_Result_user_rejected = 15, MCS_Result_enum_length = 16 }; enum DomainMCSPDU { DomainMCSPDU_PlumbDomainIndication = 0, DomainMCSPDU_ErectDomainRequest = 1, DomainMCSPDU_MergeChannelsRequest = 2, DomainMCSPDU_MergeChannelsConfirm = 3, DomainMCSPDU_PurgeChannelsIndication = 4, DomainMCSPDU_MergeTokensRequest = 5, DomainMCSPDU_MergeTokensConfirm = 6, DomainMCSPDU_PurgeTokensIndication = 7, DomainMCSPDU_DisconnectProviderUltimatum = 8, DomainMCSPDU_RejectMCSPDUUltimatum = 9, DomainMCSPDU_AttachUserRequest = 10, DomainMCSPDU_AttachUserConfirm = 11, DomainMCSPDU_DetachUserRequest = 12, DomainMCSPDU_DetachUserIndication = 13, DomainMCSPDU_ChannelJoinRequest = 14, DomainMCSPDU_ChannelJoinConfirm = 15, DomainMCSPDU_ChannelLeaveRequest = 16, DomainMCSPDU_ChannelConveneRequest = 17, DomainMCSPDU_ChannelConveneConfirm = 18, DomainMCSPDU_ChannelDisbandRequest = 19, DomainMCSPDU_ChannelDisbandIndication = 20, DomainMCSPDU_ChannelAdmitRequest = 21, DomainMCSPDU_ChannelAdmitIndication = 22, DomainMCSPDU_ChannelExpelRequest = 23, DomainMCSPDU_ChannelExpelIndication = 24, DomainMCSPDU_SendDataRequest = 25, DomainMCSPDU_SendDataIndication = 26, DomainMCSPDU_UniformSendDataRequest = 27, DomainMCSPDU_UniformSendDataIndication = 28, DomainMCSPDU_TokenGrabRequest = 29, DomainMCSPDU_TokenGrabConfirm = 30, DomainMCSPDU_TokenInhibitRequest = 31, DomainMCSPDU_TokenInhibitConfirm = 32, DomainMCSPDU_TokenGiveRequest = 33, DomainMCSPDU_TokenGiveIndication = 34, DomainMCSPDU_TokenGiveResponse = 35, DomainMCSPDU_TokenGiveConfirm = 36, DomainMCSPDU_TokenPleaseRequest = 37, DomainMCSPDU_TokenPleaseConfirm = 38, DomainMCSPDU_TokenReleaseRequest = 39, DomainMCSPDU_TokenReleaseConfirm = 40, DomainMCSPDU_TokenTestRequest = 41, DomainMCSPDU_TokenTestConfirm = 42, DomainMCSPDU_enum_length = 43 }; typedef struct { uint32 maxChannelIds; uint32 maxUserIds; uint32 maxTokenIds; uint32 numPriorities; uint32 minThroughput; uint32 maxHeight; uint32 maxMCSPDUsize; uint32 protocolVersion; } DomainParameters; struct rdp_mcs { uint16 user_id; struct rdp_transport* transport; DomainParameters domainParameters; DomainParameters targetParameters; DomainParameters minimumParameters; DomainParameters maximumParameters; boolean user_channel_joined; boolean global_channel_joined; }; typedef struct rdp_mcs rdpMcs; #define MCS_SEND_DATA_HEADER_MAX_LENGTH 8 #define MCS_TYPE_CONNECT_INITIAL 0x65 #define MCS_TYPE_CONNECT_RESPONSE 0x66 void mcs_write_connect_initial(STREAM* s, rdpMcs* mcs, STREAM* user_data); void mcs_write_connect_response(STREAM* s, rdpMcs* mcs, STREAM* user_data); boolean mcs_recv_connect_initial(rdpMcs* mcs, STREAM* s); boolean mcs_send_connect_initial(rdpMcs* mcs); boolean mcs_recv_connect_response(rdpMcs* mcs, STREAM* s); boolean mcs_send_connect_response(rdpMcs* mcs); boolean mcs_recv_erect_domain_request(rdpMcs* mcs, STREAM* s); boolean mcs_send_erect_domain_request(rdpMcs* mcs); boolean mcs_recv_attach_user_request(rdpMcs* mcs, STREAM* s); boolean mcs_send_attach_user_request(rdpMcs* mcs); boolean mcs_recv_attach_user_confirm(rdpMcs* mcs, STREAM* s); boolean mcs_send_attach_user_confirm(rdpMcs* mcs); boolean mcs_recv_channel_join_request(rdpMcs* mcs, STREAM* s, uint16* channel_id); boolean mcs_send_channel_join_request(rdpMcs* mcs, uint16 channel_id); boolean mcs_recv_channel_join_confirm(rdpMcs* mcs, STREAM* s, uint16* channel_id); boolean mcs_send_channel_join_confirm(rdpMcs* mcs, uint16 channel_id); boolean mcs_send_disconnect_provider_ultimatum(rdpMcs* mcs); boolean mcs_read_domain_mcspdu_header(STREAM* s, enum DomainMCSPDU* domainMCSPDU, uint16* length); void mcs_write_domain_mcspdu_header(STREAM* s, enum DomainMCSPDU domainMCSPDU, uint16 length, uint8 options); rdpMcs* mcs_new(rdpTransport* transport); void mcs_free(rdpMcs* mcs); #endif /* __MCS_H */ FreeRDP-1.0.2/libfreerdp-core/mppc.c000066400000000000000000001012041207112532300171020ustar00rootroot00000000000000/** * FreeRDP: A Remote Desktop Protocol Client * Implements Microsoft Point to Point Compression (MPPC) protocol * * Copyright 2011 Laxmikant Rashinkar * * 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. */ #include "rdp.h" #if 0 static uint8 HuffLengthLEC[] = { 0x6, 0x6, 0x6, 0x6, 0x7, 0x7, 0x7, 0x7, 0x7, 0x7, 0x7, 0x7, 0x8, 0x8, 0x8, 0x8, 0x8, 0x8, 0x8, 0x9, 0x8, 0x9, 0x9, 0x9, 0x9, 0x8, 0x8, 0x9, 0x9, 0x9, 0x9, 0x9, 0x8, 0x9, 0x9, 0xa, 0x9, 0x9, 0x9, 0x9, 0x9, 0x9, 0x9, 0xa, 0x9, 0xa, 0xa, 0xa, 0x9, 0x9, 0x9, 0xa, 0x9, 0xa, 0xa, 0xa, 0x9, 0x9, 0xa, 0xa, 0x9, 0xa, 0x9, 0x9, 0x8, 0x9, 0x9, 0x9, 0x9, 0xa, 0xa, 0xa, 0x9, 0x9, 0xa, 0xa, 0xa, 0xa, 0xa, 0xa, 0x9, 0x9, 0xa, 0xa, 0xa, 0xa, 0xa, 0xa, 0xa, 0x9, 0xa, 0xa, 0xa, 0xa, 0xa, 0xa, 0x8, 0xa, 0xa, 0xa, 0xa, 0xa, 0xa, 0xa, 0xa, 0xa, 0xa, 0xa, 0xa, 0xa, 0xa, 0xa, 0x9, 0xa, 0xa, 0xa, 0xa, 0xa, 0xa, 0xa, 0x9, 0xa, 0xa, 0xa, 0xa, 0xa, 0xa, 0x9, 0x7, 0x9, 0x9, 0xa, 0x9, 0xa, 0xa, 0xa, 0x9, 0xa, 0xa, 0xa, 0xa, 0xa, 0xa, 0xa, 0x9, 0xa, 0xa, 0xa, 0xa, 0xa, 0xa, 0xa, 0xa, 0xa, 0xa, 0xa, 0xa, 0xa, 0xa, 0xa, 0xa, 0xa, 0xa, 0xa, 0xa, 0xa, 0xa, 0xa, 0xa, 0xa, 0xa, 0xd, 0xa, 0xa, 0xa, 0xa, 0xa, 0xa, 0xb, 0xa, 0xa, 0xa, 0xa, 0xa, 0xa, 0xa, 0xa, 0xa, 0xa, 0xa, 0xa, 0xa, 0x9, 0xa, 0xa, 0xa, 0xa, 0xa, 0x9, 0xa, 0xa, 0xa, 0xa, 0xa, 0x9, 0xa, 0xa, 0xa, 0x9, 0xa, 0xa, 0xa, 0xa, 0xa, 0xa, 0xa, 0xa, 0xa, 0xa, 0xa, 0xa, 0xa, 0xa, 0xa, 0x9, 0xa, 0xa, 0xa, 0xa, 0xa, 0xa, 0xa, 0xa, 0xa, 0xa, 0xa, 0xa, 0xa, 0x9, 0xa, 0x8, 0x9, 0x9, 0xa, 0x9, 0xa, 0xa, 0xa, 0x9, 0xa, 0xa, 0xa, 0x9, 0x9, 0x8, 0x7, 0xd, 0xd, 0x7, 0x7, 0xa, 0x7, 0x7, 0x6, 0x6, 0x6, 0x6, 0x5, 0x6, 0x6, 0x6, 0x5, 0x6, 0x5, 0x6, 0x6, 0x6, 0x6, 0x6, 0x6, 0x6, 0x6, 0x6, 0x6, 0x6, 0x6, 0x6, 0x6, 0x8, 0x5, 0x6, 0x7, 0x7 }; #endif static uint16 HuffIndexLEC[512] = { 0x007b, 0xff1f, 0xff0d, 0xfe27, 0xfe00, 0xff05, 0xff17, 0xfe68, 0x00c5, 0xfe07, 0xff13, 0xfec0, 0xff08, 0xfe18, 0xff1b, 0xfeb3, 0xfe03, 0x00a2, 0xfe42, 0xff10, 0xfe0b, 0xfe02, 0xfe91, 0xff19, 0xfe80, 0x00e9, 0xfe3a, 0xff15, 0xfe12, 0x0057, 0xfed7, 0xff1d, 0xff0e, 0xfe35, 0xfe69, 0xff22, 0xff18, 0xfe7a, 0xfe01, 0xff23, 0xff14, 0xfef4, 0xfeb4, 0xfe09, 0xff1c, 0xfec4, 0xff09, 0xfe60, 0xfe70, 0xff12, 0xfe05, 0xfe92, 0xfea1, 0xff1a, 0xfe0f, 0xff07, 0xfe56, 0xff16, 0xff02, 0xfed8, 0xfee8, 0xff1e, 0xfe1d, 0x003b, 0xffff, 0xff06, 0xffff, 0xfe71, 0xfe89, 0xffff, 0xffff, 0xfe2c, 0xfe2b, 0xfe20, 0xffff, 0xfebb, 0xfecf, 0xfe08, 0xffff, 0xfee0, 0xfe0d, 0xffff, 0xfe99, 0xffff, 0xfe04, 0xfeaa, 0xfe49, 0xffff, 0xfe17, 0xfe61, 0xfedf, 0xffff, 0xfeff, 0xfef6, 0xfe4c, 0xffff, 0xffff, 0xfe87, 0xffff, 0xff24, 0xffff, 0xfe3c, 0xfe72, 0xffff, 0xffff, 0xfece, 0xffff, 0xfefe, 0xffff, 0xfe23, 0xfebc, 0xfe0a, 0xfea9, 0xffff, 0xfe11, 0xffff, 0xfe82, 0xffff, 0xfe06, 0xfe9a, 0xfef5, 0xffff, 0xfe22, 0xfe4d, 0xfe5f, 0xffff, 0xff03, 0xfee1, 0xffff, 0xfeca, 0xfecc, 0xffff, 0xfe19, 0xffff, 0xfeb7, 0xffff, 0xffff, 0xfe83, 0xfe29, 0xffff, 0xffff, 0xffff, 0xfe6c, 0xffff, 0xfeed, 0xffff, 0xffff, 0xfe46, 0xfe5c, 0xfe15, 0xffff, 0xfedb, 0xfea6, 0xffff, 0xffff, 0xfe44, 0xffff, 0xfe0c, 0xffff, 0xfe95, 0xfefc, 0xffff, 0xffff, 0xfeb8, 0x16c9, 0xffff, 0xfef0, 0xffff, 0xfe38, 0xffff, 0xffff, 0xfe6d, 0xfe7e, 0xffff, 0xffff, 0xffff, 0xffff, 0xfe5b, 0xfedc, 0xffff, 0xffff, 0xfeec, 0xfe47, 0xfe1f, 0xffff, 0xfe7f, 0xfe96, 0xffff, 0xffff, 0xfea5, 0xffff, 0xfe10, 0xfe40, 0xfe32, 0xfebf, 0xffff, 0xffff, 0xfed4, 0xfef1, 0xffff, 0xffff, 0xffff, 0xfe75, 0xffff, 0xffff, 0xfe8d, 0xfe31, 0xffff, 0xfe65, 0xfe1b, 0xffff, 0xfee4, 0xfefb, 0xffff, 0xffff, 0xfe52, 0xffff, 0xfe0e, 0xffff, 0xfe9d, 0xfeaf, 0xffff, 0xffff, 0xfe51, 0xfed3, 0xffff, 0xff20, 0xffff, 0xfe2f, 0xffff, 0xffff, 0xfec1, 0xfe8c, 0xffff, 0xffff, 0xffff, 0xfe3f, 0xffff, 0xffff, 0xfe76, 0xffff, 0xfefa, 0xfe53, 0xfe25, 0xffff, 0xfe64, 0xfee5, 0xffff, 0xffff, 0xfeae, 0xffff, 0xfe13, 0xffff, 0xfe88, 0xfe9e, 0xffff, 0xfe43, 0xffff, 0xffff, 0xfea4, 0xfe93, 0xffff, 0xffff, 0xffff, 0xfe3d, 0xffff, 0xffff, 0xfeeb, 0xfed9, 0xffff, 0xfe14, 0xfe5a, 0xffff, 0xfe28, 0xfe7d, 0xffff, 0xffff, 0xfe6a, 0xffff, 0xffff, 0xff01, 0xfec6, 0xfec8, 0xffff, 0xffff, 0xfeb5, 0xffff, 0xffff, 0xffff, 0xfe94, 0xfe78, 0xffff, 0xffff, 0xffff, 0xfea3, 0xffff, 0xffff, 0xfeda, 0xfe58, 0xffff, 0xfe1e, 0xfe45, 0xfeea, 0xffff, 0xfe6b, 0xffff, 0xffff, 0xfe37, 0xffff, 0xffff, 0xffff, 0xfe7c, 0xfeb6, 0xffff, 0xffff, 0xfef8, 0xffff, 0xffff, 0xffff, 0xfec7, 0xfe9b, 0xffff, 0xffff, 0xffff, 0xfe50, 0xffff, 0xffff, 0xfead, 0xfee2, 0xffff, 0xfe1a, 0xfe63, 0xfe4e, 0xffff, 0xffff, 0xfef9, 0xffff, 0xfe73, 0xffff, 0xffff, 0xffff, 0xfe30, 0xfe8b, 0xffff, 0xffff, 0xfebd, 0xfe2e, 0x0100, 0xffff, 0xfeee, 0xfed2, 0xffff, 0xffff, 0xffff, 0xfeac, 0xffff, 0xffff, 0xfe9c, 0xfe84, 0xffff, 0xfe24, 0xfe4f, 0xfef7, 0xffff, 0xffff, 0xfee3, 0xfe62, 0xffff, 0xffff, 0xffff, 0xffff, 0xfe8a, 0xfe74, 0xffff, 0xffff, 0xfe3e, 0xffff, 0xffff, 0xffff, 0xfed1, 0xfebe, 0xffff, 0xffff, 0xfe2d, 0xffff, 0xfe4a, 0xfef3, 0xffff, 0xffff, 0xfedd, 0xfe5e, 0xfe16, 0xffff, 0xfe48, 0xfea8, 0xffff, 0xfeab, 0xfe97, 0xffff, 0xffff, 0xfed0, 0xffff, 0xffff, 0xfecd, 0xfeb9, 0xffff, 0xffff, 0xffff, 0xfe2a, 0xffff, 0xffff, 0xfe86, 0xfe6e, 0xffff, 0xffff, 0xffff, 0xfede, 0xffff, 0xffff, 0xfe5d, 0xfe4b, 0xfe21, 0xffff, 0xfeef, 0xfe98, 0xffff, 0xffff, 0xfe81, 0xffff, 0xffff, 0xffff, 0xfea7, 0xffff, 0xfeba, 0xfefd, 0xffff, 0xffff, 0xffff, 0xfecb, 0xffff, 0xffff, 0xfe6f, 0xfe39, 0xffff, 0xffff, 0xffff, 0xfe85, 0xffff, 0x010c, 0xfee6, 0xfe67, 0xfe1c, 0xffff, 0xfe54, 0xfeb2, 0xffff, 0xffff, 0xfe9f, 0xffff, 0xffff, 0xffff, 0xfe59, 0xfeb1, 0xffff, 0xfec2, 0xffff, 0xffff, 0xfe36, 0xfef2, 0xffff, 0xffff, 0xfed6, 0xfe77, 0xffff, 0xffff, 0xffff, 0xfe33, 0xffff, 0xffff, 0xfe8f, 0xfe55, 0xfe26, 0x010a, 0xff04, 0xfee7, 0xffff, 0x0121, 0xfe66, 0xffff, 0xffff, 0xffff, 0xfeb0, 0xfea0, 0xffff, 0x010f, 0xfe90, 0xffff, 0xffff, 0xfed5, 0xffff, 0xffff, 0xfec3, 0xfe34, 0xffff, 0xffff, 0xffff, 0xfe8e, 0xffff, 0x0111, 0xfe79, 0xfe41, 0x010b }; static uint16 LECHTab[] = { 511, 0, 508, 448, 494, 347, 486, 482 }; #if 0 static uint8 HuffLenLOM[] = { 0x4, 0x2, 0x3, 0x4, 0x3, 0x4, 0x4, 0x5, 0x4, 0x5, 0x5, 0x6, 0x6, 0x7, 0x7, 0x8, 0x7, 0x8, 0x8, 0x9, 0x9, 0x8, 0x9, 0x9, 0x9, 0x9, 0x9, 0x9, 0x9, 0x9, 0x9, 0x9 }; #endif static uint16 HuffIndexLOM[] = { 0x0fe1, 0x0fe0, 0x0fe2, 0x0fe8, 0x000e, 0x0fe5, 0x0fe4, 0x0fea, 0x0ff1, 0x0fe3, 0x0015, 0x0fe7, 0x0fef, 0x0046, 0x0ff0, 0x0fed, 0x0fff, 0x0ff7, 0x0ffb, 0x0019, 0x0ffd, 0x0ff4, 0x012c, 0x0feb, 0x0ffe, 0x0ff6, 0x0ffa, 0x0089, 0x0ffc, 0x0ff3, 0x0ff8, 0x0ff2 }; static uint8 LOMHTab[] = { 0, 4, 10, 19 }; #if 0 static uint8 CopyOffsetBitsLUT[] = { 0, 0, 0, 0, 1, 1, 2, 2, 3, 3, 4, 4, 5, 5, 6, 6, 7, 7, 8, 8, 9, 9, 10, 10, 11, 11, 12, 12, 13, 13, 14, 14, 15 }; static uint32 CopyOffsetBaseLUT[] = { 13, 17, 25, 33, 49, 65, 97, 129, 193, 257, 385, 513, 769, 1025, 1537, 2049, 3073, 4097, 6145, 8193, 12289, 16385, 24577, 32769, 49153, 65537 }; static uint8 LoMBitsLUT[] = { 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 2, 2, 2, 2, 3, 3, 3, 3, 4, 4, 4, 4, 6, 6, 8, 8, 14, 14 }; static uint16 LoMBaseLUT[] = { 2, 3, 4, 5, 6, 7, 8, 9, 10, 12, 14, 16, 18, 22, 26, 30, 34, 42, 50, 58, 66, 82, 98, 114, 130, 194, 258, 514, 2, 2 }; #endif uint16 LEChash(uint16 key) { return ((key & 0x1ff) ^ (key >> 9) ^ (key >> 4) ^ (key >> 7)); } uint16 LOMhash(uint16 key) { return ((key & 0x1f) ^ (key >> 5) ^ (key >> 9)); } uint16 miniLEChash(uint16 key) { uint16 h; h = ((((key >> 8) ^ (key & 0xff)) >> 2) & 0xf); if(key >> 9) h = ~h; return (h % 12); } uint8 miniLOMhash(uint16 key) { return ((key >> 4) ^ (key >> 6) ^ (key >> 7)); } uint16 getLECindex(uint16 huff) { uint16 h = HuffIndexLEC[LEChash(huff)]; if((h ^ huff) >> 9) return h & 0x1ff; else return HuffIndexLEC[LECHTab[miniLEChash(huff)]]; } uint16 getLOMindex(uint16 huff) { uint16 h = HuffIndexLOM[LOMhash(huff)]; if((h ^ huff) >> 5) { return h & 0x1f; } else return HuffIndexLOM[LOMHTab[miniLOMhash(huff)]]; } int decompress_rdp(rdpRdp* rdp, uint8* cbuf, int len, int ctype, uint32* roff, uint32* rlen) { int type = ctype & 0x0f; switch (type) { case PACKET_COMPR_TYPE_8K: return decompress_rdp_4(rdp, cbuf, len, ctype, roff, rlen); break; case PACKET_COMPR_TYPE_64K: return decompress_rdp_5(rdp, cbuf, len, ctype, roff, rlen); break; case PACKET_COMPR_TYPE_RDP6: return decompress_rdp_6(rdp, cbuf, len, ctype, roff, rlen); break; case PACKET_COMPR_TYPE_RDP61: return decompress_rdp_61(rdp, cbuf, len, ctype, roff, rlen); break; default: printf("mppc.c: invalid RDP compression code 0x%2.2x\n", type); return false; } } /** * decompress RDP 4 data * * @param rdp per session information * @param cbuf compressed data * @param len length of compressed data * @param ctype compression flags * @param roff starting offset of uncompressed data * @param rlen length of uncompressed data * * @return True on success, False on failure */ int decompress_rdp_4(rdpRdp* rdp, uint8* cbuf, int len, int ctype, uint32* roff, uint32* rlen) { uint8* history_buf; /* uncompressed data goes here */ uint8* history_ptr; /* points to next free slot in history_buf */ uint32 d32; /* we process 4 compressed bytes at a time */ uint16 copy_offset; /* location to copy data from */ uint16 lom; /* length of match */ uint8* src_ptr; /* used while copying compressed data */ uint8* cptr; /* points to next byte in cbuf */ uint8 cur_byte; /* last byte fetched from cbuf */ int bits_left; /* bits left in d34 for processing */ int cur_bits_left; /* bits left in cur_byte for processing */ int tmp; uint32 i32; printf("decompress_rdp_4:\n"); if ((rdp->mppc == NULL) || (rdp->mppc->history_buf == NULL)) { printf("decompress_rdp_4: null\n"); return false; } src_ptr = 0; cptr = cbuf; copy_offset = 0; lom = 0; bits_left = 0; cur_bits_left = 0; d32 = 0; cur_byte = 0; *rlen = 0; /* get start of history buffer */ history_buf = rdp->mppc->history_buf; /* get next free slot in history buffer */ history_ptr = rdp->mppc->history_ptr; *roff = history_ptr - history_buf; if (ctype & PACKET_AT_FRONT) { /* place compressed data at start of history buffer */ history_ptr = rdp->mppc->history_buf; rdp->mppc->history_ptr = rdp->mppc->history_buf; *roff = 0; } if (ctype & PACKET_FLUSHED) { /* re-init history buffer */ history_ptr = rdp->mppc->history_buf; memset(history_buf, 0, RDP6_HISTORY_BUF_SIZE); *roff = 0; } if ((ctype & PACKET_COMPRESSED) != PACKET_COMPRESSED) { /* data in cbuf is not compressed - copy to history buf as is */ memcpy(history_ptr, cbuf, len); history_ptr += len; *rlen = history_ptr - rdp->mppc->history_ptr; rdp->mppc->history_ptr = history_ptr; return true; } /* load initial data */ tmp = 24; while (cptr < cbuf + len) { i32 = *cptr++; d32 |= i32 << tmp; bits_left += 8; tmp -= 8; if (tmp < 0) { break; } } if (cptr < cbuf + len) { cur_byte = *cptr++; cur_bits_left = 8; } else { cur_bits_left = 0; } /* ** start uncompressing data in cbuf */ while (bits_left >= 8) { /* value 0xxxxxxx = literal, not encoded value 10xxxxxx = literal, encoded value 1111xxxx = copy offset 0 - 63 value 1110xxxx = copy offset 64 - 319 value 110xxxxx = copy offset 320 - 8191 */ /* at this point, we are guaranteed that d32 has 32 bits to be processed, unless we have reached end of cbuf */ copy_offset = 0; if ((d32 & 0x80000000) == 0) { /* got a literal */ *history_ptr++ = d32 >> 24; d32 <<= 8; bits_left -= 8; } else if ((d32 & 0xc0000000) == 0x80000000) { /* got encoded literal */ d32 <<= 2; *history_ptr++ = (d32 >> 25) | 0x80; d32 <<= 7; bits_left -= 9; } else if ((d32 & 0xf0000000) == 0xf0000000) { /* got copy offset in range 0 - 63, */ /* with 6 bit copy offset */ d32 <<= 4; copy_offset = d32 >> 26; d32 <<= 6; bits_left -= 10; } else if ((d32 & 0xf0000000) == 0xe0000000) { /* got copy offset in range 64 - 319, */ /* with 8 bit copy offset */ d32 <<= 4; copy_offset = d32 >> 24; copy_offset += 64; d32 <<= 8; bits_left -= 12; } else if ((d32 & 0xe0000000) == 0xc0000000) { /* got copy offset in range 320 - 8191, */ /* with 13 bits copy offset */ d32 <<= 3; copy_offset = d32 >> 19; copy_offset += 320; d32 <<= 13; bits_left -= 16; } /* ** get more bits before we process length of match */ /* how may bits do we need to get? */ tmp = 32 - bits_left; while (tmp) { if (cur_bits_left < tmp) { /* we have less bits than we need */ i32 = cur_byte >> (8 - cur_bits_left); d32 |= i32 << ((32 - bits_left) - cur_bits_left); bits_left += cur_bits_left; tmp -= cur_bits_left; if (cptr < cbuf + len) { /* more compressed data available */ cur_byte = *cptr++; cur_bits_left = 8; } else { /* no more compressed data available */ tmp = 0; cur_bits_left = 0; } } else if (cur_bits_left > tmp) { /* we have more bits than we need */ d32 |= cur_byte >> (8 - tmp); cur_byte <<= tmp; cur_bits_left -= tmp; bits_left = 32; break; } else { /* we have just the right amount of bits */ d32 |= cur_byte >> (8 - tmp); bits_left = 32; if (cptr < cbuf + len) { cur_byte = *cptr++; cur_bits_left = 8; } else { cur_bits_left = 0; } break; } } if (!copy_offset) { continue; } /* ** compute Length of Match */ /* lengh of match Encoding (binary header + LoM bits -------------- ---------------------------------- 3 0 4...7 10 + 2 lower bits of L-o-M 8...15 110 + 3 lower bits of L-o-M 16...31 1110 + 4 lower bits of L-o-M 32...63 11110 + 5 lower bits of L-o-M 64...127 111110 + 6 lower bits of L-o-M 128...255 1111110 + 7 lower bits of L-o-M 256...511 11111110 + 8 lower bits of L-o-M 512...1023 111111110 + 9 lower bits of L-o-M 1024...2047 1111111110 + 10 lower bits of L-o-M 2048...4095 11111111110 + 11 lower bits of L-o-M 4096...8191 111111111110 + 12 lower bits of L-o-M */ if ((d32 & 0x80000000) == 0) { /* lom is fixed to 3 */ lom = 3; d32 <<= 1; bits_left -= 1; } else if ((d32 & 0xc0000000) == 0x80000000) { /* 2 lower bits of LoM */ lom = ((d32 >> 28) & 0x03) + 4; d32 <<= 4; bits_left -= 4; } else if ((d32 & 0xe0000000) == 0xc0000000) { /* 3 lower bits of LoM */ lom = ((d32 >> 26) & 0x07) + 8; d32 <<= 6; bits_left -= 6; } else if ((d32 & 0xf0000000) == 0xe0000000) { /* 4 lower bits of LoM */ lom = ((d32 >> 24) & 0x0f) + 16; d32 <<= 8; bits_left -= 8; } else if ((d32 & 0xf8000000) == 0xf0000000) { /* 5 lower bits of LoM */ lom = ((d32 >> 22) & 0x1f) + 32; d32 <<= 10; bits_left -= 10; } else if ((d32 & 0xfc000000) == 0xf8000000) { /* 6 lower bits of LoM */ lom = ((d32 >> 20) & 0x3f) + 64; d32 <<= 12; bits_left -= 12; } else if ((d32 & 0xfe000000) == 0xfc000000) { /* 7 lower bits of LoM */ lom = ((d32 >> 18) & 0x7f) + 128; d32 <<= 14; bits_left -= 14; } else if ((d32 & 0xff000000) == 0xfe000000) { /* 8 lower bits of LoM */ lom = ((d32 >> 16) & 0xff) + 256; d32 <<= 16; bits_left -= 16; } else if ((d32 & 0xff800000) == 0xff000000) { /* 9 lower bits of LoM */ lom = ((d32 >> 14) & 0x1ff) + 512; d32 <<= 18; bits_left -= 18; } else if ((d32 & 0xffc00000) == 0xff800000) { /* 10 lower bits of LoM */ lom = ((d32 >> 12) & 0x3ff) + 1024; d32 <<= 20; bits_left -= 20; } else if ((d32 & 0xffe00000) == 0xffc00000) { /* 11 lower bits of LoM */ lom = ((d32 >> 10) & 0x7ff) + 2048; d32 <<= 22; bits_left -= 22; } else if ((d32 & 0xfff00000) == 0xffe00000) { /* 12 lower bits of LoM */ lom = ((d32 >> 8) & 0xfff) + 4096; d32 <<= 24; bits_left -= 24; } /* now that we have copy_offset and LoM, process them */ src_ptr = history_ptr - copy_offset; if (src_ptr >= rdp->mppc->history_buf) { /* data does not wrap around */ while (lom > 0) { *history_ptr++ = *src_ptr++; lom--; } } else { src_ptr = rdp->mppc->history_buf_end - (copy_offset - (history_ptr - rdp->mppc->history_buf)); src_ptr++; while (lom && (src_ptr <= rdp->mppc->history_buf_end)) { *history_ptr++ = *src_ptr++; lom--; } src_ptr = rdp->mppc->history_buf; while (lom > 0) { *history_ptr++ = *src_ptr++; lom--; } } /* ** get more bits before we restart the loop */ /* how may bits do we need to get? */ tmp = 32 - bits_left; while (tmp) { if (cur_bits_left < tmp) { /* we have less bits than we need */ i32 = cur_byte >> (8 - cur_bits_left); d32 |= i32 << ((32 - bits_left) - cur_bits_left); bits_left += cur_bits_left; tmp -= cur_bits_left; if (cptr < cbuf + len) { /* more compressed data available */ cur_byte = *cptr++; cur_bits_left = 8; } else { /* no more compressed data available */ tmp = 0; cur_bits_left = 0; } } else if (cur_bits_left > tmp) { /* we have more bits than we need */ d32 |= cur_byte >> (8 - tmp); cur_byte <<= tmp; cur_bits_left -= tmp; bits_left = 32; break; } else { /* we have just the right amount of bits */ d32 |= cur_byte >> (8 - tmp); bits_left = 32; if (cptr < cbuf + len) { cur_byte = *cptr++; cur_bits_left = 8; } else { cur_bits_left = 0; } break; } } } /* end while (bits_left >= 8) */ *rlen = history_ptr - rdp->mppc->history_ptr; rdp->mppc->history_ptr = history_ptr; return true; } /** * decompress RDP 5 data * * @param rdp per session information * @param cbuf compressed data * @param len length of compressed data * @param ctype compression flags * @param roff starting offset of uncompressed data * @param rlen length of uncompressed data * * @return True on success, False on failure */ int decompress_rdp_5(rdpRdp* rdp, uint8* cbuf, int len, int ctype, uint32* roff, uint32* rlen) { uint8* history_buf; /* uncompressed data goes here */ uint8* history_ptr; /* points to next free slot in bistory_buf */ uint32 d32; /* we process 4 compressed bytes at a time */ uint16 copy_offset; /* location to copy data from */ uint16 lom; /* length of match */ uint8* src_ptr; /* used while copying compressed data */ uint8* cptr; /* points to next byte in cbuf */ uint8 cur_byte; /* last byte fetched from cbuf */ int bits_left; /* bits left in d32 for processing */ int cur_bits_left; /* bits left in cur_byte for processing */ int tmp; uint32 i32; if ((rdp->mppc == NULL) || (rdp->mppc->history_buf == NULL)) { printf("decompress_rdp_5: null\n"); return false; } src_ptr = 0; cptr = cbuf; copy_offset = 0; lom = 0; bits_left = 0; cur_bits_left = 0; d32 = 0; cur_byte = 0; *rlen = 0; /* get start of history buffer */ history_buf = rdp->mppc->history_buf; /* get next free slot in history buffer */ history_ptr = rdp->mppc->history_ptr; *roff = history_ptr - history_buf; if (ctype & PACKET_AT_FRONT) { /* place compressed data at start of history buffer */ history_ptr = rdp->mppc->history_buf; rdp->mppc->history_ptr = rdp->mppc->history_buf; *roff = 0; } if (ctype & PACKET_FLUSHED) { /* re-init history buffer */ history_ptr = rdp->mppc->history_buf; memset(history_buf, 0, RDP6_HISTORY_BUF_SIZE); *roff = 0; } if ((ctype & PACKET_COMPRESSED) != PACKET_COMPRESSED) { /* data in cbuf is not compressed - copy to history buf as is */ memcpy(history_ptr, cbuf, len); history_ptr += len; *rlen = history_ptr - rdp->mppc->history_ptr; rdp->mppc->history_ptr = history_ptr; return true; } /* load initial data */ tmp = 24; while (cptr < cbuf + len) { i32 = *cptr++; d32 |= i32 << tmp; bits_left += 8; tmp -= 8; if (tmp < 0) { break; } } if (cptr < cbuf + len) { cur_byte = *cptr++; cur_bits_left = 8; } else { cur_bits_left = 0; } /* ** start uncompressing data in cbuf */ while (bits_left >= 8) { /* value 0xxxxxxx = literal, not encoded value 10xxxxxx = literal, encoded value 11111xxx = copy offset 0 - 63 value 11110xxx = copy offset 64 - 319 value 1110xxxx = copy offset 320 - 2367 value 110xxxxx = copy offset 2368+ */ /* at this point, we are guaranteed that d32 has 32 bits to be processed, unless we have reached end of cbuf */ copy_offset = 0; if ((d32 & 0x80000000) == 0) { /* got a literal */ *history_ptr++ = d32 >> 24; d32 <<= 8; bits_left -= 8; } else if ((d32 & 0xc0000000) == 0x80000000) { /* got encoded literal */ d32 <<= 2; *history_ptr++ = (d32 >> 25) | 0x80; d32 <<= 7; bits_left -= 9; } else if ((d32 & 0xf8000000) == 0xf8000000) { /* got copy offset in range 0 - 63, */ /* with 6 bit copy offset */ d32 <<= 5; copy_offset = d32 >> 26; d32 <<= 6; bits_left -= 11; } else if ((d32 & 0xf8000000) == 0xf0000000) { /* got copy offset in range 64 - 319, */ /* with 8 bit copy offset */ d32 <<= 5; copy_offset = d32 >> 24; copy_offset += 64; d32 <<= 8; bits_left -= 13; } else if ((d32 & 0xf0000000) == 0xe0000000) { /* got copy offset in range 320 - 2367, */ /* with 11 bits copy offset */ d32 <<= 4; copy_offset = d32 >> 21; copy_offset += 320; d32 <<= 11; bits_left -= 15; } else if ((d32 & 0xe0000000) == 0xc0000000) { /* got copy offset in range 2368+, */ /* with 16 bits copy offset */ d32 <<= 3; copy_offset = d32 >> 16; copy_offset += 2368; d32 <<= 16; bits_left -= 19; } /* ** get more bits before we process length of match */ /* how may bits do we need to get? */ tmp = 32 - bits_left; while (tmp) { if (cur_bits_left < tmp) { /* we have less bits than we need */ i32 = cur_byte >> (8 - cur_bits_left); d32 |= i32 << ((32 - bits_left) - cur_bits_left); bits_left += cur_bits_left; tmp -= cur_bits_left; if (cptr < cbuf + len) { /* more compressed data available */ cur_byte = *cptr++; cur_bits_left = 8; } else { /* no more compressed data available */ tmp = 0; cur_bits_left = 0; } } else if (cur_bits_left > tmp) { /* we have more bits than we need */ d32 |= cur_byte >> (8 - tmp); cur_byte <<= tmp; cur_bits_left -= tmp; bits_left = 32; break; } else { /* we have just the right amount of bits */ d32 |= cur_byte >> (8 - tmp); bits_left = 32; if (cptr < cbuf + len) { cur_byte = *cptr++; cur_bits_left = 8; } else { cur_bits_left = 0; } break; } } if (!copy_offset) { continue; } /* ** compute Length of Match */ /* lengh of match Encoding (binary header + LoM bits -------------- ---------------------------------- 3 0 4..7 10 + 2 lower bits of LoM 8..15 110 + 3 lower bits of LoM 16..31 1110 + 4 lower bits of LoM 32..63 1111-0 + 5 lower bits of LoM 64..127 1111-10 + 6 lower bits of LoM 128..255 1111-110 + 7 lower bits of LoM 256..511 1111-1110 + 8 lower bits of LoM 512..1023 1111-1111-0 + 9 lower bits of LoM 1024..2047 1111-1111-10 + 10 lower bits of LoM 2048..4095 1111-1111-110 + 11 lower bits of LoM 4096..8191 1111-1111-1110 + 12 lower bits of LoM 8192..16383 1111-1111-1111-0 + 13 lower bits of LoM 16384..32767 1111-1111-1111-10 + 14 lower bits of LoM 32768..65535 1111-1111-1111-110 + 15 lower bits of LoM */ if ((d32 & 0x80000000) == 0) { /* lom is fixed to 3 */ lom = 3; d32 <<= 1; bits_left -= 1; } else if ((d32 & 0xc0000000) == 0x80000000) { /* 2 lower bits of LoM */ lom = ((d32 >> 28) & 0x03) + 4; d32 <<= 4; bits_left -= 4; } else if ((d32 & 0xe0000000) == 0xc0000000) { /* 3 lower bits of LoM */ lom = ((d32 >> 26) & 0x07) + 8; d32 <<= 6; bits_left -= 6; } else if ((d32 & 0xf0000000) == 0xe0000000) { /* 4 lower bits of LoM */ lom = ((d32 >> 24) & 0x0f) + 16; d32 <<= 8; bits_left -= 8; } else if ((d32 & 0xf8000000) == 0xf0000000) { /* 5 lower bits of LoM */ lom = ((d32 >> 22) & 0x1f) + 32; d32 <<= 10; bits_left -= 10; } else if ((d32 & 0xfc000000) == 0xf8000000) { /* 6 lower bits of LoM */ lom = ((d32 >> 20) & 0x3f) + 64; d32 <<= 12; bits_left -= 12; } else if ((d32 & 0xfe000000) == 0xfc000000) { /* 7 lower bits of LoM */ lom = ((d32 >> 18) & 0x7f) + 128; d32 <<= 14; bits_left -= 14; } else if ((d32 & 0xff000000) == 0xfe000000) { /* 8 lower bits of LoM */ lom = ((d32 >> 16) & 0xff) + 256; d32 <<= 16; bits_left -= 16; } else if ((d32 & 0xff800000) == 0xff000000) { /* 9 lower bits of LoM */ lom = ((d32 >> 14) & 0x1ff) + 512; d32 <<= 18; bits_left -= 18; } else if ((d32 & 0xffc00000) == 0xff800000) { /* 10 lower bits of LoM */ lom = ((d32 >> 12) & 0x3ff) + 1024; d32 <<= 20; bits_left -= 20; } else if ((d32 & 0xffe00000) == 0xffc00000) { /* 11 lower bits of LoM */ lom = ((d32 >> 10) & 0x7ff) + 2048; d32 <<= 22; bits_left -= 22; } else if ((d32 & 0xfff00000) == 0xffe00000) { /* 12 lower bits of LoM */ lom = ((d32 >> 8) & 0xfff) + 4096; d32 <<= 24; bits_left -= 24; } else if ((d32 & 0xfff80000) == 0xfff00000) { /* 13 lower bits of LoM */ lom = ((d32 >> 6) & 0x1fff) + 8192; d32 <<= 26; bits_left -= 26; } else if ((d32 & 0xfffc0000) == 0xfff80000) { /* 14 lower bits of LoM */ lom = ((d32 >> 4) & 0x3fff) + 16384; d32 <<= 28; bits_left -= 28; } else if ((d32 & 0xfffe0000) == 0xfffc0000) { /* 15 lower bits of LoM */ lom = ((d32 >> 2) & 0x7fff) + 32768; d32 <<= 30; bits_left -= 30; } /* now that we have copy_offset and LoM, process them */ src_ptr = history_ptr - copy_offset; if (src_ptr >= rdp->mppc->history_buf) { /* data does not wrap around */ while (lom > 0) { *history_ptr++ = *src_ptr++; lom--; } } else { src_ptr = rdp->mppc->history_buf_end - (copy_offset - (history_ptr - rdp->mppc->history_buf)); src_ptr++; while (lom && (src_ptr <= rdp->mppc->history_buf_end)) { *history_ptr++ = *src_ptr++; lom--; } src_ptr = rdp->mppc->history_buf; while (lom > 0) { *history_ptr++ = *src_ptr++; lom--; } } /* ** get more bits before we restart the loop */ /* how may bits do we need to get? */ tmp = 32 - bits_left; while (tmp) { if (cur_bits_left < tmp) { /* we have less bits than we need */ i32 = cur_byte >> (8 - cur_bits_left); d32 |= i32 << ((32 - bits_left) - cur_bits_left); bits_left += cur_bits_left; tmp -= cur_bits_left; if (cptr < cbuf + len) { /* more compressed data available */ cur_byte = *cptr++; cur_bits_left = 8; } else { /* no more compressed data available */ tmp = 0; cur_bits_left = 0; } } else if (cur_bits_left > tmp) { /* we have more bits than we need */ d32 |= cur_byte >> (8 - tmp); cur_byte <<= tmp; cur_bits_left -= tmp; bits_left = 32; break; } else { /* we have just the right amount of bits */ d32 |= cur_byte >> (8 - tmp); bits_left = 32; if (cptr < cbuf + len) { cur_byte = *cptr++; cur_bits_left = 8; } else { cur_bits_left = 0; } break; } } } /* end while (cptr < cbuf + len) */ *rlen = history_ptr - rdp->mppc->history_ptr; rdp->mppc->history_ptr = history_ptr; return true; } /** * decompress RDP 6 data * * @param rdp per session information * @param cbuf compressed data * @param len length of compressed data * @param ctype compression flags * @param roff starting offset of uncompressed data * @param rlen length of uncompressed data * * @return True on success, False on failure */ int decompress_rdp_6(rdpRdp* rdp, uint8* cbuf, int len, int ctype, uint32* roff, uint32* rlen) { uint8* history_buf; /* uncompressed data goes here */ uint16* offset_cache; /* Copy Offset cache */ uint8* history_ptr; /* points to next free slot in bistory_buf */ uint32 d32; /* we process 4 compressed bytes at a time */ uint16 copy_offset; /* location to copy data from */ uint16 lom; /* length of match */ uint8* src_ptr; /* used while copying compressed data */ uint8* cptr; /* points to next byte in cbuf */ uint8 cur_byte; /* last byte fetched from cbuf */ int bits_left; /* bits left in d32 for processing */ int cur_bits_left; /* bits left in cur_byte for processing */ int tmp; uint32 i32; if ((rdp->mppc == NULL) || (rdp->mppc->history_buf == NULL)) { printf("decompress_rdp_6: null\n"); return false; } src_ptr = 0; cptr = cbuf; copy_offset = 0; lom = 0; bits_left = 0; cur_bits_left = 0; d32 = 0; cur_byte = 0; *rlen = 0; /* get start of history buffer */ history_buf = rdp->mppc->history_buf; /* get start of offset_cache */ offset_cache = rdp->mppc->offset_cache; /* get next free slot in history buffer */ history_ptr = rdp->mppc->history_ptr; *roff = history_ptr - history_buf; if (ctype & PACKET_AT_FRONT) { printf("need to look later\n"); /* slid history_buf and reset history_buf to middle */ memcpy(history_buf, (history_buf + 32768), (history_ptr -history_buf - 32768)); memcpy((history_buf + (history_ptr - history_buf - 32768)), cbuf, len); history_ptr = history_buf + 32768; *roff = 32768; } if (ctype & PACKET_FLUSHED) { /* re-init history buffer */ history_ptr = rdp->mppc->history_buf; memset(history_buf, 0, RDP6_HISTORY_BUF_SIZE); memset(offset_cache, 0, RDP6_OFFSET_CACHE_SIZE); *roff = 0; } if ((ctype & PACKET_COMPRESSED) != PACKET_COMPRESSED) { /* data in cbuf is not compressed - copy to history buf as is */ memcpy(history_ptr, cbuf, len); history_ptr += len; *rlen = history_ptr - rdp->mppc->history_ptr; rdp->mppc->history_ptr = history_ptr; return true; } /* load initial data */ tmp = 24; while (cptr < cbuf + len) { i32 = *cptr++; d32 |= i32 << tmp; bits_left += 8; tmp -= 8; if (tmp < 0) { break; } } if (cptr < cbuf + len) { cur_byte = *cptr++; cur_bits_left = 8; } else { cur_bits_left = 0; } /* ** start uncompressing data in cbuf */ return true; } /** * decompress RDP 6.1 data * * @param rdp per session information * @param cbuf compressed data * @param len length of compressed data * @param ctype compression flags * @param roff starting offset of uncompressed data * @param rlen length of uncompressed data * * @return True on success, False on failure */ int decompress_rdp_61(rdpRdp* rdp, uint8* cbuf, int len, int ctype, uint32* roff, uint32* rlen) { return false; } /** * allocate space to store history buffer * * @param rdp rdp struct that contains rdp_mppc struct * @return pointer to new struct, or NULL on failure */ struct rdp_mppc* mppc_new(rdpRdp* rdp) { struct rdp_mppc* ptr; ptr = (struct rdp_mppc*) xmalloc(sizeof(struct rdp_mppc)); if (!ptr) { printf("mppc_new(): system out of memory\n"); return NULL; } ptr->history_buf = (uint8*) xmalloc(RDP6_HISTORY_BUF_SIZE); ptr->offset_cache = (uint16*) xzalloc(RDP6_OFFSET_CACHE_SIZE); if (!ptr->history_buf) { printf("mppc_new(): system out of memory\n"); xfree(ptr); return NULL; } ptr->history_ptr = ptr->history_buf; ptr->history_buf_end = ptr->history_buf + RDP6_HISTORY_BUF_SIZE - 1; return ptr; } /** * free history buffer * * @param rdp rdp struct that contains rdp_mppc struct */ void mppc_free(rdpRdp* rdp) { if (!rdp->mppc) { return; } if (rdp->mppc->history_buf) { xfree(rdp->mppc->history_buf); rdp->mppc->history_buf = NULL; rdp->mppc->history_ptr = NULL; } if (rdp->mppc->offset_cache) { xfree(rdp->mppc->offset_cache); } xfree(rdp->mppc); } FreeRDP-1.0.2/libfreerdp-core/mppc.h000066400000000000000000000026461207112532300171210ustar00rootroot00000000000000/** * FreeRDP: A Remote Desktop Protocol Client * Implements Microsoft Point to Point Compression (MPPC) protocol * * Copyright 2011 Laxmikant Rashinkar * * 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. */ #ifndef __MPPC_H #define __MPPC_H #include #define RDP6_HISTORY_BUF_SIZE 65536 #define RDP6_OFFSET_CACHE_SIZE 4 struct rdp_mppc { uint8 *history_buf; uint16 *offset_cache; uint8 *history_buf_end; uint8 *history_ptr; }; // forward declarations int decompress_rdp(rdpRdp *, uint8 *, int, int, uint32 *, uint32 *); int decompress_rdp_4(rdpRdp *, uint8 *, int, int, uint32 *, uint32 *); int decompress_rdp_5(rdpRdp *, uint8 *, int, int, uint32 *, uint32 *); int decompress_rdp_6(rdpRdp *, uint8 *, int, int, uint32 *, uint32 *); int decompress_rdp_61(rdpRdp *, uint8 *, int, int, uint32 *, uint32 *); struct rdp_mppc *mppc_new(rdpRdp *rdp); void mppc_free(rdpRdp *rdp); #endif FreeRDP-1.0.2/libfreerdp-core/nego.c000066400000000000000000000360351207112532300171040ustar00rootroot00000000000000/** * FreeRDP: A Remote Desktop Protocol Client * RDP Protocol Security Negotiation * * Copyright 2011 Marc-Andre Moreau * * 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. */ #include #include #include #include #include "tpkt.h" #include "nego.h" static const char* const NEGO_STATE_STRINGS[] = { "NEGO_STATE_INITIAL", "NEGO_STATE_NLA", "NEGO_STATE_TLS", "NEGO_STATE_RDP", "NEGO_STATE_FAIL", "NEGO_STATE_FINAL" }; static const char PROTOCOL_SECURITY_STRINGS[3][4] = { "RDP", "TLS", "NLA" }; /** * Negotiate protocol security and connect. * @param nego * @return */ boolean nego_connect(rdpNego* nego) { if (nego->state == NEGO_STATE_INITIAL) { if (nego->enabled_protocols[PROTOCOL_NLA] > 0) nego->state = NEGO_STATE_NLA; else if (nego->enabled_protocols[PROTOCOL_TLS] > 0) nego->state = NEGO_STATE_TLS; else if (nego->enabled_protocols[PROTOCOL_RDP] > 0) nego->state = NEGO_STATE_RDP; else nego->state = NEGO_STATE_FAIL; } do { DEBUG_NEGO("state: %s", NEGO_STATE_STRINGS[nego->state]); nego_send(nego); if (nego->state == NEGO_STATE_FAIL) { DEBUG_NEGO("Protocol Security Negotiation Failure"); nego->state = NEGO_STATE_FINAL; return false; } } while (nego->state != NEGO_STATE_FINAL); DEBUG_NEGO("Negotiated %s security", PROTOCOL_SECURITY_STRINGS[nego->selected_protocol]); /* update settings with negotiated protocol security */ nego->transport->settings->requested_protocols = nego->requested_protocols; nego->transport->settings->selected_protocol = nego->selected_protocol; nego->transport->settings->negotiationFlags = nego->flags; if(nego->selected_protocol == PROTOCOL_RDP) { nego->transport->settings->encryption = true; nego->transport->settings->encryption_method = ENCRYPTION_METHOD_40BIT | ENCRYPTION_METHOD_128BIT | ENCRYPTION_METHOD_FIPS; nego->transport->settings->encryption_level = ENCRYPTION_LEVEL_CLIENT_COMPATIBLE; } return true; } /** * Connect TCP layer. * @param nego * @return */ boolean nego_tcp_connect(rdpNego* nego) { if (nego->tcp_connected == 0) { if (transport_connect(nego->transport, nego->hostname, nego->port) == false) { nego->tcp_connected = 0; return false; } else { nego->tcp_connected = 1; return true; } } return true; } /** * Disconnect TCP layer. * @param nego * @return */ int nego_tcp_disconnect(rdpNego* nego) { if (nego->tcp_connected) transport_disconnect(nego->transport); nego->tcp_connected = 0; return 1; } /** * Attempt negotiating NLA + TLS security. * @param nego */ void nego_attempt_nla(rdpNego* nego) { nego->requested_protocols = PROTOCOL_NLA | PROTOCOL_TLS; DEBUG_NEGO("Attempting NLA security"); if (!nego_tcp_connect(nego)) { nego->state = NEGO_STATE_FAIL; return; } if (!nego_send_negotiation_request(nego)) { nego->state = NEGO_STATE_FAIL; return; } if (!nego_recv_response(nego)) { nego->state = NEGO_STATE_FAIL; return; } if (nego->state != NEGO_STATE_FINAL) { nego_tcp_disconnect(nego); if (nego->enabled_protocols[PROTOCOL_TLS] > 0) nego->state = NEGO_STATE_TLS; else if (nego->enabled_protocols[PROTOCOL_RDP] > 0) nego->state = NEGO_STATE_RDP; else nego->state = NEGO_STATE_FAIL; } } /** * Attempt negotiating TLS security. * @param nego */ void nego_attempt_tls(rdpNego* nego) { nego->requested_protocols = PROTOCOL_TLS; DEBUG_NEGO("Attempting TLS security"); if (!nego_tcp_connect(nego)) { nego->state = NEGO_STATE_FAIL; return; } if (!nego_send_negotiation_request(nego)) { nego->state = NEGO_STATE_FAIL; return; } if (!nego_recv_response(nego)) { nego->state = NEGO_STATE_FAIL; return; } if (nego->state != NEGO_STATE_FINAL) { nego_tcp_disconnect(nego); if (nego->enabled_protocols[PROTOCOL_RDP] > 0) nego->state = NEGO_STATE_RDP; else nego->state = NEGO_STATE_FAIL; } } /** * Attempt negotiating standard RDP security. * @param nego */ void nego_attempt_rdp(rdpNego* nego) { nego->requested_protocols = PROTOCOL_RDP; DEBUG_NEGO("Attempting RDP security"); if (!nego_tcp_connect(nego)) { nego->state = NEGO_STATE_FAIL; return; } if (!nego_send_negotiation_request(nego)) { nego->state = NEGO_STATE_FAIL; return; } if (!nego_recv_response(nego)) { nego->state = NEGO_STATE_FAIL; return; } } /** * Wait to receive a negotiation response * @param nego */ boolean nego_recv_response(rdpNego* nego) { STREAM* s = transport_recv_stream_init(nego->transport, 1024); if (transport_read(nego->transport, s) < 0) return false; return nego_recv(nego->transport, s, nego->transport->recv_extra); } /** * Receive protocol security negotiation message.\n * @msdn{cc240501} * @param transport transport * @param s stream * @param extra nego pointer */ boolean nego_recv(rdpTransport* transport, STREAM* s, void* extra) { uint8 li; uint8 type; rdpNego* nego = (rdpNego*) extra; if (tpkt_read_header(s) == 0) return false; li = tpdu_read_connection_confirm(s); if (li > 6) { /* rdpNegData (optional) */ stream_read_uint8(s, type); /* Type */ switch (type) { case TYPE_RDP_NEG_RSP: nego_process_negotiation_response(nego, s); break; case TYPE_RDP_NEG_FAILURE: nego_process_negotiation_failure(nego, s); break; } } else { nego->state = NEGO_STATE_FINAL; } return true; } /** * Read protocol security negotiation request message.\n * @param nego * @param s stream */ boolean nego_read_request(rdpNego* nego, STREAM* s) { uint8 li; uint8 c; uint8 type; tpkt_read_header(s); li = tpdu_read_connection_request(s); if (li != stream_get_left(s) + 6) { printf("Incorrect TPDU length indicator.\n"); return false; } if (stream_get_left(s) > 8) { /* Optional routingToken or cookie, ending with CR+LF */ while (stream_get_left(s) > 0) { stream_read_uint8(s, c); if (c != '\x0D') continue; stream_peek_uint8(s, c); if (c != '\x0A') continue; stream_seek_uint8(s); break; } } if (stream_get_left(s) >= 8) { /* rdpNegData (optional) */ stream_read_uint8(s, type); /* Type */ if (type != TYPE_RDP_NEG_REQ) { printf("Incorrect negotiation request type %d\n", type); return false; } nego_process_negotiation_request(nego, s); } return true; } /** * Send protocol security negotiation message. * @param nego */ void nego_send(rdpNego* nego) { if (nego->state == NEGO_STATE_NLA) nego_attempt_nla(nego); else if (nego->state == NEGO_STATE_TLS) nego_attempt_tls(nego); else if (nego->state == NEGO_STATE_RDP) nego_attempt_rdp(nego); else DEBUG_NEGO("invalid negotiation state for sending"); } /** * Send RDP Negotiation Request (RDP_NEG_REQ).\n * @msdn{cc240500}\n * @msdn{cc240470} * @param nego */ boolean nego_send_negotiation_request(rdpNego* nego) { STREAM* s; int length; uint8 *bm, *em; s = transport_send_stream_init(nego->transport, 256); length = TPDU_CONNECTION_REQUEST_LENGTH; stream_get_mark(s, bm); stream_seek(s, length); if (nego->routing_token != NULL) { stream_write(s, nego->routing_token->data, nego->routing_token->length); length += nego->routing_token->length; } else if (nego->cookie != NULL) { int cookie_length = strlen(nego->cookie); stream_write(s, "Cookie: mstshash=", 17); stream_write(s, (uint8*)nego->cookie, cookie_length); stream_write_uint8(s, 0x0D); /* CR */ stream_write_uint8(s, 0x0A); /* LF */ length += cookie_length + 19; } if (nego->requested_protocols > PROTOCOL_RDP) { /* RDP_NEG_DATA must be present for TLS and NLA */ stream_write_uint8(s, TYPE_RDP_NEG_REQ); stream_write_uint8(s, 0); /* flags, must be set to zero */ stream_write_uint16(s, 8); /* RDP_NEG_DATA length (8) */ stream_write_uint32(s, nego->requested_protocols); /* requestedProtocols */ length += 8; } stream_get_mark(s, em); stream_set_mark(s, bm); tpkt_write_header(s, length); tpdu_write_connection_request(s, length - 5); stream_set_mark(s, em); if (transport_write(nego->transport, s) < 0) return false; return true; } /** * Process Negotiation Request from Connection Request message. * @param nego * @param s */ void nego_process_negotiation_request(rdpNego* nego, STREAM* s) { uint8 flags; uint16 length; DEBUG_NEGO("RDP_NEG_REQ"); stream_read_uint8(s, flags); stream_read_uint16(s, length); stream_read_uint32(s, nego->requested_protocols); nego->state = NEGO_STATE_FINAL; } /** * Process Negotiation Response from Connection Confirm message. * @param nego * @param s */ void nego_process_negotiation_response(rdpNego* nego, STREAM* s) { uint16 length; DEBUG_NEGO("RDP_NEG_RSP"); stream_read_uint8(s, nego->flags); stream_read_uint16(s, length); stream_read_uint32(s, nego->selected_protocol); nego->state = NEGO_STATE_FINAL; } /** * Process Negotiation Failure from Connection Confirm message. * @param nego * @param s */ void nego_process_negotiation_failure(rdpNego* nego, STREAM* s) { uint8 flags; uint16 length; uint32 failureCode; DEBUG_NEGO("RDP_NEG_FAILURE"); stream_read_uint8(s, flags); stream_read_uint16(s, length); stream_read_uint32(s, failureCode); switch (failureCode) { case SSL_REQUIRED_BY_SERVER: DEBUG_NEGO("Error: SSL_REQUIRED_BY_SERVER"); break; case SSL_NOT_ALLOWED_BY_SERVER: DEBUG_NEGO("Error: SSL_NOT_ALLOWED_BY_SERVER"); break; case SSL_CERT_NOT_ON_SERVER: DEBUG_NEGO("Error: SSL_CERT_NOT_ON_SERVER"); break; case INCONSISTENT_FLAGS: DEBUG_NEGO("Error: INCONSISTENT_FLAGS"); break; case HYBRID_REQUIRED_BY_SERVER: DEBUG_NEGO("Error: HYBRID_REQUIRED_BY_SERVER"); break; default: DEBUG_NEGO("Error: Unknown protocol security error %d", failureCode); break; } nego->state = NEGO_STATE_FAIL; } /** * Send RDP Negotiation Response (RDP_NEG_RSP).\n * @param nego */ boolean nego_send_negotiation_response(rdpNego* nego) { STREAM* s; rdpSettings* settings; int length; uint8 *bm, *em; boolean ret; ret = true; settings = nego->transport->settings; s = transport_send_stream_init(nego->transport, 256); length = TPDU_CONNECTION_CONFIRM_LENGTH; stream_get_mark(s, bm); stream_seek(s, length); if (nego->selected_protocol > PROTOCOL_RDP) { /* RDP_NEG_DATA must be present for TLS and NLA */ stream_write_uint8(s, TYPE_RDP_NEG_RSP); stream_write_uint8(s, EXTENDED_CLIENT_DATA_SUPPORTED); /* flags */ stream_write_uint16(s, 8); /* RDP_NEG_DATA length (8) */ stream_write_uint32(s, nego->selected_protocol); /* selectedProtocol */ length += 8; } else if (!settings->rdp_security) { stream_write_uint8(s, TYPE_RDP_NEG_FAILURE); stream_write_uint8(s, 0); /* flags */ stream_write_uint16(s, 8); /* RDP_NEG_DATA length (8) */ /* * TODO: Check for other possibilities, * like SSL_NOT_ALLOWED_BY_SERVER. */ printf("nego_send_negotiation_response: client supports only Standard RDP Security\n"); stream_write_uint32(s, SSL_REQUIRED_BY_SERVER); length += 8; ret = false; } stream_get_mark(s, em); stream_set_mark(s, bm); tpkt_write_header(s, length); tpdu_write_connection_confirm(s, length - 5); stream_set_mark(s, em); if (transport_write(nego->transport, s) < 0) return false; if (ret) { /* update settings with negotiated protocol security */ settings->requested_protocols = nego->requested_protocols; settings->selected_protocol = nego->selected_protocol; if (settings->selected_protocol == PROTOCOL_RDP) { settings->tls_security = false; settings->nla_security = false; settings->rdp_security = true; settings->encryption = true; settings->encryption_method = ENCRYPTION_METHOD_40BIT | ENCRYPTION_METHOD_128BIT | ENCRYPTION_METHOD_FIPS; settings->encryption_level = ENCRYPTION_LEVEL_CLIENT_COMPATIBLE; } else if (settings->selected_protocol == PROTOCOL_TLS) { settings->tls_security = true; settings->nla_security = false; settings->rdp_security = false; settings->encryption = false; settings->encryption_method = ENCRYPTION_METHOD_NONE; settings->encryption_level = ENCRYPTION_LEVEL_NONE; } else if (settings->selected_protocol == PROTOCOL_NLA) { settings->tls_security = true; settings->nla_security = true; settings->rdp_security = false; settings->encryption = false; settings->encryption_method = ENCRYPTION_METHOD_NONE; settings->encryption_level = ENCRYPTION_LEVEL_NONE; } } return ret; } /** * Initialize NEGO state machine. * @param nego */ void nego_init(rdpNego* nego) { nego->state = NEGO_STATE_INITIAL; nego->requested_protocols = PROTOCOL_RDP; nego->transport->recv_callback = nego_recv; nego->transport->recv_extra = (void*) nego; nego->flags = 0; } /** * Create a new NEGO state machine instance. * @param transport * @return */ rdpNego* nego_new(struct rdp_transport * transport) { rdpNego* nego = (rdpNego*) xzalloc(sizeof(rdpNego)); if (nego != NULL) { nego->transport = transport; nego_init(nego); } return nego; } /** * Free NEGO state machine. * @param nego */ void nego_free(rdpNego* nego) { xfree(nego); } /** * Set target hostname and port. * @param nego * @param hostname * @param port */ void nego_set_target(rdpNego* nego, char* hostname, int port) { nego->hostname = hostname; nego->port = port; } /** * Enable RDP security protocol. * @param nego pointer to the negotiation structure * @param enable_rdp whether to enable normal RDP protocol (true for enabled, false for disabled) */ void nego_enable_rdp(rdpNego* nego, boolean enable_rdp) { DEBUG_NEGO("Enabling RDP security: %s", enable_rdp ? "true" : "false"); nego->enabled_protocols[PROTOCOL_RDP] = enable_rdp; } /** * Enable TLS security protocol. * @param nego pointer to the negotiation structure * @param enable_tls whether to enable TLS + RDP protocol (true for enabled, false for disabled) */ void nego_enable_tls(rdpNego* nego, boolean enable_tls) { DEBUG_NEGO("Enabling TLS security: %s", enable_tls ? "true" : "false"); nego->enabled_protocols[PROTOCOL_TLS] = enable_tls; } /** * Enable NLA security protocol. * @param nego pointer to the negotiation structure * @param enable_nla whether to enable network level authentication protocol (true for enabled, false for disabled) */ void nego_enable_nla(rdpNego* nego, boolean enable_nla) { DEBUG_NEGO("Enabling NLA security: %s", enable_nla ? "true" : "false"); nego->enabled_protocols[PROTOCOL_NLA] = enable_nla; } /** * Set routing token. * @param nego * @param routing_token */ void nego_set_routing_token(rdpNego* nego, rdpBlob* routing_token) { nego->routing_token = routing_token; } /** * Set cookie. * @param nego * @param cookie */ void nego_set_cookie(rdpNego* nego, char* cookie) { nego->cookie = cookie; } FreeRDP-1.0.2/libfreerdp-core/nego.h000066400000000000000000000067161207112532300171140ustar00rootroot00000000000000/** * FreeRDP: A Remote Desktop Protocol Client * RDP Protocol Security Negotiation * * Copyright 2011 Marc-Andre Moreau * * 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. */ #ifndef __NEGO_H #define __NEGO_H #include "transport.h" #include #include #include #include #include /* Protocol Security Negotiation Protocols */ enum RDP_NEG_PROTOCOLS { PROTOCOL_RDP = 0x00000000, PROTOCOL_TLS = 0x00000001, PROTOCOL_NLA = 0x00000002 }; /* Protocol Security Negotiation Failure Codes */ enum RDP_NEG_FAILURE_FAILURECODES { SSL_REQUIRED_BY_SERVER = 0x00000001, SSL_NOT_ALLOWED_BY_SERVER = 0x00000002, SSL_CERT_NOT_ON_SERVER = 0x00000003, INCONSISTENT_FLAGS = 0x00000004, HYBRID_REQUIRED_BY_SERVER = 0x00000005 }; enum _NEGO_STATE { NEGO_STATE_INITIAL, NEGO_STATE_NLA, /* Network Level Authentication (TLS implicit) */ NEGO_STATE_TLS, /* TLS Encryption without NLA */ NEGO_STATE_RDP, /* Standard Legacy RDP Encryption */ NEGO_STATE_FAIL, /* Negotiation failure */ NEGO_STATE_FINAL }; typedef enum _NEGO_STATE NEGO_STATE; /* RDP Negotiation Messages */ enum RDP_NEG_MSG { /* X224_TPDU_CONNECTION_REQUEST */ TYPE_RDP_NEG_REQ = 0x1, /* X224_TPDU_CONNECTION_CONFIRM */ TYPE_RDP_NEG_RSP = 0x2, TYPE_RDP_NEG_FAILURE = 0x3 }; #define EXTENDED_CLIENT_DATA_SUPPORTED 0x01 struct rdp_nego { int port; uint32 flags; char* hostname; char* cookie; NEGO_STATE state; int tcp_connected; rdpBlob* routing_token; uint32 selected_protocol; uint32 requested_protocols; uint8 enabled_protocols[3]; rdpTransport* transport; }; typedef struct rdp_nego rdpNego; boolean nego_connect(rdpNego* nego); void nego_attempt_nla(rdpNego* nego); void nego_attempt_tls(rdpNego* nego); void nego_attempt_rdp(rdpNego* nego); void nego_send(rdpNego* nego); boolean nego_recv(rdpTransport* transport, STREAM* s, void* extra); boolean nego_recv_response(rdpNego* nego); boolean nego_read_request(rdpNego* nego, STREAM* s); boolean nego_send_negotiation_request(rdpNego* nego); void nego_process_negotiation_request(rdpNego* nego, STREAM* s); void nego_process_negotiation_response(rdpNego* nego, STREAM* s); void nego_process_negotiation_failure(rdpNego* nego, STREAM* s); boolean nego_send_negotiation_response(rdpNego* nego); rdpNego* nego_new(struct rdp_transport * transport); void nego_free(rdpNego* nego); void nego_init(rdpNego* nego); void nego_set_target(rdpNego* nego, char* hostname, int port); void nego_enable_rdp(rdpNego* nego, boolean enable_rdp); void nego_enable_nla(rdpNego* nego, boolean enable_nla); void nego_enable_tls(rdpNego* nego, boolean enable_tls); void nego_set_routing_token(rdpNego* nego, rdpBlob* routing_token); void nego_set_cookie(rdpNego* nego, char* cookie); #ifdef WITH_DEBUG_NEGO #define DEBUG_NEGO(fmt, ...) DEBUG_CLASS(NEGO, fmt, ## __VA_ARGS__) #else #define DEBUG_NEGO(fmt, ...) DEBUG_NULL(fmt, ## __VA_ARGS__) #endif #endif /* __NEGO_H */ FreeRDP-1.0.2/libfreerdp-core/ntlmssp.c000066400000000000000000001513421207112532300176530ustar00rootroot00000000000000/** * FreeRDP: A Remote Desktop Protocol Client * NT LAN Manager Security Support Provider (NTLMSSP) * * Copyright 2011 Marc-Andre Moreau * * 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. */ #include #include #include #include #include #include #include #include "ntlmssp.h" #define NTLMSSP_NEGOTIATE_56 0x80000000 /* W (0) */ #define NTLMSSP_NEGOTIATE_KEY_EXCH 0x40000000 /* V (1) */ #define NTLMSSP_NEGOTIATE_128 0x20000000 /* U (2) */ #define NTLMSSP_RESERVED1 0x10000000 /* r1 (3) */ #define NTLMSSP_RESERVED2 0x08000000 /* r2 (4) */ #define NTLMSSP_RESERVED3 0x04000000 /* r3 (5) */ #define NTLMSSP_NEGOTIATE_VERSION 0x02000000 /* T (6) */ #define NTLMSSP_RESERVED4 0x01000000 /* r4 (7) */ #define NTLMSSP_NEGOTIATE_TARGET_INFO 0x00800000 /* S (8) */ #define NTLMSSP_RESERVEDEQUEST_NON_NT_SESSION_KEY 0x00400000 /* R (9) */ #define NTLMSSP_RESERVED5 0x00200000 /* r5 (10) */ #define NTLMSSP_NEGOTIATE_IDENTIFY 0x00100000 /* Q (11) */ #define NTLMSSP_NEGOTIATE_EXTENDED_SESSION_SECURITY 0x00080000 /* P (12) */ #define NTLMSSP_RESERVED6 0x00040000 /* r6 (13) */ #define NTLMSSP_TARGET_TYPE_SERVER 0x00020000 /* O (14) */ #define NTLMSSP_TARGET_TYPE_DOMAIN 0x00010000 /* N (15) */ #define NTLMSSP_NEGOTIATE_ALWAYS_SIGN 0x00008000 /* M (16) */ #define NTLMSSP_RESERVED7 0x00004000 /* r7 (17) */ #define NTLMSSP_NEGOTIATE_WORKSTATION_SUPPLIED 0x00002000 /* L (18) */ #define NTLMSSP_NEGOTIATE_DOMAIN_SUPPLIED 0x00001000 /* K (19) */ #define NTLMSSP_NEGOTIATE_ANONYMOUS 0x00000800 /* J (20) */ #define NTLMSSP_RESERVED8 0x00000400 /* r8 (21) */ #define NTLMSSP_NEGOTIATE_NTLM 0x00000200 /* H (22) */ #define NTLMSSP_RESERVED9 0x00000100 /* r9 (23) */ #define NTLMSSP_NEGOTIATE_LM_KEY 0x00000080 /* G (24) */ #define NTLMSSP_NEGOTIATE_DATAGRAM 0x00000040 /* F (25) */ #define NTLMSSP_NEGOTIATE_SEAL 0x00000020 /* E (26) */ #define NTLMSSP_NEGOTIATE_SIGN 0x00000010 /* D (27) */ #define NTLMSSP_RESERVED10 0x00000008 /* r10 (28) */ #define NTLMSSP_REQUEST_TARGET 0x00000004 /* C (29) */ #define NTLMSSP_NEGOTIATE_OEM 0x00000002 /* B (30) */ #define NTLMSSP_NEGOTIATE_UNICODE 0x00000001 /* A (31) */ #define WINDOWS_MAJOR_VERSION_5 0x05 #define WINDOWS_MAJOR_VERSION_6 0x06 #define WINDOWS_MINOR_VERSION_0 0x00 #define WINDOWS_MINOR_VERSION_1 0x01 #define WINDOWS_MINOR_VERSION_2 0x02 #define NTLMSSP_REVISION_W2K3 0x0F static const char ntlm_signature[] = "NTLMSSP"; static const char lm_magic[] = "KGS!@#$%"; static const char client_sign_magic[] = "session key to client-to-server signing key magic constant"; static const char server_sign_magic[] = "session key to server-to-client signing key magic constant"; static const char client_seal_magic[] = "session key to client-to-server sealing key magic constant"; static const char server_seal_magic[] = "session key to server-to-client sealing key magic constant"; static const char* const NTLMSSP_NEGOTIATE_STRINGS[] = { "NTLMSSP_NEGOTIATE_56", "NTLMSSP_NEGOTIATE_KEY_EXCH", "NTLMSSP_NEGOTIATE_128", "NTLMSSP_RESERVED1", "NTLMSSP_RESERVED2", "NTLMSSP_RESERVED3", "NTLMSSP_NEGOTIATE_VERSION", "NTLMSSP_RESERVED4", "NTLMSSP_NEGOTIATE_TARGET_INFO", "NTLMSSP_REQUEST_NON_NT_SESSION_KEY", "NTLMSSP_RESERVED5", "NTLMSSP_NEGOTIATE_IDENTIFY", "NTLMSSP_NEGOTIATE_EXTENDED_SESSION_SECURITY", "NTLMSSP_RESERVED6", "NTLMSSP_TARGET_TYPE_SERVER", "NTLMSSP_TARGET_TYPE_DOMAIN", "NTLMSSP_NEGOTIATE_ALWAYS_SIGN", "NTLMSSP_RESERVED7", "NTLMSSP_NEGOTIATE_WORKSTATION_SUPPLIED", "NTLMSSP_NEGOTIATE_DOMAIN_SUPPLIED", "NTLMSSP_NEGOTIATE_ANONYMOUS", "NTLMSSP_RESERVED8", "NTLMSSP_NEGOTIATE_NTLM", "NTLMSSP_RESERVED9", "NTLMSSP_NEGOTIATE_LM_KEY", "NTLMSSP_NEGOTIATE_DATAGRAM", "NTLMSSP_NEGOTIATE_SEAL", "NTLMSSP_NEGOTIATE_SIGN", "NTLMSSP_RESERVED10", "NTLMSSP_REQUEST_TARGET", "NTLMSSP_NEGOTIATE_OEM", "NTLMSSP_NEGOTIATE_UNICODE" }; static const char* const AV_PAIRS_STRINGS[] = { "MsvAvEOL", "MsvAvNbComputerName", "MsvAvNbDomainName", "MsvAvDnsComputerName", "MsvAvDnsDomainName", "MsvAvDnsTreeName", "MsvAvFlags", "MsvAvTimestamp", "MsvAvRestrictions", "MsvAvTargetName", "MsvChannelBindings" }; /** * Set NTLMSSP username. * @param ntlmssp * @param username username */ void ntlmssp_set_username(NTLMSSP* ntlmssp, char* username) { freerdp_blob_free(&ntlmssp->username); if (username != NULL) { ntlmssp->username.data = freerdp_uniconv_out(ntlmssp->uniconv, username, (size_t*) &(ntlmssp->username.length)); } } /** * Set NTLMSSP domain name. * @param ntlmssp * @param domain domain name */ void ntlmssp_set_domain(NTLMSSP* ntlmssp, char* domain) { freerdp_blob_free(&ntlmssp->domain); if (domain != NULL) { ntlmssp->domain.data = freerdp_uniconv_out(ntlmssp->uniconv, domain, (size_t*) &(ntlmssp->domain.length)); } } /** * Set NTLMSSP password. * @param ntlmssp * @param password password */ void ntlmssp_set_password(NTLMSSP* ntlmssp, char* password) { freerdp_blob_free(&ntlmssp->password); if (password != NULL) { ntlmssp->password.data = freerdp_uniconv_out(ntlmssp->uniconv, password, (size_t*) &(ntlmssp->password.length)); } } /** * Set NTLMSSP workstation. * @param ntlmssp * @param workstation workstation */ void ntlmssp_set_workstation(NTLMSSP* ntlmssp, char* workstation) { freerdp_blob_free(&ntlmssp->workstation); if (workstation != NULL) { ntlmssp->workstation.data = freerdp_uniconv_out(ntlmssp->uniconv, workstation, (size_t*) &(ntlmssp->workstation.length)); } } /** * Generate client challenge (8-byte nonce). * @param ntlmssp */ void ntlmssp_generate_client_challenge(NTLMSSP* ntlmssp) { /* ClientChallenge in computation of LMv2 and NTLMv2 responses */ crypto_nonce(ntlmssp->client_challenge, 8); } /** * Generate KeyExchangeKey (the 128-bit SessionBaseKey).\n * @msdn{cc236710} * @param ntlmssp */ void ntlmssp_generate_key_exchange_key(NTLMSSP* ntlmssp) { /* In NTLMv2, KeyExchangeKey is the 128-bit SessionBaseKey */ memcpy(ntlmssp->key_exchange_key, ntlmssp->session_base_key, 16); } /** * Generate RandomSessionKey (16-byte nonce). * @param ntlmssp */ void ntlmssp_generate_random_session_key(NTLMSSP* ntlmssp) { crypto_nonce(ntlmssp->random_session_key, 16); } /** * Generate ExportedSessionKey (the RandomSessionKey, exported) * @param ntlmssp */ void ntlmssp_generate_exported_session_key(NTLMSSP* ntlmssp) { memcpy(ntlmssp->exported_session_key, ntlmssp->random_session_key, 16); } /** * Encrypt RandomSessionKey (RC4-encrypted RandomSessionKey, using KeyExchangeKey as the key). * @param ntlmssp */ void ntlmssp_encrypt_random_session_key(NTLMSSP* ntlmssp) { /* In NTLMv2, EncryptedRandomSessionKey is the ExportedSessionKey RC4-encrypted with the KeyExchangeKey */ credssp_rc4k(ntlmssp->key_exchange_key, 16, ntlmssp->random_session_key, ntlmssp->encrypted_random_session_key); } /** * Generate timestamp for AUTHENTICATE_MESSAGE. * @param ntlmssp */ void ntlmssp_generate_timestamp(NTLMSSP* ntlmssp) { credssp_current_time(ntlmssp->timestamp); if (ntlmssp->ntlm_v2) { if (ntlmssp->av_pairs->Timestamp.length == 8) { memcpy(ntlmssp->av_pairs->Timestamp.value, ntlmssp->timestamp, 8); return; } } else { if (ntlmssp->av_pairs->Timestamp.length != 8) { ntlmssp->av_pairs->Timestamp.length = 8; ntlmssp->av_pairs->Timestamp.value = xmalloc(ntlmssp->av_pairs->Timestamp.length); } memcpy(ntlmssp->av_pairs->Timestamp.value, ntlmssp->timestamp, 8); } } /** * Generate signing key.\n * @msdn{cc236711} * @param exported_session_key ExportedSessionKey * @param sign_magic Sign magic string * @param signing_key Destination signing key */ void ntlmssp_generate_signing_key(uint8* exported_session_key, rdpBlob* sign_magic, uint8* signing_key) { int length; uint8* value; CryptoMd5 md5; length = 16 + sign_magic->length; value = (uint8*) xmalloc(length); /* Concatenate ExportedSessionKey with sign magic */ memcpy(value, exported_session_key, 16); memcpy(&value[16], sign_magic->data, sign_magic->length); md5 = crypto_md5_init(); crypto_md5_update(md5, value, length); crypto_md5_final(md5, signing_key); xfree(value); } /** * Generate client signing key (ClientSigningKey).\n * @msdn{cc236711} * @param ntlmssp */ void ntlmssp_generate_client_signing_key(NTLMSSP* ntlmssp) { rdpBlob sign_magic; sign_magic.data = (void*) client_sign_magic; sign_magic.length = sizeof(client_sign_magic); ntlmssp_generate_signing_key(ntlmssp->exported_session_key, &sign_magic, ntlmssp->client_signing_key); } /** * Generate server signing key (ServerSigningKey).\n * @msdn{cc236711} * @param ntlmssp */ void ntlmssp_generate_server_signing_key(NTLMSSP* ntlmssp) { rdpBlob sign_magic; sign_magic.data = (void*) server_sign_magic; sign_magic.length = sizeof(server_sign_magic); ntlmssp_generate_signing_key(ntlmssp->exported_session_key, &sign_magic, ntlmssp->server_signing_key); } /** * Generate sealing key.\n * @msdn{cc236712} * @param exported_session_key ExportedSessionKey * @param seal_magic Seal magic string * @param sealing_key Destination sealing key */ void ntlmssp_generate_sealing_key(uint8* exported_session_key, rdpBlob* seal_magic, uint8* sealing_key) { uint8* p; CryptoMd5 md5; rdpBlob blob; freerdp_blob_alloc(&blob, 16 + seal_magic->length); p = (uint8*) blob.data; /* Concatenate ExportedSessionKey with seal magic */ memcpy(p, exported_session_key, 16); memcpy(&p[16], seal_magic->data, seal_magic->length); md5 = crypto_md5_init(); crypto_md5_update(md5, blob.data, blob.length); crypto_md5_final(md5, sealing_key); freerdp_blob_free(&blob); } /** * Generate client sealing key (ClientSealingKey).\n * @msdn{cc236712} * @param ntlmssp */ void ntlmssp_generate_client_sealing_key(NTLMSSP* ntlmssp) { rdpBlob seal_magic; seal_magic.data = (void*) client_seal_magic; seal_magic.length = sizeof(client_seal_magic); ntlmssp_generate_signing_key(ntlmssp->exported_session_key, &seal_magic, ntlmssp->client_sealing_key); } /** * Generate server sealing key (ServerSealingKey).\n * @msdn{cc236712} * @param ntlmssp */ void ntlmssp_generate_server_sealing_key(NTLMSSP* ntlmssp) { rdpBlob seal_magic; seal_magic.data = (void*) server_seal_magic; seal_magic.length = sizeof(server_seal_magic); ntlmssp_generate_signing_key(ntlmssp->exported_session_key, &seal_magic, ntlmssp->server_sealing_key); } /** * Initialize RC4 stream cipher states for sealing. * @param ntlmssp */ void ntlmssp_init_rc4_seal_states(NTLMSSP* ntlmssp) { ntlmssp->send_rc4_seal = crypto_rc4_init(ntlmssp->client_sealing_key, 16); ntlmssp->recv_rc4_seal = crypto_rc4_init(ntlmssp->server_sealing_key, 16); } /** * Get bit from a byte buffer using a bit offset. * @param buffer byte buffer * @param bit bit offset * @return bit value */ static int get_bit(char* buffer, int bit) { return (buffer[(bit - (bit % 8)) / 8] >> (7 - bit % 8) & 1); } /** * Set bit in a byte buffer using a bit offset. * @param buffer byte buffer * @param bit bit offset * @param value bit value */ static void set_bit(char* buffer, int bit, int value) { buffer[(bit - (bit % 8)) / 8] |= value << (7 - bit % 8); } static void ntlmssp_compute_des_key(char* text, char* des_key) { int i, j; int bit; int nbits; /* Convert the 7 bytes into a bit stream, and insert a parity-bit (odd parity) after every seven bits. */ memset(des_key, '\0', 8); for (i = 0; i < 8; i++) { nbits = 0; for (j = 0; j < 7; j++) { /* copy 7 bits, and count the number of bits that are set */ bit = get_bit(text, i*7 + j); set_bit(des_key, i*7 + i + j, bit); nbits += bit; } /* insert parity bit (odd parity) */ if (nbits % 2 == 0) set_bit(des_key, i*7 + i + j, 1); } } void ntlmssp_compute_lm_hash(char* password, char* hash) { int i; int maxlen; char text[14]; char des_key1[8]; char des_key2[8]; des_key_schedule ks; /* LM("password") = E52CAC67419A9A224A3B108F3FA6CB6D */ maxlen = (strlen(password) < 14) ? strlen(password) : 14; /* convert to uppercase */ for (i = 0; i < maxlen; i++) { if ((password[i] >= 'a') && (password[i] <= 'z')) text[i] = password[i] - 32; else text[i] = password[i]; } /* pad with nulls up to 14 bytes */ for (i = maxlen; i < 14; i++) text[i] = '\0'; ntlmssp_compute_des_key(text, des_key1); ntlmssp_compute_des_key(&text[7], des_key2); DES_set_key((const_DES_cblock*)des_key1, &ks); DES_ecb_encrypt((const_DES_cblock*) lm_magic, (DES_cblock*)hash, &ks, DES_ENCRYPT); DES_set_key((const_DES_cblock*)des_key2, &ks); DES_ecb_encrypt((const_DES_cblock*) lm_magic, (DES_cblock*)&hash[8], &ks, DES_ENCRYPT); } void ntlmssp_compute_ntlm_hash(rdpBlob* password, char* hash) { /* NTLMv1("password") = 8846F7EAEE8FB117AD06BDD830B7586C */ MD4_CTX md4_ctx; /* Password needs to be in unicode */ /* Apply the MD4 digest algorithm on the password in unicode, the result is the NTLM hash */ MD4_Init(&md4_ctx); MD4_Update(&md4_ctx, password->data, password->length); MD4_Final((void*) hash, &md4_ctx); } void ntlmssp_compute_ntlm_v2_hash(NTLMSSP* ntlmssp, char* hash) { char* p; rdpBlob blob; char ntlm_hash[16]; freerdp_blob_alloc(&blob, ntlmssp->username.length + ntlmssp->domain.length); p = (char*) blob.data; /* First, compute the NTLMv1 hash of the password */ ntlmssp_compute_ntlm_hash(&ntlmssp->password, ntlm_hash); /* Concatenate(Uppercase(username),domain)*/ memcpy(p, ntlmssp->username.data, ntlmssp->username.length); freerdp_uniconv_uppercase(ntlmssp->uniconv, p, ntlmssp->username.length / 2); memcpy(&p[ntlmssp->username.length], ntlmssp->domain.data, ntlmssp->domain.length); /* Compute the HMAC-MD5 hash of the above value using the NTLMv1 hash as the key, the result is the NTLMv2 hash */ HMAC(EVP_md5(), (void*) ntlm_hash, 16, blob.data, blob.length, (void*) hash, NULL); freerdp_blob_free(&blob); } void ntlmssp_compute_lm_response(char* password, char* challenge, char* response) { char hash[21]; char des_key1[8]; char des_key2[8]; char des_key3[8]; des_key_schedule ks; /* A LM hash is 16-bytes long, but the LM response uses a LM hash null-padded to 21 bytes */ memset(hash, '\0', 21); ntlmssp_compute_lm_hash(password, hash); /* Each 7-byte third of the 21-byte null-padded LM hash is used to create a DES key */ ntlmssp_compute_des_key(hash, des_key1); ntlmssp_compute_des_key(&hash[7], des_key2); ntlmssp_compute_des_key(&hash[14], des_key3); /* Encrypt the LM challenge with each key, and concatenate the result. This is the LM response (24 bytes) */ DES_set_key((const_DES_cblock*)des_key1, &ks); DES_ecb_encrypt((const_DES_cblock*)challenge, (DES_cblock*)response, &ks, DES_ENCRYPT); DES_set_key((const_DES_cblock*)des_key2, &ks); DES_ecb_encrypt((const_DES_cblock*)challenge, (DES_cblock*)&response[8], &ks, DES_ENCRYPT); DES_set_key((const_DES_cblock*)des_key3, &ks); DES_ecb_encrypt((const_DES_cblock*)challenge, (DES_cblock*)&response[16], &ks, DES_ENCRYPT); } void ntlmssp_compute_lm_v2_response(NTLMSSP* ntlmssp) { char *response; char value[16]; char ntlm_v2_hash[16]; /* Compute the NTLMv2 hash */ ntlmssp_compute_ntlm_v2_hash(ntlmssp, ntlm_v2_hash); /* Concatenate the server and client challenges */ memcpy(value, ntlmssp->server_challenge, 8); memcpy(&value[8], ntlmssp->client_challenge, 8); freerdp_blob_alloc(&ntlmssp->lm_challenge_response, 24); response = (char*) ntlmssp->lm_challenge_response.data; /* Compute the HMAC-MD5 hash of the resulting value using the NTLMv2 hash as the key */ HMAC(EVP_md5(), (void*) ntlm_v2_hash, 16, (void*) value, 16, (void*) response, NULL); /* Concatenate the resulting HMAC-MD5 hash and the client challenge, giving us the LMv2 response (24 bytes) */ memcpy(&response[16], ntlmssp->client_challenge, 8); } /** * Compute NTLMv2 Response.\n * NTLMv2_RESPONSE @msdn{cc236653}\n * NTLMv2 Authentication @msdn{cc236700} * @param ntlmssp */ void ntlmssp_compute_ntlm_v2_response(NTLMSSP* ntlmssp) { uint8* blob; uint8 ntlm_v2_hash[16]; uint8 nt_proof_str[16]; rdpBlob ntlm_v2_temp; rdpBlob ntlm_v2_temp_chal; freerdp_blob_alloc(&ntlm_v2_temp, ntlmssp->target_info.length + 28); memset(ntlm_v2_temp.data, '\0', ntlm_v2_temp.length); blob = (uint8*) ntlm_v2_temp.data; /* Compute the NTLMv2 hash */ ntlmssp_compute_ntlm_v2_hash(ntlmssp, (char*) ntlm_v2_hash); #ifdef WITH_DEBUG_NLA printf("Password (length = %d)\n", ntlmssp->password.length); freerdp_hexdump(ntlmssp->password.data, ntlmssp->password.length); printf("\n"); printf("Username (length = %d)\n", ntlmssp->username.length); freerdp_hexdump(ntlmssp->username.data, ntlmssp->username.length); printf("\n"); printf("Domain (length = %d)\n", ntlmssp->domain.length); freerdp_hexdump(ntlmssp->domain.data, ntlmssp->domain.length); printf("\n"); printf("Workstation (length = %d)\n", ntlmssp->workstation.length); freerdp_hexdump(ntlmssp->workstation.data, ntlmssp->workstation.length); printf("\n"); printf("NTOWFv2, NTLMv2 Hash\n"); freerdp_hexdump(ntlm_v2_hash, 16); printf("\n"); #endif /* Construct temp */ blob[0] = 1; /* RespType (1 byte) */ blob[1] = 1; /* HighRespType (1 byte) */ /* Reserved1 (2 bytes) */ /* Reserved2 (4 bytes) */ memcpy(&blob[8], ntlmssp->av_pairs->Timestamp.value, 8); /* Timestamp (8 bytes) */ memcpy(&blob[16], ntlmssp->client_challenge, 8); /* ClientChallenge (8 bytes) */ /* Reserved3 (4 bytes) */ memcpy(&blob[28], ntlmssp->target_info.data, ntlmssp->target_info.length); #ifdef WITH_DEBUG_NLA printf("NTLMv2 Response Temp Blob\n"); freerdp_hexdump(ntlm_v2_temp.data, ntlm_v2_temp.length); printf("\n"); #endif /* Concatenate server challenge with temp */ freerdp_blob_alloc(&ntlm_v2_temp_chal, ntlm_v2_temp.length + 8); blob = (uint8*) ntlm_v2_temp_chal.data; memcpy(blob, ntlmssp->server_challenge, 8); memcpy(&blob[8], ntlm_v2_temp.data, ntlm_v2_temp.length); HMAC(EVP_md5(), (void*) ntlm_v2_hash, 16, (void*) ntlm_v2_temp_chal.data, ntlm_v2_temp_chal.length, (void*) nt_proof_str, NULL); /* NtChallengeResponse, Concatenate NTProofStr with temp */ freerdp_blob_alloc(&ntlmssp->nt_challenge_response, ntlm_v2_temp.length + 16); blob = (uint8*) ntlmssp->nt_challenge_response.data; memcpy(blob, nt_proof_str, 16); memcpy(&blob[16], ntlm_v2_temp.data, ntlm_v2_temp.length); /* Compute SessionBaseKey, the HMAC-MD5 hash of NTProofStr using the NTLMv2 hash as the key */ HMAC(EVP_md5(), (void*) ntlm_v2_hash, 16, (void*) nt_proof_str, 16, (void*) ntlmssp->session_base_key, NULL); freerdp_blob_free(&ntlm_v2_temp); freerdp_blob_free(&ntlm_v2_temp_chal); } /** * Input NegotiateFlags, a 4-byte bit map. * @param s * @param flags */ void ntlmssp_input_negotiate_flags(STREAM* s, uint32* flags) { *flags = 0; stream_read_uint32(s, *flags); } /** * Output NegotiateFlags, a 4-byte bit map. * @param s * @param flags */ void ntlmssp_output_negotiate_flags(STREAM* s, uint32 flags) { stream_write_uint32(s, flags); } void ntlmssp_print_negotiate_flags(uint32 flags) { int i; const char* str; printf("negotiateFlags \"0x%08X\"{\n", flags); for (i = 31; i >= 0; i--) { if ((flags >> i) & 1) { str = NTLMSSP_NEGOTIATE_STRINGS[(31 - i)]; printf("\t%s (%d),\n", str, (31 - i)); } } printf("}\n"); } /** * Output Restriction_Encoding.\n * Restriction_Encoding @msdn{cc236647} * @param ntlmssp */ static void ntlmssp_output_restriction_encoding(NTLMSSP* ntlmssp) { AV_PAIR *restrictions = &ntlmssp->av_pairs->Restrictions; STREAM* s = stream_new(0); uint8 machineID[32] = "\x3A\x15\x8E\xA6\x75\x82\xD8\xF7\x3E\x06\xFA\x7A\xB4\xDF\xFD\x43" "\x84\x6C\x02\x3A\xFD\x5A\x94\xFE\xCF\x97\x0F\x3D\x19\x2C\x38\x20"; restrictions->value = xmalloc(48); restrictions->length = 48; s->data = restrictions->value; s->size = restrictions->length; s->p = s->data; stream_write_uint32(s, 48); /* Size */ stream_write_zero(s, 4); /* Z4 (set to zero) */ /* IntegrityLevel (bit 31 set to 1) */ stream_write_uint8(s, 1); stream_write_zero(s, 3); stream_write_uint32(s, 0x00002000); /* SubjectIntegrityLevel */ stream_write(s, machineID, 32); /* MachineID */ xfree(s); } /** * Output TargetName.\n * @param ntlmssp */ void ntlmssp_output_target_name(NTLMSSP* ntlmssp) { STREAM* s = stream_new(0); AV_PAIR* target_name = &ntlmssp->av_pairs->TargetName; /* * TODO: No idea what should be set here (observed MsvAvTargetName = MsvAvDnsComputerName or * MsvAvTargetName should be the name of the service be accessed after authentication) * here used: "TERMSRV/192.168.0.123" in unicode (Dmitrij Jasnov) */ uint8 name[42] = "\x54\x00\x45\x00\x52\x00\x4d\x00\x53\x00\x52\x00\x56\x00\x2f\x00\x31\x00\x39\x00\x32" "\x00\x2e\x00\x31\x00\x36\x00\x38\x00\x2e\x00\x30\x00\x2e\x00\x31\x00\x32\x00\x33\x00"; target_name->length = 42; target_name->value = (uint8*) xmalloc(target_name->length); s->data = target_name->value; s->size = target_name->length; s->p = s->data; stream_write(s, name, target_name->length); xfree(s); } /** * Output ChannelBindings.\n * @param ntlmssp */ void ntlmssp_output_channel_bindings(NTLMSSP* ntlmssp) { STREAM* s = stream_new(0); AV_PAIR* channel_bindings = &ntlmssp->av_pairs->ChannelBindings; channel_bindings->value = (uint8*) xmalloc(48); channel_bindings->length = 16; s->data = channel_bindings->value; s->size = channel_bindings->length; s->p = s->data; stream_write_zero(s, 16); /* an all-zero value of the hash is used to indicate absence of channel bindings */ xfree(s); } /** * Populate array of AV_PAIRs.\n * AV_PAIR @msdn{cc236646} * @param ntlmssp */ void ntlmssp_populate_av_pairs(NTLMSSP* ntlmssp) { STREAM* s; rdpBlob target_info; AV_PAIRS *av_pairs = ntlmssp->av_pairs; /* MsvAvFlags */ av_pairs->Flags = 0x00000002; /* Indicates the present of a Message Integrity Check (MIC) */ /* Restriction_Encoding */ ntlmssp_output_restriction_encoding(ntlmssp); /* TargetName */ ntlmssp_output_target_name(ntlmssp); /* ChannelBindings */ ntlmssp_output_channel_bindings(ntlmssp); s = stream_new(0); s->data = xmalloc(ntlmssp->target_info.length + 512); s->p = s->data; ntlmssp_output_av_pairs(ntlmssp, s); freerdp_blob_alloc(&target_info, s->p - s->data); memcpy(target_info.data, s->data, target_info.length); ntlmssp->target_info.data = target_info.data; ntlmssp->target_info.length = target_info.length; } /** * Input array of AV_PAIRs.\n * AV_PAIR @msdn{cc236646} * @param ntlmssp * @param s */ void ntlmssp_input_av_pairs(NTLMSSP* ntlmssp, STREAM* s) { AV_ID AvId; uint16 AvLen; uint8* value; AV_PAIRS* av_pairs = ntlmssp->av_pairs; #ifdef WITH_DEBUG_NLA printf("AV_PAIRS = {\n"); #endif do { value = NULL; stream_read_uint16(s, AvId); stream_read_uint16(s, AvLen); if (AvLen > 0) { if (AvId != MsvAvFlags) { value = xmalloc(AvLen); stream_read(s, value, AvLen); } else { stream_read_uint32(s, av_pairs->Flags); } } switch (AvId) { case MsvAvNbComputerName: av_pairs->NbComputerName.length = AvLen; av_pairs->NbComputerName.value = value; break; case MsvAvNbDomainName: av_pairs->NbDomainName.length = AvLen; av_pairs->NbDomainName.value = value; break; case MsvAvDnsComputerName: av_pairs->DnsComputerName.length = AvLen; av_pairs->DnsComputerName.value = value; break; case MsvAvDnsDomainName: av_pairs->DnsDomainName.length = AvLen; av_pairs->DnsDomainName.value = value; break; case MsvAvDnsTreeName: av_pairs->DnsTreeName.length = AvLen; av_pairs->DnsTreeName.value = value; break; case MsvAvTimestamp: av_pairs->Timestamp.length = AvLen; av_pairs->Timestamp.value = value; break; case MsvAvRestrictions: av_pairs->Restrictions.length = AvLen; av_pairs->Restrictions.value = value; break; case MsvAvTargetName: av_pairs->TargetName.length = AvLen; av_pairs->TargetName.value = value; break; case MsvChannelBindings: av_pairs->ChannelBindings.length = AvLen; av_pairs->ChannelBindings.value = value; break; default: if (value != NULL) xfree(value); break; } #ifdef WITH_DEBUG_NLA if (AvId < 10) printf("\tAvId: %s, AvLen: %d\n", AV_PAIRS_STRINGS[AvId], AvLen); else printf("\tAvId: %s, AvLen: %d\n", "Unknown", AvLen); freerdp_hexdump(value, AvLen); #endif } while (AvId != MsvAvEOL); #ifdef WITH_DEBUG_NLA printf("}\n"); #endif } /** * Output array of AV_PAIRs.\n * AV_PAIR @msdn{cc236646} * @param ntlmssp * @param s */ void ntlmssp_output_av_pairs(NTLMSSP* ntlmssp, STREAM* s) { AV_PAIRS* av_pairs = ntlmssp->av_pairs; if (av_pairs->NbDomainName.length > 0) { stream_write_uint16(s, MsvAvNbDomainName); /* AvId */ stream_write_uint16(s, av_pairs->NbDomainName.length); /* AvLen */ stream_write(s, av_pairs->NbDomainName.value, av_pairs->NbDomainName.length); /* Value */ } if (av_pairs->NbComputerName.length > 0) { stream_write_uint16(s, MsvAvNbComputerName); /* AvId */ stream_write_uint16(s, av_pairs->NbComputerName.length); /* AvLen */ stream_write(s, av_pairs->NbComputerName.value, av_pairs->NbComputerName.length); /* Value */ } if (av_pairs->DnsDomainName.length > 0) { stream_write_uint16(s, MsvAvDnsDomainName); /* AvId */ stream_write_uint16(s, av_pairs->DnsDomainName.length); /* AvLen */ stream_write(s, av_pairs->DnsDomainName.value, av_pairs->DnsDomainName.length); /* Value */ } if (av_pairs->DnsComputerName.length > 0) { stream_write_uint16(s, MsvAvDnsComputerName); /* AvId */ stream_write_uint16(s, av_pairs->DnsComputerName.length); /* AvLen */ stream_write(s, av_pairs->DnsComputerName.value, av_pairs->DnsComputerName.length); /* Value */ } if (av_pairs->DnsTreeName.length > 0) { stream_write_uint16(s, MsvAvDnsTreeName); /* AvId */ stream_write_uint16(s, av_pairs->DnsTreeName.length); /* AvLen */ stream_write(s, av_pairs->DnsTreeName.value, av_pairs->DnsTreeName.length); /* Value */ } if (av_pairs->Timestamp.length > 0) { stream_write_uint16(s, MsvAvTimestamp); /* AvId */ stream_write_uint16(s, av_pairs->Timestamp.length); /* AvLen */ stream_write(s, av_pairs->Timestamp.value, av_pairs->Timestamp.length); /* Value */ } if (av_pairs->Flags > 0) { stream_write_uint16(s, MsvAvFlags); /* AvId */ stream_write_uint16(s, 4); /* AvLen */ stream_write_uint32(s, av_pairs->Flags); /* Value */ } if (av_pairs->Restrictions.length > 0) { stream_write_uint16(s, MsvAvRestrictions); /* AvId */ stream_write_uint16(s, av_pairs->Restrictions.length); /* AvLen */ stream_write(s, av_pairs->Restrictions.value, av_pairs->Restrictions.length); /* Value */ } if (av_pairs->ChannelBindings.length > 0) { stream_write_uint16(s, MsvChannelBindings); /* AvId */ stream_write_uint16(s, av_pairs->ChannelBindings.length); /* AvLen */ stream_write(s, av_pairs->ChannelBindings.value, av_pairs->ChannelBindings.length); /* Value */ } if (av_pairs->TargetName.length > 0) { stream_write_uint16(s, MsvAvTargetName); /* AvId */ stream_write_uint16(s, av_pairs->TargetName.length); /* AvLen */ stream_write(s, av_pairs->TargetName.value, av_pairs->TargetName.length); /* Value */ } /* This indicates the end of the AV_PAIR array */ stream_write_uint16(s, MsvAvEOL); /* AvId */ stream_write_uint16(s, 0); /* AvLen */ if (ntlmssp->ntlm_v2) { stream_write_zero(s, 8); } } /** * Print array of AV_PAIRs.\n * AV_PAIR @msdn{cc236646} * @param ntlmssp * @param s */ void ntlmssp_print_av_pairs(NTLMSSP* ntlmssp) { AV_PAIRS* av_pairs = ntlmssp->av_pairs; printf("AV_PAIRS = {\n"); if (av_pairs->NbDomainName.length > 0) { printf("\tAvId: MsvAvNbDomainName AvLen: %d\n", av_pairs->NbDomainName.length); freerdp_hexdump(av_pairs->NbDomainName.value, av_pairs->NbDomainName.length); } if (av_pairs->NbComputerName.length > 0) { printf("\tAvId: MsvAvNbComputerName AvLen: %d\n", av_pairs->NbComputerName.length); freerdp_hexdump(av_pairs->NbComputerName.value, av_pairs->NbComputerName.length); } if (av_pairs->DnsDomainName.length > 0) { printf("\tAvId: MsvAvDnsDomainName AvLen: %d\n", av_pairs->DnsDomainName.length); freerdp_hexdump(av_pairs->DnsDomainName.value, av_pairs->DnsDomainName.length); } if (av_pairs->DnsComputerName.length > 0) { printf("\tAvId: MsvAvDnsComputerName AvLen: %d\n", av_pairs->DnsComputerName.length); freerdp_hexdump(av_pairs->DnsComputerName.value, av_pairs->DnsComputerName.length); } if (av_pairs->DnsTreeName.length > 0) { printf("\tAvId: MsvAvDnsTreeName AvLen: %d\n", av_pairs->DnsTreeName.length); freerdp_hexdump(av_pairs->DnsTreeName.value, av_pairs->DnsTreeName.length); } if (av_pairs->Timestamp.length > 0) { printf("\tAvId: MsvAvTimestamp AvLen: %d\n", av_pairs->Timestamp.length); freerdp_hexdump(av_pairs->Timestamp.value, av_pairs->Timestamp.length); } if (av_pairs->Flags > 0) { printf("\tAvId: MsvAvFlags AvLen: %d\n", 4); printf("0x%08X\n", av_pairs->Flags); } if (av_pairs->Restrictions.length > 0) { printf("\tAvId: MsvAvRestrictions AvLen: %d\n", av_pairs->Restrictions.length); freerdp_hexdump(av_pairs->Restrictions.value, av_pairs->Restrictions.length); } if (av_pairs->ChannelBindings.length > 0) { printf("\tAvId: MsvChannelBindings AvLen: %d\n", av_pairs->ChannelBindings.length); freerdp_hexdump(av_pairs->ChannelBindings.value, av_pairs->ChannelBindings.length); } if (av_pairs->TargetName.length > 0) { printf("\tAvId: MsvAvTargetName AvLen: %d\n", av_pairs->TargetName.length); freerdp_hexdump(av_pairs->TargetName.value, av_pairs->TargetName.length); } printf("}\n"); } /** * Free array of AV_PAIRs.\n * AV_PAIR @msdn{cc236646} * @param ntlmssp */ void ntlmssp_free_av_pairs(NTLMSSP* ntlmssp) { AV_PAIRS *av_pairs = ntlmssp->av_pairs; if (av_pairs != NULL) { if (av_pairs->NbComputerName.value != NULL) xfree(av_pairs->NbComputerName.value); if (av_pairs->NbDomainName.value != NULL) xfree(av_pairs->NbDomainName.value); if (av_pairs->DnsComputerName.value != NULL) xfree(av_pairs->DnsComputerName.value); if (av_pairs->DnsDomainName.value != NULL) xfree(av_pairs->DnsDomainName.value); if (av_pairs->DnsTreeName.value != NULL) xfree(av_pairs->DnsTreeName.value); if (av_pairs->Timestamp.value != NULL) xfree(av_pairs->Timestamp.value); if (av_pairs->Restrictions.value != NULL) xfree(av_pairs->Restrictions.value); if (av_pairs->TargetName.value != NULL) xfree(av_pairs->TargetName.value); if (av_pairs->ChannelBindings.value != NULL) xfree(av_pairs->ChannelBindings.value); xfree(av_pairs); } ntlmssp->av_pairs = NULL; } /** * Output VERSION structure.\n * VERSION @msdn{cc236654} * @param s */ static void ntlmssp_output_version(STREAM* s) { /* The following version information was observed with Windows 7 */ stream_write_uint8(s, WINDOWS_MAJOR_VERSION_6); /* ProductMajorVersion (1 byte) */ stream_write_uint8(s, WINDOWS_MINOR_VERSION_1); /* ProductMinorVersion (1 byte) */ stream_write_uint16(s, 7600); /* ProductBuild (2 bytes) */ stream_write_zero(s, 3); /* Reserved (3 bytes) */ stream_write_uint8(s, NTLMSSP_REVISION_W2K3); /* NTLMRevisionCurrent (1 byte) */ } void ntlmssp_compute_message_integrity_check(NTLMSSP* ntlmssp) { HMAC_CTX hmac_ctx; /* * Compute the HMAC-MD5 hash of ConcatenationOf(NEGOTIATE_MESSAGE, * CHALLENGE_MESSAGE, AUTHENTICATE_MESSAGE) using the ExportedSessionKey */ HMAC_CTX_init(&hmac_ctx); HMAC_Init_ex(&hmac_ctx, ntlmssp->exported_session_key, 16, EVP_md5(), NULL); HMAC_Update(&hmac_ctx, ntlmssp->negotiate_message.data, ntlmssp->negotiate_message.length); HMAC_Update(&hmac_ctx, ntlmssp->challenge_message.data, ntlmssp->challenge_message.length); HMAC_Update(&hmac_ctx, ntlmssp->authenticate_message.data, ntlmssp->authenticate_message.length); HMAC_Final(&hmac_ctx, ntlmssp->message_integrity_check, NULL); } /** * Encrypt and sign message using NTLMSSP.\n * GSS_WrapEx() @msdn{cc236718}\n * EncryptMessage() @msdn{aa375378} * @param ntlmssp * @param[in] msg message to encrypt * @param[out] encrypted_msg encrypted message * @param[out] signature destination signature */ void ntlmssp_encrypt_message(NTLMSSP* ntlmssp, rdpBlob* msg, rdpBlob* encrypted_msg, uint8* signature) { HMAC_CTX hmac_ctx; uint8 digest[16]; uint8 checksum[8]; uint32 version = 1; /* Compute the HMAC-MD5 hash of ConcatenationOf(seq_num,msg) using the client signing key */ HMAC_CTX_init(&hmac_ctx); HMAC_Init_ex(&hmac_ctx, ntlmssp->client_signing_key, 16, EVP_md5(), NULL); HMAC_Update(&hmac_ctx, (void*) &ntlmssp->send_seq_num, 4); HMAC_Update(&hmac_ctx, msg->data, msg->length); HMAC_Final(&hmac_ctx, digest, NULL); /* Allocate space for encrypted message */ freerdp_blob_alloc(encrypted_msg, msg->length); /* Encrypt message using with RC4 */ crypto_rc4(ntlmssp->send_rc4_seal, msg->length, msg->data, encrypted_msg->data); /* RC4-encrypt first 8 bytes of digest */ crypto_rc4(ntlmssp->send_rc4_seal, 8, digest, checksum); /* Concatenate version, ciphertext and sequence number to build signature */ memcpy(signature, (void*) &version, 4); memcpy(&signature[4], (void*) checksum, 8); memcpy(&signature[12], (void*) &(ntlmssp->send_seq_num), 4); HMAC_CTX_cleanup(&hmac_ctx); ntlmssp->send_seq_num++; } /** * Decrypt message and verify signature using NTLMSSP.\n * GSS_UnwrapEx() @msdn{cc236703}\n * DecryptMessage() @msdn{aa375211} * @param ntlmssp * @param[in] encrypted_msg encrypted message * @param[out] msg decrypted message * @param[in] signature signature * @return */ int ntlmssp_decrypt_message(NTLMSSP* ntlmssp, rdpBlob* encrypted_msg, rdpBlob* msg, uint8* signature) { HMAC_CTX hmac_ctx; uint8 digest[16]; uint8 checksum[8]; uint32 version = 1; uint8 expected_signature[16]; /* Allocate space for encrypted message */ freerdp_blob_alloc(msg, encrypted_msg->length); /* Encrypt message using with RC4 */ crypto_rc4(ntlmssp->recv_rc4_seal, encrypted_msg->length, encrypted_msg->data, msg->data); /* Compute the HMAC-MD5 hash of ConcatenationOf(seq_num,msg) using the client signing key */ HMAC_CTX_init(&hmac_ctx); HMAC_Init_ex(&hmac_ctx, ntlmssp->server_signing_key, 16, EVP_md5(), NULL); HMAC_Update(&hmac_ctx, (void*) &ntlmssp->recv_seq_num, 4); HMAC_Update(&hmac_ctx, msg->data, msg->length); HMAC_Final(&hmac_ctx, digest, NULL); /* RC4-encrypt first 8 bytes of digest */ crypto_rc4(ntlmssp->recv_rc4_seal, 8, digest, checksum); /* Concatenate version, ciphertext and sequence number to build signature */ memcpy(expected_signature, (void*) &version, 4); memcpy(&expected_signature[4], (void*) checksum, 8); memcpy(&expected_signature[12], (void*) &(ntlmssp->recv_seq_num), 4); if (memcmp(signature, expected_signature, 16) != 0) { /* signature verification failed! */ printf("signature verification failed, something nasty is going on!\n"); return 0; } HMAC_CTX_cleanup(&hmac_ctx); ntlmssp->recv_seq_num++; return 1; } /** * Send NTLMSSP NEGOTIATE_MESSAGE.\n * NEGOTIATE_MESSAGE @msdn{cc236641} * @param ntlmssp * @param s */ void ntlmssp_send_negotiate_message(NTLMSSP* ntlmssp, STREAM* s) { int length; uint32 negotiateFlags = 0; stream_write(s, ntlm_signature, 8); /* Signature (8 bytes) */ stream_write_uint32(s, 1); /* MessageType */ if (ntlmssp->ntlm_v2) { DEBUG_NLA("Negotiating NTLMv2"); /* observed: B7 82 08 E2 (0xE20882B7) (Dmitrij Jasnov) */ negotiateFlags |= NTLMSSP_NEGOTIATE_56; negotiateFlags |= NTLMSSP_NEGOTIATE_KEY_EXCH; negotiateFlags |= NTLMSSP_NEGOTIATE_128; negotiateFlags |= NTLMSSP_NEGOTIATE_VERSION; negotiateFlags |= NTLMSSP_NEGOTIATE_EXTENDED_SESSION_SECURITY; negotiateFlags |= NTLMSSP_NEGOTIATE_ALWAYS_SIGN; negotiateFlags |= NTLMSSP_NEGOTIATE_NTLM; negotiateFlags |= NTLMSSP_NEGOTIATE_LM_KEY; negotiateFlags |= NTLMSSP_NEGOTIATE_SEAL; negotiateFlags |= NTLMSSP_NEGOTIATE_SIGN; negotiateFlags |= NTLMSSP_REQUEST_TARGET; negotiateFlags |= NTLMSSP_NEGOTIATE_OEM; negotiateFlags |= NTLMSSP_NEGOTIATE_UNICODE; } else { negotiateFlags |= NTLMSSP_NEGOTIATE_KEY_EXCH; negotiateFlags |= NTLMSSP_NEGOTIATE_128; negotiateFlags |= NTLMSSP_NEGOTIATE_EXTENDED_SESSION_SECURITY; negotiateFlags |= NTLMSSP_NEGOTIATE_ALWAYS_SIGN; negotiateFlags |= NTLMSSP_NEGOTIATE_NTLM; negotiateFlags |= NTLMSSP_NEGOTIATE_SEAL; negotiateFlags |= NTLMSSP_NEGOTIATE_SIGN; negotiateFlags |= NTLMSSP_REQUEST_TARGET; negotiateFlags |= NTLMSSP_NEGOTIATE_UNICODE; } ntlmssp_output_negotiate_flags(s, negotiateFlags); /* NegotiateFlags (4 bytes) */ #ifdef WITH_DEBUG_NLA ntlmssp_print_negotiate_flags(negotiateFlags); #endif /* only set if NTLMSSP_NEGOTIATE_DOMAIN_SUPPLIED is set */ /* DomainNameFields (8 bytes) */ stream_write_uint16(s, 0); /* DomainNameLen */ stream_write_uint16(s, 0); /* DomainNameMaxLen */ stream_write_uint32(s, 0); /* DomainNameBufferOffset */ /* only set if NTLMSSP_NEGOTIATE_WORKSTATION_SUPPLIED is set */ /* WorkstationFields (8 bytes) */ stream_write_uint16(s, 0); /* WorkstationLen */ stream_write_uint16(s, 0); /* WorkstationMaxLen */ stream_write_uint32(s, 0); /* WorkstationBufferOffset */ if (negotiateFlags & NTLMSSP_NEGOTIATE_VERSION) { /* Only present if NTLMSSP_NEGOTIATE_VERSION is set */ ntlmssp_output_version(s); #ifdef WITH_DEBUG_NLA printf("Version (length = 8)\n"); freerdp_hexdump((s->p - 8), 8); printf("\n"); #endif } length = s->p - s->data; freerdp_blob_alloc(&ntlmssp->negotiate_message, length); memcpy(ntlmssp->negotiate_message.data, s->data, length); #ifdef WITH_DEBUG_NLA printf("NEGOTIATE_MESSAGE (length = %d)\n", length); freerdp_hexdump(s->data, length); printf("\n"); #endif ntlmssp->state = NTLMSSP_STATE_CHALLENGE; } /** * Receive NTLMSSP CHALLENGE_MESSAGE.\n * CHALLENGE_MESSAGE @msdn{cc236642} * @param ntlmssp * @param s */ void ntlmssp_recv_challenge_message(NTLMSSP* ntlmssp, STREAM* s) { uint8* p; int length; uint8* start_offset; uint8* payload_offset; uint16 targetNameLen; uint16 targetNameMaxLen; uint32 targetNameBufferOffset; uint16 targetInfoLen; uint16 targetInfoMaxLen; uint32 targetInfoBufferOffset; start_offset = s->p - 12; /* TargetNameFields (8 bytes) */ stream_read_uint16(s, targetNameLen); /* TargetNameLen (2 bytes) */ stream_read_uint16(s, targetNameMaxLen); /* TargetNameMaxLen (2 bytes) */ stream_read_uint32(s, targetNameBufferOffset); /* TargetNameBufferOffset (4 bytes) */ ntlmssp_input_negotiate_flags(s, &(ntlmssp->negotiate_flags)); /* NegotiateFlags (4 bytes) */ #ifdef WITH_DEBUG_NLA ntlmssp_print_negotiate_flags(ntlmssp->negotiate_flags); #endif stream_read(s, ntlmssp->server_challenge, 8); /* ServerChallenge (8 bytes) */ stream_seek(s, 8); /* Reserved (8 bytes), should be ignored */ /* TargetInfoFields (8 bytes) */ stream_read_uint16(s, targetInfoLen); /* TargetInfoLen (2 bytes) */ stream_read_uint16(s, targetInfoMaxLen); /* TargetInfoMaxLen (2 bytes) */ stream_read_uint32(s, targetInfoBufferOffset); /* TargetInfoBufferOffset (4 bytes) */ /* only present if NTLMSSP_NEGOTIATE_VERSION is set */ if (ntlmssp->negotiate_flags & NTLMSSP_NEGOTIATE_VERSION) { stream_seek(s, 8); /* Version (8 bytes), can be ignored */ } /* Payload (variable) */ payload_offset = s->p; if (targetNameLen > 0) { p = start_offset + targetNameBufferOffset; freerdp_blob_alloc(&ntlmssp->target_name, targetNameLen); memcpy(ntlmssp->target_name.data, p, targetNameLen); #ifdef WITH_DEBUG_NLA printf("targetName (length = %d, offset = %d)\n", targetNameLen, targetNameBufferOffset); freerdp_hexdump(ntlmssp->target_name.data, ntlmssp->target_name.length); printf("\n"); #endif } if (targetInfoLen > 0) { p = start_offset + targetInfoBufferOffset; freerdp_blob_alloc(&ntlmssp->target_info, targetInfoLen); memcpy(ntlmssp->target_info.data, p, targetInfoLen); #ifdef WITH_DEBUG_NLA printf("targetInfo (length = %d, offset = %d)\n", targetInfoLen, targetInfoBufferOffset); freerdp_hexdump(ntlmssp->target_info.data, ntlmssp->target_info.length); printf("\n"); #endif if (ntlmssp->ntlm_v2) { s->p = p; ntlmssp_input_av_pairs(ntlmssp, s); } } length = (payload_offset - start_offset) + targetNameLen + targetInfoLen; freerdp_blob_alloc(&ntlmssp->challenge_message, length); memcpy(ntlmssp->challenge_message.data, start_offset, length); #ifdef WITH_DEBUG_NLA printf("CHALLENGE_MESSAGE (length = %d)\n", length); freerdp_hexdump(start_offset, length); printf("\n"); #endif /* AV_PAIRs */ if (ntlmssp->ntlm_v2) ntlmssp_populate_av_pairs(ntlmssp); /* Timestamp */ ntlmssp_generate_timestamp(ntlmssp); /* LmChallengeResponse */ ntlmssp_compute_lm_v2_response(ntlmssp); if (ntlmssp->ntlm_v2) memset(ntlmssp->lm_challenge_response.data, '\0', 24); /* NtChallengeResponse */ ntlmssp_compute_ntlm_v2_response(ntlmssp); /* KeyExchangeKey */ ntlmssp_generate_key_exchange_key(ntlmssp); /* EncryptedRandomSessionKey */ ntlmssp_encrypt_random_session_key(ntlmssp); /* Generate signing keys */ ntlmssp_generate_client_signing_key(ntlmssp); ntlmssp_generate_server_signing_key(ntlmssp); /* Generate sealing keys */ ntlmssp_generate_client_sealing_key(ntlmssp); ntlmssp_generate_server_sealing_key(ntlmssp); /* Initialize RC4 seal state using client sealing key */ ntlmssp_init_rc4_seal_states(ntlmssp); #ifdef WITH_DEBUG_NLA printf("ClientChallenge\n"); freerdp_hexdump(ntlmssp->client_challenge, 8); printf("\n"); printf("ServerChallenge\n"); freerdp_hexdump(ntlmssp->server_challenge, 8); printf("\n"); printf("SessionBaseKey\n"); freerdp_hexdump(ntlmssp->session_base_key, 16); printf("\n"); printf("KeyExchangeKey\n"); freerdp_hexdump(ntlmssp->key_exchange_key, 16); printf("\n"); printf("ExportedSessionKey\n"); freerdp_hexdump(ntlmssp->exported_session_key, 16); printf("\n"); printf("RandomSessionKey\n"); freerdp_hexdump(ntlmssp->random_session_key, 16); printf("\n"); printf("ClientSignKey\n"); freerdp_hexdump(ntlmssp->client_signing_key, 16); printf("\n"); printf("ClientSealingKey\n"); freerdp_hexdump(ntlmssp->client_sealing_key, 16); printf("\n"); printf("Timestamp\n"); freerdp_hexdump(ntlmssp->timestamp, 8); printf("\n"); #endif ntlmssp->state = NTLMSSP_STATE_AUTHENTICATE; } /** * Send NTLMSSP AUTHENTICATE_MESSAGE.\n * AUTHENTICATE_MESSAGE @msdn{cc236643} * @param ntlmssp * @param s */ void ntlmssp_send_authenticate_message(NTLMSSP* ntlmssp, STREAM* s) { int length; uint32 negotiateFlags = 0; uint8* mic_offset = NULL; uint16 DomainNameLen; uint16 UserNameLen; uint16 WorkstationLen; uint16 LmChallengeResponseLen; uint16 NtChallengeResponseLen; uint16 EncryptedRandomSessionKeyLen; uint32 PayloadBufferOffset; uint32 DomainNameBufferOffset; uint32 UserNameBufferOffset; uint32 WorkstationBufferOffset; uint32 LmChallengeResponseBufferOffset; uint32 NtChallengeResponseBufferOffset; uint32 EncryptedRandomSessionKeyBufferOffset; uint8* UserNameBuffer; uint8* DomainNameBuffer; uint8* WorkstationBuffer; uint8* EncryptedRandomSessionKeyBuffer; WorkstationLen = ntlmssp->workstation.length; WorkstationBuffer = ntlmssp->workstation.data; if (ntlmssp->ntlm_v2 < 1) WorkstationLen = 0; DomainNameLen = ntlmssp->domain.length; DomainNameBuffer = ntlmssp->domain.data; UserNameLen = ntlmssp->username.length; UserNameBuffer = ntlmssp->username.data; LmChallengeResponseLen = ntlmssp->lm_challenge_response.length; NtChallengeResponseLen = ntlmssp->nt_challenge_response.length; EncryptedRandomSessionKeyLen = 16; EncryptedRandomSessionKeyBuffer = ntlmssp->encrypted_random_session_key; if (ntlmssp->ntlm_v2) { /* observed: 35 82 88 e2 (0xE2888235) */ negotiateFlags |= NTLMSSP_NEGOTIATE_56; negotiateFlags |= NTLMSSP_NEGOTIATE_KEY_EXCH; negotiateFlags |= NTLMSSP_NEGOTIATE_128; negotiateFlags |= NTLMSSP_NEGOTIATE_VERSION; negotiateFlags |= NTLMSSP_NEGOTIATE_TARGET_INFO; negotiateFlags |= NTLMSSP_NEGOTIATE_EXTENDED_SESSION_SECURITY; negotiateFlags |= NTLMSSP_NEGOTIATE_ALWAYS_SIGN; negotiateFlags |= NTLMSSP_NEGOTIATE_NTLM; negotiateFlags |= NTLMSSP_NEGOTIATE_SEAL; negotiateFlags |= NTLMSSP_NEGOTIATE_SIGN; negotiateFlags |= NTLMSSP_REQUEST_TARGET; negotiateFlags |= NTLMSSP_NEGOTIATE_UNICODE; } else { negotiateFlags |= NTLMSSP_NEGOTIATE_KEY_EXCH; negotiateFlags |= NTLMSSP_NEGOTIATE_128; negotiateFlags |= NTLMSSP_NEGOTIATE_EXTENDED_SESSION_SECURITY; negotiateFlags |= NTLMSSP_NEGOTIATE_ALWAYS_SIGN; negotiateFlags |= NTLMSSP_NEGOTIATE_NTLM; negotiateFlags |= NTLMSSP_NEGOTIATE_SEAL; negotiateFlags |= NTLMSSP_NEGOTIATE_SIGN; negotiateFlags |= NTLMSSP_REQUEST_TARGET; negotiateFlags |= NTLMSSP_NEGOTIATE_UNICODE; } if (ntlmssp->ntlm_v2) PayloadBufferOffset = 80; /* starting buffer offset */ else PayloadBufferOffset = 64; /* starting buffer offset */ if (negotiateFlags & NTLMSSP_NEGOTIATE_VERSION) PayloadBufferOffset += 8; DomainNameBufferOffset = PayloadBufferOffset; UserNameBufferOffset = DomainNameBufferOffset + DomainNameLen; WorkstationBufferOffset = UserNameBufferOffset + UserNameLen; LmChallengeResponseBufferOffset = WorkstationBufferOffset + WorkstationLen; NtChallengeResponseBufferOffset = LmChallengeResponseBufferOffset + LmChallengeResponseLen; EncryptedRandomSessionKeyBufferOffset = NtChallengeResponseBufferOffset + NtChallengeResponseLen; stream_write(s, ntlm_signature, 8); /* Signature (8 bytes) */ stream_write_uint32(s, 3); /* MessageType */ /* LmChallengeResponseFields (8 bytes) */ stream_write_uint16(s, LmChallengeResponseLen); /* LmChallengeResponseLen */ stream_write_uint16(s, LmChallengeResponseLen); /* LmChallengeResponseMaxLen */ stream_write_uint32(s, LmChallengeResponseBufferOffset); /* LmChallengeResponseBufferOffset */ /* NtChallengeResponseFields (8 bytes) */ stream_write_uint16(s, NtChallengeResponseLen); /* NtChallengeResponseLen */ stream_write_uint16(s, NtChallengeResponseLen); /* NtChallengeResponseMaxLen */ stream_write_uint32(s, NtChallengeResponseBufferOffset); /* NtChallengeResponseBufferOffset */ /* only set if NTLMSSP_NEGOTIATE_DOMAIN_SUPPLIED is set */ /* DomainNameFields (8 bytes) */ stream_write_uint16(s, DomainNameLen); /* DomainNameLen */ stream_write_uint16(s, DomainNameLen); /* DomainNameMaxLen */ stream_write_uint32(s, DomainNameBufferOffset); /* DomainNameBufferOffset */ /* UserNameFields (8 bytes) */ stream_write_uint16(s, UserNameLen); /* UserNameLen */ stream_write_uint16(s, UserNameLen); /* UserNameMaxLen */ stream_write_uint32(s, UserNameBufferOffset); /* UserNameBufferOffset */ /* only set if NTLMSSP_NEGOTIATE_WORKSTATION_SUPPLIED is set */ /* WorkstationFields (8 bytes) */ stream_write_uint16(s, WorkstationLen); /* WorkstationLen */ stream_write_uint16(s, WorkstationLen); /* WorkstationMaxLen */ stream_write_uint32(s, WorkstationBufferOffset); /* WorkstationBufferOffset */ /* EncryptedRandomSessionKeyFields (8 bytes) */ stream_write_uint16(s, EncryptedRandomSessionKeyLen); /* EncryptedRandomSessionKeyLen */ stream_write_uint16(s, EncryptedRandomSessionKeyLen); /* EncryptedRandomSessionKeyMaxLen */ stream_write_uint32(s, EncryptedRandomSessionKeyBufferOffset); /* EncryptedRandomSessionKeyBufferOffset */ ntlmssp_output_negotiate_flags(s, negotiateFlags); /* NegotiateFlags (4 bytes) */ #ifdef WITH_DEBUG_NLA ntlmssp_print_negotiate_flags(negotiateFlags); #endif if (negotiateFlags & NTLMSSP_NEGOTIATE_VERSION) { /* Only present if NTLMSSP_NEGOTIATE_VERSION is set */ ntlmssp_output_version(s); #ifdef WITH_DEBUG_NLA printf("Version (length = 8)\n"); freerdp_hexdump((s->p - 8), 8); printf("\n"); #endif } if (ntlmssp->ntlm_v2) { /* Message Integrity Check */ mic_offset = s->p; stream_write_zero(s, 16); } /* DomainName */ if (DomainNameLen > 0) { stream_write(s, DomainNameBuffer, DomainNameLen); #ifdef WITH_DEBUG_NLA printf("DomainName (length = %d, offset = %d)\n", DomainNameLen, DomainNameBufferOffset); freerdp_hexdump(DomainNameBuffer, DomainNameLen); printf("\n"); #endif } /* UserName */ stream_write(s, UserNameBuffer, UserNameLen); #ifdef WITH_DEBUG_NLA printf("UserName (length = %d, offset = %d)\n", UserNameLen, UserNameBufferOffset); freerdp_hexdump(UserNameBuffer, UserNameLen); printf("\n"); #endif /* Workstation */ if (WorkstationLen > 0) { stream_write(s, WorkstationBuffer, WorkstationLen); #ifdef WITH_DEBUG_NLA printf("Workstation (length = %d, offset = %d)\n", WorkstationLen, WorkstationBufferOffset); freerdp_hexdump(WorkstationBuffer, WorkstationLen); printf("\n"); #endif } /* LmChallengeResponse */ stream_write(s, ntlmssp->lm_challenge_response.data, LmChallengeResponseLen); #ifdef WITH_DEBUG_NLA printf("LmChallengeResponse (length = %d, offset = %d)\n", LmChallengeResponseLen, LmChallengeResponseBufferOffset); freerdp_hexdump(ntlmssp->lm_challenge_response.data, LmChallengeResponseLen); printf("\n"); #endif /* NtChallengeResponse */ stream_write(s, ntlmssp->nt_challenge_response.data, NtChallengeResponseLen); #ifdef WITH_DEBUG_NLA if (ntlmssp->ntlm_v2) { ntlmssp_print_av_pairs(ntlmssp); printf("targetInfo (length = %d)\n", ntlmssp->target_info.length); freerdp_hexdump(ntlmssp->target_info.data, ntlmssp->target_info.length); printf("\n"); } #endif #ifdef WITH_DEBUG_NLA printf("NtChallengeResponse (length = %d, offset = %d)\n", NtChallengeResponseLen, NtChallengeResponseBufferOffset); freerdp_hexdump(ntlmssp->nt_challenge_response.data, NtChallengeResponseLen); printf("\n"); #endif /* EncryptedRandomSessionKey */ stream_write(s, EncryptedRandomSessionKeyBuffer, EncryptedRandomSessionKeyLen); #ifdef WITH_DEBUG_NLA printf("EncryptedRandomSessionKey (length = %d, offset = %d)\n", EncryptedRandomSessionKeyLen, EncryptedRandomSessionKeyBufferOffset); freerdp_hexdump(EncryptedRandomSessionKeyBuffer, EncryptedRandomSessionKeyLen); printf("\n"); #endif length = s->p - s->data; freerdp_blob_alloc(&ntlmssp->authenticate_message, length); memcpy(ntlmssp->authenticate_message.data, s->data, length); if (ntlmssp->ntlm_v2) { /* Message Integrity Check */ ntlmssp_compute_message_integrity_check(ntlmssp); s->p = mic_offset; stream_write(s, ntlmssp->message_integrity_check, 16); s->p = s->data + length; #ifdef WITH_DEBUG_NLA printf("MessageIntegrityCheck (length = 16)\n"); freerdp_hexdump(mic_offset, 16); printf("\n"); #endif } #ifdef WITH_DEBUG_NLA printf("AUTHENTICATE_MESSAGE (length = %d)\n", length); freerdp_hexdump(s->data, length); printf("\n"); #endif ntlmssp->state = NTLMSSP_STATE_FINAL; } /** * Send NTLMSSP message. * @param ntlmssp * @param s * @return */ int ntlmssp_send(NTLMSSP* ntlmssp, STREAM* s) { if (ntlmssp->state == NTLMSSP_STATE_INITIAL) ntlmssp->state = NTLMSSP_STATE_NEGOTIATE; if (ntlmssp->state == NTLMSSP_STATE_NEGOTIATE) ntlmssp_send_negotiate_message(ntlmssp, s); else if (ntlmssp->state == NTLMSSP_STATE_AUTHENTICATE) ntlmssp_send_authenticate_message(ntlmssp, s); return (ntlmssp->state == NTLMSSP_STATE_FINAL) ? 0 : 1; } /** * Receive NTLMSSP message. * @param ntlmssp * @param s * @return */ int ntlmssp_recv(NTLMSSP* ntlmssp, STREAM* s) { char signature[8]; /* Signature, "NTLMSSP" */ uint32 messageType; /* MessageType */ stream_read(s, signature, 8); stream_read_uint32(s, messageType); if (messageType == 2 && ntlmssp->state == NTLMSSP_STATE_CHALLENGE) ntlmssp_recv_challenge_message(ntlmssp, s); return 1; } /** * Create new NTLMSSP state machine instance. * @return */ NTLMSSP* ntlmssp_new() { NTLMSSP* ntlmssp = (NTLMSSP*) xmalloc(sizeof(NTLMSSP)); if (ntlmssp != NULL) { memset(ntlmssp, '\0', sizeof(NTLMSSP)); ntlmssp->av_pairs = (AV_PAIRS*) xmalloc(sizeof(AV_PAIRS)); memset(ntlmssp->av_pairs, 0, sizeof(AV_PAIRS)); ntlmssp_init(ntlmssp); } return ntlmssp; } /** * Initialize NTLMSSP state machine. * @param ntlmssp */ void ntlmssp_init(NTLMSSP* ntlmssp) { ntlmssp->state = NTLMSSP_STATE_INITIAL; ntlmssp->uniconv = freerdp_uniconv_new(); } /** * Finalize NTLMSSP state machine. * @param ntlmssp */ void ntlmssp_uninit(NTLMSSP* ntlmssp) { freerdp_blob_free(&ntlmssp->username); freerdp_blob_free(&ntlmssp->password); freerdp_blob_free(&ntlmssp->domain); freerdp_blob_free(&ntlmssp->spn); freerdp_blob_free(&ntlmssp->workstation); freerdp_blob_free(&ntlmssp->target_info); freerdp_blob_free(&ntlmssp->target_name); freerdp_blob_free(&ntlmssp->negotiate_message); freerdp_blob_free(&ntlmssp->challenge_message); freerdp_blob_free(&ntlmssp->authenticate_message); freerdp_blob_free(&ntlmssp->lm_challenge_response); freerdp_blob_free(&ntlmssp->nt_challenge_response); ntlmssp_free_av_pairs(ntlmssp); freerdp_uniconv_free(ntlmssp->uniconv); ntlmssp->state = NTLMSSP_STATE_FINAL; } /** * Free NTLMSSP state machine. * @param ntlmssp */ void ntlmssp_free(NTLMSSP* ntlmssp) { ntlmssp_uninit(ntlmssp); if (ntlmssp->send_rc4_seal) crypto_rc4_free(ntlmssp->send_rc4_seal); if (ntlmssp->recv_rc4_seal) crypto_rc4_free(ntlmssp->recv_rc4_seal); xfree(ntlmssp); } FreeRDP-1.0.2/libfreerdp-core/ntlmssp.h000066400000000000000000000113151207112532300176530ustar00rootroot00000000000000/** * FreeRDP: A Remote Desktop Protocol Client * NT LAN Manager Security Support Provider (NTLMSSP) * * Copyright 2011 Marc-Andre Moreau * * 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. */ #ifndef __NTLMSSP_H #define __NTLMSSP_H #include "credssp.h" #include #include #include #include struct _AV_PAIR { uint16 length; uint8* value; }; typedef struct _AV_PAIR AV_PAIR; struct _AV_PAIRS { AV_PAIR NbComputerName; AV_PAIR NbDomainName; AV_PAIR DnsComputerName; AV_PAIR DnsDomainName; AV_PAIR DnsTreeName; AV_PAIR Timestamp; AV_PAIR Restrictions; AV_PAIR TargetName; AV_PAIR ChannelBindings; uint32 Flags; }; typedef struct _AV_PAIRS AV_PAIRS; enum _AV_ID { MsvAvEOL, MsvAvNbComputerName, MsvAvNbDomainName, MsvAvDnsComputerName, MsvAvDnsDomainName, MsvAvDnsTreeName, MsvAvFlags, MsvAvTimestamp, MsvAvRestrictions, MsvAvTargetName, MsvChannelBindings }; typedef enum _AV_ID AV_ID; enum _NTLMSSP_STATE { NTLMSSP_STATE_INITIAL, NTLMSSP_STATE_NEGOTIATE, NTLMSSP_STATE_CHALLENGE, NTLMSSP_STATE_AUTHENTICATE, NTLMSSP_STATE_FINAL }; typedef enum _NTLMSSP_STATE NTLMSSP_STATE; struct _NTLMSSP { NTLMSSP_STATE state; rdpBlob password; rdpBlob username; rdpBlob domain; rdpBlob workstation; rdpBlob target_info; rdpBlob target_name; rdpBlob spn; UNICONV *uniconv; uint32 negotiate_flags; uint8 timestamp[8]; uint8 server_challenge[8]; uint8 client_challenge[8]; uint8 session_base_key[16]; uint8 key_exchange_key[16]; uint8 random_session_key[16]; uint8 exported_session_key[16]; uint8 encrypted_random_session_key[16]; uint8 client_signing_key[16]; uint8 client_sealing_key[16]; uint8 server_signing_key[16]; uint8 server_sealing_key[16]; uint8 message_integrity_check[16]; rdpBlob nt_challenge_response; rdpBlob lm_challenge_response; rdpBlob negotiate_message; rdpBlob challenge_message; rdpBlob authenticate_message; CryptoRc4 send_rc4_seal; CryptoRc4 recv_rc4_seal; AV_PAIRS *av_pairs; int send_seq_num; int recv_seq_num; int ntlm_v2; }; typedef struct _NTLMSSP NTLMSSP; void ntlmssp_set_username(NTLMSSP* ntlmssp, char* username); void ntlmssp_set_domain(NTLMSSP* ntlmssp, char* domain); void ntlmssp_set_password(NTLMSSP* ntlmssp, char* password); void ntlmssp_set_workstation(NTLMSSP* ntlmssp, char* workstation); void ntlmssp_generate_client_challenge(NTLMSSP* ntlmssp); void ntlmssp_generate_key_exchange_key(NTLMSSP* ntlmssp); void ntlmssp_generate_random_session_key(NTLMSSP* ntlmssp); void ntlmssp_generate_exported_session_key(NTLMSSP* ntlmssp); void ntlmssp_encrypt_random_session_key(NTLMSSP* ntlmssp); void ntlmssp_generate_timestamp(NTLMSSP* ntlmssp); void ntlmssp_generate_client_signing_key(NTLMSSP* ntlmssp); void ntlmssp_generate_server_signing_key(NTLMSSP* ntlmssp); void ntlmssp_generate_client_sealing_key(NTLMSSP* ntlmssp); void ntlmssp_generate_server_sealing_key(NTLMSSP* ntlmssp); void ntlmssp_init_rc4_seal_states(NTLMSSP* ntlmssp); void ntlmssp_compute_lm_hash(char* password, char* hash); void ntlmssp_compute_ntlm_hash(rdpBlob* password, char* hash); void ntlmssp_compute_ntlm_v2_hash(NTLMSSP* ntlmssp, char* hash); void ntlmssp_compute_lm_response(char* password, char* challenge, char* response); void ntlmssp_compute_lm_v2_response(NTLMSSP* ntlmssp); void ntlmssp_compute_ntlm_v2_response(NTLMSSP* ntlmssp); void ntlmssp_populate_av_pairs(NTLMSSP* ntlmssp); void ntlmssp_input_av_pairs(NTLMSSP* ntlmssp, STREAM* s); void ntlmssp_output_av_pairs(NTLMSSP* ntlmssp, STREAM* s); void ntlmssp_free_av_pairs(NTLMSSP* ntlmssp); void ntlmssp_compute_message_integrity_check(NTLMSSP* ntlmssp); void ntlmssp_encrypt_message(NTLMSSP* ntlmssp, rdpBlob* msg, rdpBlob* encrypted_msg, uint8* signature); int ntlmssp_decrypt_message(NTLMSSP* ntlmssp, rdpBlob* encrypted_msg, rdpBlob* msg, uint8* signature); int ntlmssp_recv(NTLMSSP* ntlmssp, STREAM* s); int ntlmssp_send(NTLMSSP* ntlmssp, STREAM* s); NTLMSSP* ntlmssp_new(); void ntlmssp_init(NTLMSSP* ntlmssp); void ntlmssp_free(NTLMSSP* ntlmssp); #ifdef WITH_DEBUG_NLA #define DEBUG_NLA(fmt, ...) DEBUG_CLASS(NLA, fmt, ## __VA_ARGS__) #else #define DEBUG_NLA(fmt, ...) DEBUG_NULL(fmt, ## __VA_ARGS__) #endif #endif /* __NTLMSSP_H */ FreeRDP-1.0.2/libfreerdp-core/orders.c000066400000000000000000001736511207112532300174600ustar00rootroot00000000000000/** * FreeRDP: A Remote Desktop Protocol Client * Drawing Orders * * Copyright 2011 Marc-Andre Moreau * * 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. */ #include "window.h" #include #include #include #include "orders.h" #ifdef WITH_DEBUG_ORDERS static const char* const PRIMARY_DRAWING_ORDER_STRINGS[] = { "DstBlt", "PatBlt", "ScrBlt", "", "", "", "", "DrawNineGrid", "MultiDrawNineGrid", "LineTo", "OpaqueRect", "SaveBitmap", "", "MemBlt", "Mem3Blt", "MultiDstBlt", "MultiPatBlt", "MultiScrBlt", "MultiOpaqueRect", "FastIndex", "PolygonSC", "PolygonCB", "Polyline", "", "FastGlyph", "EllipseSC", "EllipseCB", "GlyphIndex" }; #define PRIMARY_DRAWING_ORDER_COUNT (sizeof(PRIMARY_DRAWING_ORDER_STRINGS) / sizeof(PRIMARY_DRAWING_ORDER_STRINGS[0])) static const char* const SECONDARY_DRAWING_ORDER_STRINGS[] = { "Cache Bitmap", "Cache Color Table", "Cache Bitmap (Compressed)", "Cache Glyph", "Cache Bitmap V2", "Cache Bitmap V2 (Compressed)", "", "Cache Brush", "Cache Bitmap V3" }; #define SECONDARY_DRAWING_ORDER_COUNT (sizeof(SECONDARY_DRAWING_ORDER_STRINGS) / sizeof(SECONDARY_DRAWING_ORDER_STRINGS[0])) static const char* const ALTSEC_DRAWING_ORDER_STRINGS[] = { "Switch Surface", "Create Offscreen Bitmap", "Stream Bitmap First", "Stream Bitmap Next", "Create NineGrid Bitmap", "Draw GDI+ First", "Draw GDI+ Next", "Draw GDI+ End", "Draw GDI+ Cache First", "Draw GDI+ Cache Next", "Draw GDI+ Cache End", "Windowing", "Desktop Composition", "Frame Marker" }; #define ALTSEC_DRAWING_ORDER_COUNT (sizeof(ALTSEC_DRAWING_ORDER_STRINGS) / sizeof(ALTSEC_DRAWING_ORDER_STRINGS[0])) #endif /* WITH_DEBUG_ORDERS */ static const uint8 PRIMARY_DRAWING_ORDER_FIELD_BYTES[] = { DSTBLT_ORDER_FIELD_BYTES, PATBLT_ORDER_FIELD_BYTES, SCRBLT_ORDER_FIELD_BYTES, 0, 0, 0, 0, DRAW_NINE_GRID_ORDER_FIELD_BYTES, MULTI_DRAW_NINE_GRID_ORDER_FIELD_BYTES, LINE_TO_ORDER_FIELD_BYTES, OPAQUE_RECT_ORDER_FIELD_BYTES, SAVE_BITMAP_ORDER_FIELD_BYTES, 0, MEMBLT_ORDER_FIELD_BYTES, MEM3BLT_ORDER_FIELD_BYTES, MULTI_DSTBLT_ORDER_FIELD_BYTES, MULTI_PATBLT_ORDER_FIELD_BYTES, MULTI_SCRBLT_ORDER_FIELD_BYTES, MULTI_OPAQUE_RECT_ORDER_FIELD_BYTES, FAST_INDEX_ORDER_FIELD_BYTES, POLYGON_SC_ORDER_FIELD_BYTES, POLYGON_CB_ORDER_FIELD_BYTES, POLYLINE_ORDER_FIELD_BYTES, 0, FAST_GLYPH_ORDER_FIELD_BYTES, ELLIPSE_SC_ORDER_FIELD_BYTES, ELLIPSE_CB_ORDER_FIELD_BYTES, GLYPH_INDEX_ORDER_FIELD_BYTES }; static const uint8 CBR2_BPP[] = { 0, 0, 0, 8, 16, 24, 32 }; static const uint8 CBR23_BPP[] = { 0, 0, 0, 8, 16, 24, 32 }; static const uint8 BMF_BPP[] = { 0, 1, 0, 8, 16, 24, 32 }; INLINE void update_read_coord(STREAM* s, sint32* coord, boolean delta) { sint8 lsi8; sint16 lsi16; if (delta) { stream_read_uint8(s, lsi8); *coord += lsi8; } else { stream_read_uint16(s, lsi16); *coord = lsi16; } } INLINE void update_read_color(STREAM* s, uint32* color) { uint8 byte; stream_read_uint8(s, byte); *color = byte; stream_read_uint8(s, byte); *color |= (byte << 8); stream_read_uint8(s, byte); *color |= (byte << 16); } INLINE void update_read_colorref(STREAM* s, uint32* color) { uint8 byte; stream_read_uint8(s, byte); *color = byte; stream_read_uint8(s, byte); *color |= (byte << 8); stream_read_uint8(s, byte); *color |= (byte << 16); stream_seek_uint8(s); } INLINE void update_read_color_quad(STREAM* s, uint32* color) { uint8 byte; stream_read_uint8(s, byte); *color = (byte << 16); stream_read_uint8(s, byte); *color |= (byte << 8); stream_read_uint8(s, byte); *color |= byte; stream_seek_uint8(s); } INLINE void update_read_2byte_unsigned(STREAM* s, uint32* value) { uint8 byte; stream_read_uint8(s, byte); if (byte & 0x80) { *value = (byte & 0x7F) << 8; stream_read_uint8(s, byte); *value |= byte; } else { *value = (byte & 0x7F); } } INLINE void update_read_2byte_signed(STREAM* s, sint32* value) { uint8 byte; boolean negative; stream_read_uint8(s, byte); negative = (byte & 0x40) ? true : false; *value = (byte & 0x3F); if (byte & 0x80) { stream_read_uint8(s, byte); *value = (*value << 8) | byte; } if (negative) *value *= -1; } INLINE void update_read_4byte_unsigned(STREAM* s, uint32* value) { uint8 byte; uint8 count; stream_read_uint8(s, byte); count = (byte & 0xC0) >> 6; switch (count) { case 0: *value = (byte & 0x3F); break; case 1: *value = (byte & 0x3F) << 8; stream_read_uint8(s, byte); *value |= byte; break; case 2: *value = (byte & 0x3F) << 16; stream_read_uint8(s, byte); *value |= (byte << 8); stream_read_uint8(s, byte); *value |= byte; break; case 3: *value = (byte & 0x3F) << 24; stream_read_uint8(s, byte); *value |= (byte << 16); stream_read_uint8(s, byte); *value |= (byte << 8); stream_read_uint8(s, byte); *value |= byte; break; default: break; } } INLINE void update_read_delta(STREAM* s, sint32* value) { uint8 byte; stream_read_uint8(s, byte); if (byte & 0x40) *value = (byte | ~0x3F); else *value = (byte & 0x3F); if (byte & 0x80) { stream_read_uint8(s, byte); *value = (*value << 8) | byte; } } INLINE void update_read_glyph_delta(STREAM* s, uint16* value) { uint8 byte; stream_read_uint8(s, byte); if (byte == 0x80) stream_read_uint16(s, *value); else *value = (byte & 0x3F); } INLINE void update_seek_glyph_delta(STREAM* s) { uint8 byte; stream_read_uint8(s, byte); if (byte & 0x80) stream_seek_uint8(s); } INLINE void update_read_brush(STREAM* s, rdpBrush* brush, uint8 fieldFlags) { if (fieldFlags & ORDER_FIELD_01) stream_read_uint8(s, brush->x); if (fieldFlags & ORDER_FIELD_02) stream_read_uint8(s, brush->y); if (fieldFlags & ORDER_FIELD_03) stream_read_uint8(s, brush->style); if (fieldFlags & ORDER_FIELD_04) stream_read_uint8(s, brush->hatch); if (brush->style & CACHED_BRUSH) { brush->index = brush->hatch; brush->bpp = BMF_BPP[brush->style & 0x0F]; if (brush->bpp == 0) brush->bpp = 1; } if (fieldFlags & ORDER_FIELD_05) { brush->data = (uint8*) brush->p8x8; stream_read_uint8(s, brush->data[7]); stream_read_uint8(s, brush->data[6]); stream_read_uint8(s, brush->data[5]); stream_read_uint8(s, brush->data[4]); stream_read_uint8(s, brush->data[3]); stream_read_uint8(s, brush->data[2]); stream_read_uint8(s, brush->data[1]); brush->data[0] = brush->hatch; } } INLINE void update_read_delta_rects(STREAM* s, DELTA_RECT* rectangles, int number) { int i; uint8 flags = 0; uint8* zeroBits; int zeroBitsSize; if (number > 45) number = 45; zeroBitsSize = ((number + 1) / 2); stream_get_mark(s, zeroBits); stream_seek(s, zeroBitsSize); memset(rectangles, 0, sizeof(DELTA_RECT) * (number + 1)); for (i = 1; i < number + 1; i++) { if ((i - 1) % 2 == 0) flags = zeroBits[(i - 1) / 2]; if (~flags & 0x80) update_read_delta(s, &rectangles[i].left); if (~flags & 0x40) update_read_delta(s, &rectangles[i].top); if (~flags & 0x20) update_read_delta(s, &rectangles[i].width); else rectangles[i].width = rectangles[i - 1].width; if (~flags & 0x10) update_read_delta(s, &rectangles[i].height); else rectangles[i].height = rectangles[i - 1].height; rectangles[i].left = rectangles[i].left + rectangles[i - 1].left; rectangles[i].top = rectangles[i].top + rectangles[i - 1].top; flags <<= 4; } } INLINE void update_read_delta_points(STREAM* s, DELTA_POINT* points, int number, sint16 x, sint16 y) { int i; uint8 flags = 0; uint8* zeroBits; int zeroBitsSize; zeroBitsSize = ((number + 3) / 4); stream_get_mark(s, zeroBits); stream_seek(s, zeroBitsSize); memset(points, 0, sizeof(DELTA_POINT) * number); for (i = 0; i < number; i++) { if (i % 4 == 0) flags = zeroBits[i / 4]; if (~flags & 0x80) update_read_delta(s, &points[i].x); if (~flags & 0x40) update_read_delta(s, &points[i].y); flags <<= 2; } } /* Primary Drawing Orders */ void update_read_dstblt_order(STREAM* s, ORDER_INFO* orderInfo, DSTBLT_ORDER* dstblt) { if (orderInfo->fieldFlags & ORDER_FIELD_01) update_read_coord(s, &dstblt->nLeftRect, orderInfo->deltaCoordinates); if (orderInfo->fieldFlags & ORDER_FIELD_02) update_read_coord(s, &dstblt->nTopRect, orderInfo->deltaCoordinates); if (orderInfo->fieldFlags & ORDER_FIELD_03) update_read_coord(s, &dstblt->nWidth, orderInfo->deltaCoordinates); if (orderInfo->fieldFlags & ORDER_FIELD_04) update_read_coord(s, &dstblt->nHeight, orderInfo->deltaCoordinates); if (orderInfo->fieldFlags & ORDER_FIELD_05) stream_read_uint8(s, dstblt->bRop); } void update_read_patblt_order(STREAM* s, ORDER_INFO* orderInfo, PATBLT_ORDER* patblt) { if (orderInfo->fieldFlags & ORDER_FIELD_01) update_read_coord(s, &patblt->nLeftRect, orderInfo->deltaCoordinates); if (orderInfo->fieldFlags & ORDER_FIELD_02) update_read_coord(s, &patblt->nTopRect, orderInfo->deltaCoordinates); if (orderInfo->fieldFlags & ORDER_FIELD_03) update_read_coord(s, &patblt->nWidth, orderInfo->deltaCoordinates); if (orderInfo->fieldFlags & ORDER_FIELD_04) update_read_coord(s, &patblt->nHeight, orderInfo->deltaCoordinates); if (orderInfo->fieldFlags & ORDER_FIELD_05) stream_read_uint8(s, patblt->bRop); if (orderInfo->fieldFlags & ORDER_FIELD_06) update_read_color(s, &patblt->backColor); if (orderInfo->fieldFlags & ORDER_FIELD_07) update_read_color(s, &patblt->foreColor); update_read_brush(s, &patblt->brush, orderInfo->fieldFlags >> 7); } void update_read_scrblt_order(STREAM* s, ORDER_INFO* orderInfo, SCRBLT_ORDER* scrblt) { if (orderInfo->fieldFlags & ORDER_FIELD_01) update_read_coord(s, &scrblt->nLeftRect, orderInfo->deltaCoordinates); if (orderInfo->fieldFlags & ORDER_FIELD_02) update_read_coord(s, &scrblt->nTopRect, orderInfo->deltaCoordinates); if (orderInfo->fieldFlags & ORDER_FIELD_03) update_read_coord(s, &scrblt->nWidth, orderInfo->deltaCoordinates); if (orderInfo->fieldFlags & ORDER_FIELD_04) update_read_coord(s, &scrblt->nHeight, orderInfo->deltaCoordinates); if (orderInfo->fieldFlags & ORDER_FIELD_05) stream_read_uint8(s, scrblt->bRop); if (orderInfo->fieldFlags & ORDER_FIELD_06) update_read_coord(s, &scrblt->nXSrc, orderInfo->deltaCoordinates); if (orderInfo->fieldFlags & ORDER_FIELD_07) update_read_coord(s, &scrblt->nYSrc, orderInfo->deltaCoordinates); } void update_read_opaque_rect_order(STREAM* s, ORDER_INFO* orderInfo, OPAQUE_RECT_ORDER* opaque_rect) { uint8 byte; if (orderInfo->fieldFlags & ORDER_FIELD_01) update_read_coord(s, &opaque_rect->nLeftRect, orderInfo->deltaCoordinates); if (orderInfo->fieldFlags & ORDER_FIELD_02) update_read_coord(s, &opaque_rect->nTopRect, orderInfo->deltaCoordinates); if (orderInfo->fieldFlags & ORDER_FIELD_03) update_read_coord(s, &opaque_rect->nWidth, orderInfo->deltaCoordinates); if (orderInfo->fieldFlags & ORDER_FIELD_04) update_read_coord(s, &opaque_rect->nHeight, orderInfo->deltaCoordinates); if (orderInfo->fieldFlags & ORDER_FIELD_05) { stream_read_uint8(s, byte); opaque_rect->color = (opaque_rect->color & 0xFFFFFF00) | byte; } if (orderInfo->fieldFlags & ORDER_FIELD_06) { stream_read_uint8(s, byte); opaque_rect->color = (opaque_rect->color & 0xFFFF00FF) | (byte << 8); } if (orderInfo->fieldFlags & ORDER_FIELD_07) { stream_read_uint8(s, byte); opaque_rect->color = (opaque_rect->color & 0xFF00FFFF) | (byte << 16); } } void update_read_draw_nine_grid_order(STREAM* s, ORDER_INFO* orderInfo, DRAW_NINE_GRID_ORDER* draw_nine_grid) { if (orderInfo->fieldFlags & ORDER_FIELD_01) update_read_coord(s, &draw_nine_grid->srcLeft, orderInfo->deltaCoordinates); if (orderInfo->fieldFlags & ORDER_FIELD_02) update_read_coord(s, &draw_nine_grid->srcTop, orderInfo->deltaCoordinates); if (orderInfo->fieldFlags & ORDER_FIELD_03) update_read_coord(s, &draw_nine_grid->srcRight, orderInfo->deltaCoordinates); if (orderInfo->fieldFlags & ORDER_FIELD_04) update_read_coord(s, &draw_nine_grid->srcBottom, orderInfo->deltaCoordinates); if (orderInfo->fieldFlags & ORDER_FIELD_05) stream_read_uint16(s, draw_nine_grid->bitmapId); } void update_read_multi_dstblt_order(STREAM* s, ORDER_INFO* orderInfo, MULTI_DSTBLT_ORDER* multi_dstblt) { if (orderInfo->fieldFlags & ORDER_FIELD_01) update_read_coord(s, &multi_dstblt->nLeftRect, orderInfo->deltaCoordinates); if (orderInfo->fieldFlags & ORDER_FIELD_02) update_read_coord(s, &multi_dstblt->nTopRect, orderInfo->deltaCoordinates); if (orderInfo->fieldFlags & ORDER_FIELD_03) update_read_coord(s, &multi_dstblt->nWidth, orderInfo->deltaCoordinates); if (orderInfo->fieldFlags & ORDER_FIELD_04) update_read_coord(s, &multi_dstblt->nHeight, orderInfo->deltaCoordinates); if (orderInfo->fieldFlags & ORDER_FIELD_05) stream_read_uint8(s, multi_dstblt->bRop); if (orderInfo->fieldFlags & ORDER_FIELD_06) stream_read_uint8(s, multi_dstblt->numRectangles); if (orderInfo->fieldFlags & ORDER_FIELD_07) { stream_read_uint16(s, multi_dstblt->cbData); update_read_delta_rects(s, multi_dstblt->rectangles, multi_dstblt->numRectangles); } } void update_read_multi_patblt_order(STREAM* s, ORDER_INFO* orderInfo, MULTI_PATBLT_ORDER* multi_patblt) { if (orderInfo->fieldFlags & ORDER_FIELD_01) update_read_coord(s, &multi_patblt->nLeftRect, orderInfo->deltaCoordinates); if (orderInfo->fieldFlags & ORDER_FIELD_02) update_read_coord(s, &multi_patblt->nTopRect, orderInfo->deltaCoordinates); if (orderInfo->fieldFlags & ORDER_FIELD_03) update_read_coord(s, &multi_patblt->nWidth, orderInfo->deltaCoordinates); if (orderInfo->fieldFlags & ORDER_FIELD_04) update_read_coord(s, &multi_patblt->nHeight, orderInfo->deltaCoordinates); if (orderInfo->fieldFlags & ORDER_FIELD_05) stream_read_uint8(s, multi_patblt->bRop); if (orderInfo->fieldFlags & ORDER_FIELD_06) update_read_color(s, &multi_patblt->backColor); if (orderInfo->fieldFlags & ORDER_FIELD_07) update_read_color(s, &multi_patblt->foreColor); update_read_brush(s, &multi_patblt->brush, orderInfo->fieldFlags >> 7); if (orderInfo->fieldFlags & ORDER_FIELD_13) stream_read_uint8(s, multi_patblt->numRectangles); if (orderInfo->fieldFlags & ORDER_FIELD_14) { stream_read_uint16(s, multi_patblt->cbData); update_read_delta_rects(s, multi_patblt->rectangles, multi_patblt->numRectangles); } } void update_read_multi_scrblt_order(STREAM* s, ORDER_INFO* orderInfo, MULTI_SCRBLT_ORDER* multi_scrblt) { if (orderInfo->fieldFlags & ORDER_FIELD_01) update_read_coord(s, &multi_scrblt->nLeftRect, orderInfo->deltaCoordinates); if (orderInfo->fieldFlags & ORDER_FIELD_02) update_read_coord(s, &multi_scrblt->nTopRect, orderInfo->deltaCoordinates); if (orderInfo->fieldFlags & ORDER_FIELD_03) update_read_coord(s, &multi_scrblt->nWidth, orderInfo->deltaCoordinates); if (orderInfo->fieldFlags & ORDER_FIELD_04) update_read_coord(s, &multi_scrblt->nHeight, orderInfo->deltaCoordinates); if (orderInfo->fieldFlags & ORDER_FIELD_05) stream_read_uint8(s, multi_scrblt->bRop); if (orderInfo->fieldFlags & ORDER_FIELD_06) update_read_coord(s, &multi_scrblt->nXSrc, orderInfo->deltaCoordinates); if (orderInfo->fieldFlags & ORDER_FIELD_07) update_read_coord(s, &multi_scrblt->nYSrc, orderInfo->deltaCoordinates); if (orderInfo->fieldFlags & ORDER_FIELD_08) stream_read_uint8(s, multi_scrblt->numRectangles); if (orderInfo->fieldFlags & ORDER_FIELD_09) { stream_read_uint16(s, multi_scrblt->cbData); update_read_delta_rects(s, multi_scrblt->rectangles, multi_scrblt->numRectangles); } } void update_read_multi_opaque_rect_order(STREAM* s, ORDER_INFO* orderInfo, MULTI_OPAQUE_RECT_ORDER* multi_opaque_rect) { uint8 byte; if (orderInfo->fieldFlags & ORDER_FIELD_01) update_read_coord(s, &multi_opaque_rect->nLeftRect, orderInfo->deltaCoordinates); if (orderInfo->fieldFlags & ORDER_FIELD_02) update_read_coord(s, &multi_opaque_rect->nTopRect, orderInfo->deltaCoordinates); if (orderInfo->fieldFlags & ORDER_FIELD_03) update_read_coord(s, &multi_opaque_rect->nWidth, orderInfo->deltaCoordinates); if (orderInfo->fieldFlags & ORDER_FIELD_04) update_read_coord(s, &multi_opaque_rect->nHeight, orderInfo->deltaCoordinates); if (orderInfo->fieldFlags & ORDER_FIELD_05) { stream_read_uint8(s, byte); multi_opaque_rect->color = (multi_opaque_rect->color & 0xFFFFFF00) | byte; } if (orderInfo->fieldFlags & ORDER_FIELD_06) { stream_read_uint8(s, byte); multi_opaque_rect->color = (multi_opaque_rect->color & 0xFFFF00FF) | (byte << 8); } if (orderInfo->fieldFlags & ORDER_FIELD_07) { stream_read_uint8(s, byte); multi_opaque_rect->color = (multi_opaque_rect->color & 0xFF00FFFF) | (byte << 16); } if (orderInfo->fieldFlags & ORDER_FIELD_08) stream_read_uint8(s, multi_opaque_rect->numRectangles); if (orderInfo->fieldFlags & ORDER_FIELD_09) { stream_read_uint16(s, multi_opaque_rect->cbData); update_read_delta_rects(s, multi_opaque_rect->rectangles, multi_opaque_rect->numRectangles); } } void update_read_multi_draw_nine_grid_order(STREAM* s, ORDER_INFO* orderInfo, MULTI_DRAW_NINE_GRID_ORDER* multi_draw_nine_grid) { if (orderInfo->fieldFlags & ORDER_FIELD_01) update_read_coord(s, &multi_draw_nine_grid->srcLeft, orderInfo->deltaCoordinates); if (orderInfo->fieldFlags & ORDER_FIELD_02) update_read_coord(s, &multi_draw_nine_grid->srcTop, orderInfo->deltaCoordinates); if (orderInfo->fieldFlags & ORDER_FIELD_03) update_read_coord(s, &multi_draw_nine_grid->srcRight, orderInfo->deltaCoordinates); if (orderInfo->fieldFlags & ORDER_FIELD_04) update_read_coord(s, &multi_draw_nine_grid->srcBottom, orderInfo->deltaCoordinates); if (orderInfo->fieldFlags & ORDER_FIELD_05) stream_read_uint16(s, multi_draw_nine_grid->bitmapId); if (orderInfo->fieldFlags & ORDER_FIELD_06) stream_read_uint8(s, multi_draw_nine_grid->nDeltaEntries); if (orderInfo->fieldFlags & ORDER_FIELD_07) { stream_read_uint16(s, multi_draw_nine_grid->cbData); stream_seek(s, multi_draw_nine_grid->cbData); } } void update_read_line_to_order(STREAM* s, ORDER_INFO* orderInfo, LINE_TO_ORDER* line_to) { if (orderInfo->fieldFlags & ORDER_FIELD_01) stream_read_uint16(s, line_to->backMode); if (orderInfo->fieldFlags & ORDER_FIELD_02) update_read_coord(s, &line_to->nXStart, orderInfo->deltaCoordinates); if (orderInfo->fieldFlags & ORDER_FIELD_03) update_read_coord(s, &line_to->nYStart, orderInfo->deltaCoordinates); if (orderInfo->fieldFlags & ORDER_FIELD_04) update_read_coord(s, &line_to->nXEnd, orderInfo->deltaCoordinates); if (orderInfo->fieldFlags & ORDER_FIELD_05) update_read_coord(s, &line_to->nYEnd, orderInfo->deltaCoordinates); if (orderInfo->fieldFlags & ORDER_FIELD_06) update_read_color(s, &line_to->backColor); if (orderInfo->fieldFlags & ORDER_FIELD_07) stream_read_uint8(s, line_to->bRop2); if (orderInfo->fieldFlags & ORDER_FIELD_08) stream_read_uint8(s, line_to->penStyle); if (orderInfo->fieldFlags & ORDER_FIELD_09) stream_read_uint8(s, line_to->penWidth); if (orderInfo->fieldFlags & ORDER_FIELD_10) update_read_color(s, &line_to->penColor); } void update_read_polyline_order(STREAM* s, ORDER_INFO* orderInfo, POLYLINE_ORDER* polyline) { if (orderInfo->fieldFlags & ORDER_FIELD_01) update_read_coord(s, &polyline->xStart, orderInfo->deltaCoordinates); if (orderInfo->fieldFlags & ORDER_FIELD_02) update_read_coord(s, &polyline->yStart, orderInfo->deltaCoordinates); if (orderInfo->fieldFlags & ORDER_FIELD_03) stream_read_uint8(s, polyline->bRop2); if (orderInfo->fieldFlags & ORDER_FIELD_04) stream_seek_uint16(s); if (orderInfo->fieldFlags & ORDER_FIELD_05) update_read_color(s, &polyline->penColor); if (orderInfo->fieldFlags & ORDER_FIELD_06) stream_read_uint8(s, polyline->numPoints); if (orderInfo->fieldFlags & ORDER_FIELD_07) { stream_read_uint8(s, polyline->cbData); if (polyline->points == NULL) polyline->points = (DELTA_POINT*) xmalloc(sizeof(DELTA_POINT) * polyline->numPoints); else polyline->points = (DELTA_POINT*) xrealloc(polyline->points, sizeof(DELTA_POINT) * polyline->numPoints); update_read_delta_points(s, polyline->points, polyline->numPoints, polyline->xStart, polyline->yStart); } } void update_read_memblt_order(STREAM* s, ORDER_INFO* orderInfo, MEMBLT_ORDER* memblt) { if (orderInfo->fieldFlags & ORDER_FIELD_01) stream_read_uint16(s, memblt->cacheId); if (orderInfo->fieldFlags & ORDER_FIELD_02) update_read_coord(s, &memblt->nLeftRect, orderInfo->deltaCoordinates); if (orderInfo->fieldFlags & ORDER_FIELD_03) update_read_coord(s, &memblt->nTopRect, orderInfo->deltaCoordinates); if (orderInfo->fieldFlags & ORDER_FIELD_04) update_read_coord(s, &memblt->nWidth, orderInfo->deltaCoordinates); if (orderInfo->fieldFlags & ORDER_FIELD_05) update_read_coord(s, &memblt->nHeight, orderInfo->deltaCoordinates); if (orderInfo->fieldFlags & ORDER_FIELD_06) stream_read_uint8(s, memblt->bRop); if (orderInfo->fieldFlags & ORDER_FIELD_07) update_read_coord(s, &memblt->nXSrc, orderInfo->deltaCoordinates); if (orderInfo->fieldFlags & ORDER_FIELD_08) update_read_coord(s, &memblt->nYSrc, orderInfo->deltaCoordinates); if (orderInfo->fieldFlags & ORDER_FIELD_09) stream_read_uint16(s, memblt->cacheIndex); memblt->colorIndex = (memblt->cacheId >> 8); memblt->cacheId = (memblt->cacheId & 0xFF); } void update_read_mem3blt_order(STREAM* s, ORDER_INFO* orderInfo, MEM3BLT_ORDER* mem3blt) { if (orderInfo->fieldFlags & ORDER_FIELD_01) stream_read_uint16(s, mem3blt->cacheId); if (orderInfo->fieldFlags & ORDER_FIELD_02) update_read_coord(s, &mem3blt->nLeftRect, orderInfo->deltaCoordinates); if (orderInfo->fieldFlags & ORDER_FIELD_03) update_read_coord(s, &mem3blt->nTopRect, orderInfo->deltaCoordinates); if (orderInfo->fieldFlags & ORDER_FIELD_04) update_read_coord(s, &mem3blt->nWidth, orderInfo->deltaCoordinates); if (orderInfo->fieldFlags & ORDER_FIELD_05) update_read_coord(s, &mem3blt->nHeight, orderInfo->deltaCoordinates); if (orderInfo->fieldFlags & ORDER_FIELD_06) stream_read_uint8(s, mem3blt->bRop); if (orderInfo->fieldFlags & ORDER_FIELD_07) update_read_coord(s, &mem3blt->nXSrc, orderInfo->deltaCoordinates); if (orderInfo->fieldFlags & ORDER_FIELD_08) update_read_coord(s, &mem3blt->nYSrc, orderInfo->deltaCoordinates); if (orderInfo->fieldFlags & ORDER_FIELD_09) update_read_color(s, &mem3blt->backColor); if (orderInfo->fieldFlags & ORDER_FIELD_10) update_read_color(s, &mem3blt->foreColor); update_read_brush(s, &mem3blt->brush, orderInfo->fieldFlags >> 10); if (orderInfo->fieldFlags & ORDER_FIELD_16) stream_read_uint16(s, mem3blt->cacheIndex); mem3blt->colorIndex = (mem3blt->cacheId >> 8); mem3blt->cacheId = (mem3blt->cacheId & 0xFF); } void update_read_save_bitmap_order(STREAM* s, ORDER_INFO* orderInfo, SAVE_BITMAP_ORDER* save_bitmap) { if (orderInfo->fieldFlags & ORDER_FIELD_01) stream_read_uint32(s, save_bitmap->savedBitmapPosition); if (orderInfo->fieldFlags & ORDER_FIELD_02) update_read_coord(s, &save_bitmap->nLeftRect, orderInfo->deltaCoordinates); if (orderInfo->fieldFlags & ORDER_FIELD_03) update_read_coord(s, &save_bitmap->nTopRect, orderInfo->deltaCoordinates); if (orderInfo->fieldFlags & ORDER_FIELD_04) update_read_coord(s, &save_bitmap->nRightRect, orderInfo->deltaCoordinates); if (orderInfo->fieldFlags & ORDER_FIELD_05) update_read_coord(s, &save_bitmap->nBottomRect, orderInfo->deltaCoordinates); if (orderInfo->fieldFlags & ORDER_FIELD_06) stream_read_uint8(s, save_bitmap->operation); } void update_read_glyph_index_order(STREAM* s, ORDER_INFO* orderInfo, GLYPH_INDEX_ORDER* glyph_index) { if (orderInfo->fieldFlags & ORDER_FIELD_01) stream_read_uint8(s, glyph_index->cacheId); if (orderInfo->fieldFlags & ORDER_FIELD_02) stream_read_uint8(s, glyph_index->flAccel); if (orderInfo->fieldFlags & ORDER_FIELD_03) stream_read_uint8(s, glyph_index->ulCharInc); if (orderInfo->fieldFlags & ORDER_FIELD_04) stream_read_uint8(s, glyph_index->fOpRedundant); if (orderInfo->fieldFlags & ORDER_FIELD_05) update_read_color(s, &glyph_index->backColor); if (orderInfo->fieldFlags & ORDER_FIELD_06) update_read_color(s, &glyph_index->foreColor); if (orderInfo->fieldFlags & ORDER_FIELD_07) stream_read_uint16(s, glyph_index->bkLeft); if (orderInfo->fieldFlags & ORDER_FIELD_08) stream_read_uint16(s, glyph_index->bkTop); if (orderInfo->fieldFlags & ORDER_FIELD_09) stream_read_uint16(s, glyph_index->bkRight); if (orderInfo->fieldFlags & ORDER_FIELD_10) stream_read_uint16(s, glyph_index->bkBottom); if (orderInfo->fieldFlags & ORDER_FIELD_11) stream_read_uint16(s, glyph_index->opLeft); if (orderInfo->fieldFlags & ORDER_FIELD_12) stream_read_uint16(s, glyph_index->opTop); if (orderInfo->fieldFlags & ORDER_FIELD_13) stream_read_uint16(s, glyph_index->opRight); if (orderInfo->fieldFlags & ORDER_FIELD_14) stream_read_uint16(s, glyph_index->opBottom); update_read_brush(s, &glyph_index->brush, orderInfo->fieldFlags >> 14); if (orderInfo->fieldFlags & ORDER_FIELD_20) stream_read_uint16(s, glyph_index->x); if (orderInfo->fieldFlags & ORDER_FIELD_21) stream_read_uint16(s, glyph_index->y); if (orderInfo->fieldFlags & ORDER_FIELD_22) { stream_read_uint8(s, glyph_index->cbData); memcpy(glyph_index->data, s->p, glyph_index->cbData); stream_seek(s, glyph_index->cbData); } } void update_read_fast_index_order(STREAM* s, ORDER_INFO* orderInfo, FAST_INDEX_ORDER* fast_index) { if (orderInfo->fieldFlags & ORDER_FIELD_01) stream_read_uint8(s, fast_index->cacheId); if (orderInfo->fieldFlags & ORDER_FIELD_02) { stream_read_uint8(s, fast_index->ulCharInc); stream_read_uint8(s, fast_index->flAccel); } if (orderInfo->fieldFlags & ORDER_FIELD_03) update_read_color(s, &fast_index->backColor); if (orderInfo->fieldFlags & ORDER_FIELD_04) update_read_color(s, &fast_index->foreColor); if (orderInfo->fieldFlags & ORDER_FIELD_05) update_read_coord(s, &fast_index->bkLeft, orderInfo->deltaCoordinates); if (orderInfo->fieldFlags & ORDER_FIELD_06) update_read_coord(s, &fast_index->bkTop, orderInfo->deltaCoordinates); if (orderInfo->fieldFlags & ORDER_FIELD_07) update_read_coord(s, &fast_index->bkRight, orderInfo->deltaCoordinates); if (orderInfo->fieldFlags & ORDER_FIELD_08) update_read_coord(s, &fast_index->bkBottom, orderInfo->deltaCoordinates); if (orderInfo->fieldFlags & ORDER_FIELD_09) update_read_coord(s, &fast_index->opLeft, orderInfo->deltaCoordinates); if (orderInfo->fieldFlags & ORDER_FIELD_10) update_read_coord(s, &fast_index->opTop, orderInfo->deltaCoordinates); if (orderInfo->fieldFlags & ORDER_FIELD_11) update_read_coord(s, &fast_index->opRight, orderInfo->deltaCoordinates); if (orderInfo->fieldFlags & ORDER_FIELD_12) update_read_coord(s, &fast_index->opBottom, orderInfo->deltaCoordinates); if (orderInfo->fieldFlags & ORDER_FIELD_13) update_read_coord(s, &fast_index->x, orderInfo->deltaCoordinates); if (orderInfo->fieldFlags & ORDER_FIELD_14) update_read_coord(s, &fast_index->y, orderInfo->deltaCoordinates); if (orderInfo->fieldFlags & ORDER_FIELD_15) { stream_read_uint8(s, fast_index->cbData); memcpy(fast_index->data, s->p, fast_index->cbData); stream_seek(s, fast_index->cbData); } } void update_read_fast_glyph_order(STREAM* s, ORDER_INFO* orderInfo, FAST_GLYPH_ORDER* fast_glyph) { GLYPH_DATA_V2* glyph; uint8* phold; if (orderInfo->fieldFlags & ORDER_FIELD_01) stream_read_uint8(s, fast_glyph->cacheId); if (orderInfo->fieldFlags & ORDER_FIELD_02) { stream_read_uint8(s, fast_glyph->ulCharInc); stream_read_uint8(s, fast_glyph->flAccel); } if (orderInfo->fieldFlags & ORDER_FIELD_03) update_read_color(s, &fast_glyph->backColor); if (orderInfo->fieldFlags & ORDER_FIELD_04) update_read_color(s, &fast_glyph->foreColor); if (orderInfo->fieldFlags & ORDER_FIELD_05) update_read_coord(s, &fast_glyph->bkLeft, orderInfo->deltaCoordinates); if (orderInfo->fieldFlags & ORDER_FIELD_06) update_read_coord(s, &fast_glyph->bkTop, orderInfo->deltaCoordinates); if (orderInfo->fieldFlags & ORDER_FIELD_07) update_read_coord(s, &fast_glyph->bkRight, orderInfo->deltaCoordinates); if (orderInfo->fieldFlags & ORDER_FIELD_08) update_read_coord(s, &fast_glyph->bkBottom, orderInfo->deltaCoordinates); if (orderInfo->fieldFlags & ORDER_FIELD_09) update_read_coord(s, &fast_glyph->opLeft, orderInfo->deltaCoordinates); if (orderInfo->fieldFlags & ORDER_FIELD_10) update_read_coord(s, &fast_glyph->opTop, orderInfo->deltaCoordinates); if (orderInfo->fieldFlags & ORDER_FIELD_11) update_read_coord(s, &fast_glyph->opRight, orderInfo->deltaCoordinates); if (orderInfo->fieldFlags & ORDER_FIELD_12) update_read_coord(s, &fast_glyph->opBottom, orderInfo->deltaCoordinates); if (orderInfo->fieldFlags & ORDER_FIELD_13) update_read_coord(s, &fast_glyph->x, orderInfo->deltaCoordinates); if (orderInfo->fieldFlags & ORDER_FIELD_14) update_read_coord(s, &fast_glyph->y, orderInfo->deltaCoordinates); if (orderInfo->fieldFlags & ORDER_FIELD_15) { stream_read_uint8(s, fast_glyph->cbData); memcpy(fast_glyph->data, s->p, fast_glyph->cbData); phold = s->p; stream_seek(s, 1); if ((fast_glyph->cbData > 1) && (fast_glyph->glyph_data == NULL)) { /* parse optional glyph data */ glyph = (GLYPH_DATA_V2*) xmalloc(sizeof(GLYPH_DATA_V2)); glyph->cacheIndex = fast_glyph->data[0]; update_read_2byte_signed(s, &glyph->x); update_read_2byte_signed(s, &glyph->y); update_read_2byte_unsigned(s, &glyph->cx); update_read_2byte_unsigned(s, &glyph->cy); glyph->cb = ((glyph->cx + 7) / 8) * glyph->cy; glyph->cb += ((glyph->cb % 4) > 0) ? 4 - (glyph->cb % 4) : 0; glyph->aj = (uint8*) xmalloc(glyph->cb); stream_read(s, glyph->aj, glyph->cb); fast_glyph->glyph_data = glyph; } s->p = phold + fast_glyph->cbData; } } void update_read_polygon_sc_order(STREAM* s, ORDER_INFO* orderInfo, POLYGON_SC_ORDER* polygon_sc) { if (orderInfo->fieldFlags & ORDER_FIELD_01) update_read_coord(s, &polygon_sc->xStart, orderInfo->deltaCoordinates); if (orderInfo->fieldFlags & ORDER_FIELD_02) update_read_coord(s, &polygon_sc->yStart, orderInfo->deltaCoordinates); if (orderInfo->fieldFlags & ORDER_FIELD_03) stream_read_uint8(s, polygon_sc->bRop2); if (orderInfo->fieldFlags & ORDER_FIELD_04) stream_read_uint8(s, polygon_sc->fillMode); if (orderInfo->fieldFlags & ORDER_FIELD_05) update_read_color(s, &polygon_sc->brushColor); if (orderInfo->fieldFlags & ORDER_FIELD_06) stream_read_uint8(s, polygon_sc->nDeltaEntries); if (orderInfo->fieldFlags & ORDER_FIELD_07) { stream_read_uint8(s, polygon_sc->cbData); stream_seek(s, polygon_sc->cbData); } } void update_read_polygon_cb_order(STREAM* s, ORDER_INFO* orderInfo, POLYGON_CB_ORDER* polygon_cb) { if (orderInfo->fieldFlags & ORDER_FIELD_01) update_read_coord(s, &polygon_cb->xStart, orderInfo->deltaCoordinates); if (orderInfo->fieldFlags & ORDER_FIELD_02) update_read_coord(s, &polygon_cb->yStart, orderInfo->deltaCoordinates); if (orderInfo->fieldFlags & ORDER_FIELD_03) stream_read_uint8(s, polygon_cb->bRop2); if (orderInfo->fieldFlags & ORDER_FIELD_04) stream_read_uint8(s, polygon_cb->fillMode); if (orderInfo->fieldFlags & ORDER_FIELD_05) update_read_color(s, &polygon_cb->backColor); if (orderInfo->fieldFlags & ORDER_FIELD_06) update_read_color(s, &polygon_cb->foreColor); update_read_brush(s, &polygon_cb->brush, orderInfo->fieldFlags >> 6); if (orderInfo->fieldFlags & ORDER_FIELD_12) stream_read_uint8(s, polygon_cb->nDeltaEntries); if (orderInfo->fieldFlags & ORDER_FIELD_13) { stream_read_uint8(s, polygon_cb->cbData); stream_seek(s, polygon_cb->cbData); } } void update_read_ellipse_sc_order(STREAM* s, ORDER_INFO* orderInfo, ELLIPSE_SC_ORDER* ellipse_sc) { if (orderInfo->fieldFlags & ORDER_FIELD_01) update_read_coord(s, &ellipse_sc->leftRect, orderInfo->deltaCoordinates); if (orderInfo->fieldFlags & ORDER_FIELD_02) update_read_coord(s, &ellipse_sc->topRect, orderInfo->deltaCoordinates); if (orderInfo->fieldFlags & ORDER_FIELD_03) update_read_coord(s, &ellipse_sc->rightRect, orderInfo->deltaCoordinates); if (orderInfo->fieldFlags & ORDER_FIELD_04) update_read_coord(s, &ellipse_sc->bottomRect, orderInfo->deltaCoordinates); if (orderInfo->fieldFlags & ORDER_FIELD_05) stream_read_uint8(s, ellipse_sc->bRop2); if (orderInfo->fieldFlags & ORDER_FIELD_06) stream_read_uint8(s, ellipse_sc->fillMode); if (orderInfo->fieldFlags & ORDER_FIELD_07) update_read_color(s, &ellipse_sc->color); } void update_read_ellipse_cb_order(STREAM* s, ORDER_INFO* orderInfo, ELLIPSE_CB_ORDER* ellipse_cb) { if (orderInfo->fieldFlags & ORDER_FIELD_01) update_read_coord(s, &ellipse_cb->leftRect, orderInfo->deltaCoordinates); if (orderInfo->fieldFlags & ORDER_FIELD_02) update_read_coord(s, &ellipse_cb->topRect, orderInfo->deltaCoordinates); if (orderInfo->fieldFlags & ORDER_FIELD_03) update_read_coord(s, &ellipse_cb->rightRect, orderInfo->deltaCoordinates); if (orderInfo->fieldFlags & ORDER_FIELD_04) update_read_coord(s, &ellipse_cb->bottomRect, orderInfo->deltaCoordinates); if (orderInfo->fieldFlags & ORDER_FIELD_05) stream_read_uint8(s, ellipse_cb->bRop2); if (orderInfo->fieldFlags & ORDER_FIELD_06) stream_read_uint8(s, ellipse_cb->fillMode); if (orderInfo->fieldFlags & ORDER_FIELD_07) update_read_color(s, &ellipse_cb->backColor); if (orderInfo->fieldFlags & ORDER_FIELD_08) update_read_color(s, &ellipse_cb->foreColor); update_read_brush(s, &ellipse_cb->brush, orderInfo->fieldFlags >> 8); } /* Secondary Drawing Orders */ void update_read_cache_bitmap_order(STREAM* s, CACHE_BITMAP_ORDER* cache_bitmap_order, boolean compressed, uint16 flags) { stream_read_uint8(s, cache_bitmap_order->cacheId); /* cacheId (1 byte) */ stream_seek_uint8(s); /* pad1Octet (1 byte) */ stream_read_uint8(s, cache_bitmap_order->bitmapWidth); /* bitmapWidth (1 byte) */ stream_read_uint8(s, cache_bitmap_order->bitmapHeight); /* bitmapHeight (1 byte) */ stream_read_uint8(s, cache_bitmap_order->bitmapBpp); /* bitmapBpp (1 byte) */ stream_read_uint16(s, cache_bitmap_order->bitmapLength); /* bitmapLength (2 bytes) */ stream_read_uint16(s, cache_bitmap_order->cacheIndex); /* cacheIndex (2 bytes) */ if (compressed) { if ((flags & NO_BITMAP_COMPRESSION_HDR) == 0) { uint8* bitmapComprHdr = (uint8*) &(cache_bitmap_order->bitmapComprHdr); stream_read(s, bitmapComprHdr, 8); /* bitmapComprHdr (8 bytes) */ cache_bitmap_order->bitmapLength -= 8; } stream_get_mark(s, cache_bitmap_order->bitmapDataStream); stream_seek(s, cache_bitmap_order->bitmapLength); } else { stream_get_mark(s, cache_bitmap_order->bitmapDataStream); stream_seek(s, cache_bitmap_order->bitmapLength); /* bitmapDataStream */ } cache_bitmap_order->compressed = compressed; } void update_read_cache_bitmap_v2_order(STREAM* s, CACHE_BITMAP_V2_ORDER* cache_bitmap_v2_order, boolean compressed, uint16 flags) { uint8 bitsPerPixelId; cache_bitmap_v2_order->cacheId = flags & 0x0003; cache_bitmap_v2_order->flags = (flags & 0xFF80) >> 7; bitsPerPixelId = (flags & 0x0078) >> 3; cache_bitmap_v2_order->bitmapBpp = CBR2_BPP[bitsPerPixelId]; if (cache_bitmap_v2_order->flags & CBR2_PERSISTENT_KEY_PRESENT) { stream_read_uint32(s, cache_bitmap_v2_order->key1); /* key1 (4 bytes) */ stream_read_uint32(s, cache_bitmap_v2_order->key2); /* key2 (4 bytes) */ } if (cache_bitmap_v2_order->flags & CBR2_HEIGHT_SAME_AS_WIDTH) { update_read_2byte_unsigned(s, &cache_bitmap_v2_order->bitmapWidth); /* bitmapWidth */ cache_bitmap_v2_order->bitmapHeight = cache_bitmap_v2_order->bitmapWidth; } else { update_read_2byte_unsigned(s, &cache_bitmap_v2_order->bitmapWidth); /* bitmapWidth */ update_read_2byte_unsigned(s, &cache_bitmap_v2_order->bitmapHeight); /* bitmapHeight */ } update_read_4byte_unsigned(s, &cache_bitmap_v2_order->bitmapLength); /* bitmapLength */ update_read_2byte_unsigned(s, &cache_bitmap_v2_order->cacheIndex); /* cacheIndex */ if (cache_bitmap_v2_order->flags & CBR2_DO_NOT_CACHE) cache_bitmap_v2_order->cacheIndex = BITMAP_CACHE_WAITING_LIST_INDEX; if (compressed) { if (!(cache_bitmap_v2_order->flags & CBR2_NO_BITMAP_COMPRESSION_HDR)) { stream_read_uint16(s, cache_bitmap_v2_order->cbCompFirstRowSize); /* cbCompFirstRowSize (2 bytes) */ stream_read_uint16(s, cache_bitmap_v2_order->cbCompMainBodySize); /* cbCompMainBodySize (2 bytes) */ stream_read_uint16(s, cache_bitmap_v2_order->cbScanWidth); /* cbScanWidth (2 bytes) */ stream_read_uint16(s, cache_bitmap_v2_order->cbUncompressedSize); /* cbUncompressedSize (2 bytes) */ cache_bitmap_v2_order->bitmapLength = cache_bitmap_v2_order->cbCompMainBodySize; } stream_get_mark(s, cache_bitmap_v2_order->bitmapDataStream); stream_seek(s, cache_bitmap_v2_order->bitmapLength); } else { stream_get_mark(s, cache_bitmap_v2_order->bitmapDataStream); stream_seek(s, cache_bitmap_v2_order->bitmapLength); } cache_bitmap_v2_order->compressed = compressed; } void update_read_cache_bitmap_v3_order(STREAM* s, CACHE_BITMAP_V3_ORDER* cache_bitmap_v3_order, boolean compressed, uint16 flags) { uint8 bitsPerPixelId; BITMAP_DATA_EX* bitmapData; cache_bitmap_v3_order->cacheId = flags & 0x00000003; cache_bitmap_v3_order->flags = (flags & 0x0000FF80) >> 7; bitsPerPixelId = (flags & 0x00000078) >> 3; cache_bitmap_v3_order->bpp = CBR23_BPP[bitsPerPixelId]; stream_read_uint16(s, cache_bitmap_v3_order->cacheIndex); /* cacheIndex (2 bytes) */ stream_read_uint32(s, cache_bitmap_v3_order->key1); /* key1 (4 bytes) */ stream_read_uint32(s, cache_bitmap_v3_order->key2); /* key2 (4 bytes) */ bitmapData = &cache_bitmap_v3_order->bitmapData; stream_read_uint8(s, bitmapData->bpp); stream_seek_uint8(s); /* reserved1 (1 byte) */ stream_seek_uint8(s); /* reserved2 (1 byte) */ stream_read_uint8(s, bitmapData->codecID); /* codecID (1 byte) */ stream_read_uint16(s, bitmapData->width); /* width (2 bytes) */ stream_read_uint16(s, bitmapData->height); /* height (2 bytes) */ stream_read_uint32(s, bitmapData->length); /* length (4 bytes) */ if (bitmapData->data == NULL) bitmapData->data = (uint8*) xmalloc(bitmapData->length); else bitmapData->data = (uint8*) xrealloc(bitmapData->data, bitmapData->length); stream_read(s, bitmapData->data, bitmapData->length); } void update_read_cache_color_table_order(STREAM* s, CACHE_COLOR_TABLE_ORDER* cache_color_table_order, uint16 flags) { int i; uint32* colorTable; stream_read_uint8(s, cache_color_table_order->cacheIndex); /* cacheIndex (1 byte) */ stream_read_uint8(s, cache_color_table_order->numberColors); /* numberColors (2 bytes) */ colorTable = cache_color_table_order->colorTable; if (colorTable == NULL) colorTable = (uint32*) xmalloc(cache_color_table_order->numberColors * 4); else colorTable = (uint32*) xrealloc(colorTable, cache_color_table_order->numberColors * 4); for (i = 0; i < (int) cache_color_table_order->numberColors; i++) { update_read_color_quad(s, &colorTable[i]); } cache_color_table_order->colorTable = colorTable; } void update_read_cache_glyph_order(STREAM* s, CACHE_GLYPH_ORDER* cache_glyph_order, uint16 flags) { int i; sint16 lsi16; GLYPH_DATA* glyph; stream_read_uint8(s, cache_glyph_order->cacheId); /* cacheId (1 byte) */ stream_read_uint8(s, cache_glyph_order->cGlyphs); /* cGlyphs (1 byte) */ for (i = 0; i < (int) cache_glyph_order->cGlyphs; i++) { if (cache_glyph_order->glyphData[i] == NULL) { cache_glyph_order->glyphData[i] = (GLYPH_DATA*) xmalloc(sizeof(GLYPH_DATA)); } glyph = cache_glyph_order->glyphData[i]; stream_read_uint16(s, glyph->cacheIndex); stream_read_uint16(s, lsi16); glyph->x = lsi16; stream_read_uint16(s, lsi16); glyph->y = lsi16; stream_read_uint16(s, glyph->cx); stream_read_uint16(s, glyph->cy); glyph->cb = ((glyph->cx + 7) / 8) * glyph->cy; glyph->cb += ((glyph->cb % 4) > 0) ? 4 - (glyph->cb % 4) : 0; glyph->aj = (uint8*) xmalloc(glyph->cb); stream_read(s, glyph->aj, glyph->cb); } if (flags & CG_GLYPH_UNICODE_PRESENT) stream_seek(s, cache_glyph_order->cGlyphs * 2); } void update_read_cache_glyph_v2_order(STREAM* s, CACHE_GLYPH_V2_ORDER* cache_glyph_v2_order, uint16 flags) { int i; GLYPH_DATA_V2* glyph; cache_glyph_v2_order->cacheId = (flags & 0x000F); cache_glyph_v2_order->flags = (flags & 0x00F0) >> 4; cache_glyph_v2_order->cGlyphs = (flags & 0xFF00) >> 8; for (i = 0; i < (int) cache_glyph_v2_order->cGlyphs; i++) { if (cache_glyph_v2_order->glyphData[i] == NULL) { cache_glyph_v2_order->glyphData[i] = (GLYPH_DATA_V2*) xmalloc(sizeof(GLYPH_DATA_V2)); } glyph = cache_glyph_v2_order->glyphData[i]; stream_read_uint8(s, glyph->cacheIndex); update_read_2byte_signed(s, &glyph->x); update_read_2byte_signed(s, &glyph->y); update_read_2byte_unsigned(s, &glyph->cx); update_read_2byte_unsigned(s, &glyph->cy); glyph->cb = ((glyph->cx + 7) / 8) * glyph->cy; glyph->cb += ((glyph->cb % 4) > 0) ? 4 - (glyph->cb % 4) : 0; glyph->aj = (uint8*) xmalloc(glyph->cb); stream_read(s, glyph->aj, glyph->cb); } if (flags & CG_GLYPH_UNICODE_PRESENT) stream_seek(s, cache_glyph_v2_order->cGlyphs * 2); } void update_decompress_brush(STREAM* s, uint8* output, uint8 bpp) { int index; int x, y, k; uint8 byte = 0; uint8* palette; int bytesPerPixel; palette = s->p + 16; bytesPerPixel = ((bpp + 1) / 8); for (y = 7; y >= 0; y--) { for (x = 0; x < 8; x++) { if ((x % 4) == 0) stream_read_uint8(s, byte); index = ((byte >> ((3 - (x % 4)) * 2)) & 0x03); for (k = 0; k < bytesPerPixel; k++) { output[((y * 8 + x) * bytesPerPixel) + k] = palette[(index * bytesPerPixel) + k]; } } } } void update_read_cache_brush_order(STREAM* s, CACHE_BRUSH_ORDER* cache_brush_order, uint16 flags) { int i; int size; uint8 iBitmapFormat; boolean compressed = false; stream_read_uint8(s, cache_brush_order->index); /* cacheEntry (1 byte) */ stream_read_uint8(s, iBitmapFormat); /* iBitmapFormat (1 byte) */ cache_brush_order->bpp = BMF_BPP[iBitmapFormat]; stream_read_uint8(s, cache_brush_order->cx); /* cx (1 byte) */ stream_read_uint8(s, cache_brush_order->cy); /* cy (1 byte) */ stream_read_uint8(s, cache_brush_order->style); /* style (1 byte) */ stream_read_uint8(s, cache_brush_order->length); /* iBytes (1 byte) */ if ((cache_brush_order->cx == 8) && (cache_brush_order->cy == 8)) { size = (cache_brush_order->bpp == 1) ? 8 : 8 * 8 * cache_brush_order->bpp; cache_brush_order->data = (uint8*) xmalloc(size); if (cache_brush_order->bpp == 1) { if (cache_brush_order->length != 8) { printf("incompatible 1bpp brush of length:%d\n", cache_brush_order->length); return; } /* rows are encoded in reverse order */ for (i = 7; i >= 0; i--) { stream_read_uint8(s, cache_brush_order->data[i]); } } else { if ((iBitmapFormat == BMF_8BPP) && (cache_brush_order->length == 20)) compressed = true; else if ((iBitmapFormat == BMF_16BPP) && (cache_brush_order->length == 24)) compressed = true; else if ((iBitmapFormat == BMF_32BPP) && (cache_brush_order->length == 32)) compressed = true; if (compressed != false) { /* compressed brush */ update_decompress_brush(s, cache_brush_order->data, cache_brush_order->bpp); } else { /* uncompressed brush */ int scanline = (cache_brush_order->bpp / 8) * 8; for (i = 7; i >= 0; i--) { stream_read(s, &cache_brush_order->data[i * scanline], scanline); } } } } } /* Alternate Secondary Drawing Orders */ void update_read_create_offscreen_bitmap_order(STREAM* s, CREATE_OFFSCREEN_BITMAP_ORDER* create_offscreen_bitmap) { uint16 flags; boolean deleteListPresent; OFFSCREEN_DELETE_LIST* deleteList; stream_read_uint16(s, flags); /* flags (2 bytes) */ create_offscreen_bitmap->id = flags & 0x7FFF; deleteListPresent = (flags & 0x8000) ? true : false; stream_read_uint16(s, create_offscreen_bitmap->cx); /* cx (2 bytes) */ stream_read_uint16(s, create_offscreen_bitmap->cy); /* cy (2 bytes) */ deleteList = &(create_offscreen_bitmap->deleteList); if (deleteListPresent) { int i; stream_read_uint16(s, deleteList->cIndices); if (deleteList->cIndices > deleteList->sIndices) { deleteList->sIndices = deleteList->cIndices; deleteList->indices = xrealloc(deleteList->indices, deleteList->sIndices * 2); } for (i = 0; i < (int) deleteList->cIndices; i++) { stream_read_uint16(s, deleteList->indices[i]); } } else { deleteList->cIndices = 0; } } void update_read_switch_surface_order(STREAM* s, SWITCH_SURFACE_ORDER* switch_surface) { stream_read_uint16(s, switch_surface->bitmapId); /* bitmapId (2 bytes) */ } void update_read_create_nine_grid_bitmap_order(STREAM* s, CREATE_NINE_GRID_BITMAP_ORDER* create_nine_grid_bitmap) { NINE_GRID_BITMAP_INFO* nineGridInfo; stream_read_uint8(s, create_nine_grid_bitmap->bitmapBpp); /* bitmapBpp (1 byte) */ stream_read_uint16(s, create_nine_grid_bitmap->bitmapId); /* bitmapId (2 bytes) */ nineGridInfo = &(create_nine_grid_bitmap->nineGridInfo); stream_read_uint32(s, nineGridInfo->flFlags); /* flFlags (4 bytes) */ stream_read_uint16(s, nineGridInfo->ulLeftWidth); /* ulLeftWidth (2 bytes) */ stream_read_uint16(s, nineGridInfo->ulRightWidth); /* ulRightWidth (2 bytes) */ stream_read_uint16(s, nineGridInfo->ulTopHeight); /* ulTopHeight (2 bytes) */ stream_read_uint16(s, nineGridInfo->ulBottomHeight); /* ulBottomHeight (2 bytes) */ update_read_colorref(s, &nineGridInfo->crTransparent); /* crTransparent (4 bytes) */ } void update_read_frame_marker_order(STREAM* s, FRAME_MARKER_ORDER* frame_marker) { stream_read_uint32(s, frame_marker->action); /* action (4 bytes) */ } void update_read_stream_bitmap_first_order(STREAM* s, STREAM_BITMAP_FIRST_ORDER* stream_bitmap_first) { stream_read_uint8(s, stream_bitmap_first->bitmapFlags); /* bitmapFlags (1 byte) */ stream_read_uint8(s, stream_bitmap_first->bitmapBpp); /* bitmapBpp (1 byte) */ stream_read_uint16(s, stream_bitmap_first->bitmapType); /* bitmapType (2 bytes) */ stream_read_uint16(s, stream_bitmap_first->bitmapWidth); /* bitmapWidth (2 bytes) */ stream_read_uint16(s, stream_bitmap_first->bitmapHeight); /* bitmapHeigth (2 bytes) */ if (stream_bitmap_first->bitmapFlags & STREAM_BITMAP_V2) stream_read_uint32(s, stream_bitmap_first->bitmapSize); /* bitmapSize (4 bytes) */ else stream_read_uint16(s, stream_bitmap_first->bitmapSize); /* bitmapSize (2 bytes) */ stream_read_uint16(s, stream_bitmap_first->bitmapBlockSize); /* bitmapBlockSize (2 bytes) */ stream_seek(s, stream_bitmap_first->bitmapBlockSize); /* bitmapBlock */ } void update_read_stream_bitmap_next_order(STREAM* s, STREAM_BITMAP_FIRST_ORDER* stream_bitmap_next) { stream_read_uint8(s, stream_bitmap_next->bitmapFlags); /* bitmapFlags (1 byte) */ stream_read_uint16(s, stream_bitmap_next->bitmapType); /* bitmapType (2 bytes) */ stream_read_uint16(s, stream_bitmap_next->bitmapBlockSize); /* bitmapBlockSize (2 bytes) */ stream_seek(s, stream_bitmap_next->bitmapBlockSize); /* bitmapBlock */ } void update_read_draw_gdiplus_first_order(STREAM* s, DRAW_GDIPLUS_FIRST_ORDER* draw_gdiplus_first) { stream_seek_uint8(s); /* pad1Octet (1 byte) */ stream_read_uint16(s, draw_gdiplus_first->cbSize); /* cbSize (2 bytes) */ stream_read_uint32(s, draw_gdiplus_first->cbTotalSize); /* cbTotalSize (4 bytes) */ stream_read_uint32(s, draw_gdiplus_first->cbTotalEmfSize); /* cbTotalEmfSize (4 bytes) */ stream_seek(s, draw_gdiplus_first->cbSize); /* emfRecords */ } void update_read_draw_gdiplus_next_order(STREAM* s, DRAW_GDIPLUS_NEXT_ORDER* draw_gdiplus_next) { stream_seek_uint8(s); /* pad1Octet (1 byte) */ stream_read_uint16(s, draw_gdiplus_next->cbSize); /* cbSize (2 bytes) */ stream_seek(s, draw_gdiplus_next->cbSize); /* emfRecords */ } void update_read_draw_gdiplus_end_order(STREAM* s, DRAW_GDIPLUS_END_ORDER* draw_gdiplus_end) { stream_seek_uint8(s); /* pad1Octet (1 byte) */ stream_read_uint16(s, draw_gdiplus_end->cbSize); /* cbSize (2 bytes) */ stream_read_uint32(s, draw_gdiplus_end->cbTotalSize); /* cbTotalSize (4 bytes) */ stream_read_uint32(s, draw_gdiplus_end->cbTotalEmfSize); /* cbTotalEmfSize (4 bytes) */ stream_seek(s, draw_gdiplus_end->cbSize); /* emfRecords */ } void update_read_draw_gdiplus_cache_first_order(STREAM* s, DRAW_GDIPLUS_CACHE_FIRST_ORDER* draw_gdiplus_cache_first) { stream_read_uint8(s, draw_gdiplus_cache_first->flags); /* flags (1 byte) */ stream_read_uint16(s, draw_gdiplus_cache_first->cacheType); /* cacheType (2 bytes) */ stream_read_uint16(s, draw_gdiplus_cache_first->cacheIndex); /* cacheIndex (2 bytes) */ stream_read_uint16(s, draw_gdiplus_cache_first->cbSize); /* cbSize (2 bytes) */ stream_read_uint32(s, draw_gdiplus_cache_first->cbTotalSize); /* cbTotalSize (4 bytes) */ stream_seek(s, draw_gdiplus_cache_first->cbSize); /* emfRecords */ } void update_read_draw_gdiplus_cache_next_order(STREAM* s, DRAW_GDIPLUS_CACHE_NEXT_ORDER* draw_gdiplus_cache_next) { stream_read_uint8(s, draw_gdiplus_cache_next->flags); /* flags (1 byte) */ stream_read_uint16(s, draw_gdiplus_cache_next->cacheType); /* cacheType (2 bytes) */ stream_read_uint16(s, draw_gdiplus_cache_next->cacheIndex); /* cacheIndex (2 bytes) */ stream_read_uint16(s, draw_gdiplus_cache_next->cbSize); /* cbSize (2 bytes) */ stream_seek(s, draw_gdiplus_cache_next->cbSize); /* emfRecords */ } void update_read_draw_gdiplus_cache_end_order(STREAM* s, DRAW_GDIPLUS_CACHE_END_ORDER* draw_gdiplus_cache_end) { stream_read_uint8(s, draw_gdiplus_cache_end->flags); /* flags (1 byte) */ stream_read_uint16(s, draw_gdiplus_cache_end->cacheType); /* cacheType (2 bytes) */ stream_read_uint16(s, draw_gdiplus_cache_end->cacheIndex); /* cacheIndex (2 bytes) */ stream_read_uint16(s, draw_gdiplus_cache_end->cbSize); /* cbSize (2 bytes) */ stream_read_uint32(s, draw_gdiplus_cache_end->cbTotalSize); /* cbTotalSize (4 bytes) */ stream_seek(s, draw_gdiplus_cache_end->cbSize); /* emfRecords */ } void update_read_field_flags(STREAM* s, uint32* fieldFlags, uint8 flags, uint8 fieldBytes) { int i; uint8 byte; if (flags & ORDER_ZERO_FIELD_BYTE_BIT0) fieldBytes--; if (flags & ORDER_ZERO_FIELD_BYTE_BIT1) { if (fieldBytes > 1) fieldBytes -= 2; else fieldBytes = 0; } *fieldFlags = 0; for (i = 0; i < fieldBytes; i++) { stream_read_uint8(s, byte); *fieldFlags |= byte << (i * 8); } } void update_read_bounds(STREAM* s, rdpBounds* bounds) { uint8 flags; stream_read_uint8(s, flags); /* field flags */ if (flags & BOUND_LEFT) update_read_coord(s, &bounds->left, false); else if (flags & BOUND_DELTA_LEFT) update_read_coord(s, &bounds->left, true); if (flags & BOUND_TOP) update_read_coord(s, &bounds->top, false); else if (flags & BOUND_DELTA_TOP) update_read_coord(s, &bounds->top, true); if (flags & BOUND_RIGHT) update_read_coord(s, &bounds->right, false); else if (flags & BOUND_DELTA_RIGHT) update_read_coord(s, &bounds->right, true); if (flags & BOUND_BOTTOM) update_read_coord(s, &bounds->bottom, false); else if (flags & BOUND_DELTA_BOTTOM) update_read_coord(s, &bounds->bottom, true); } void update_recv_primary_order(rdpUpdate* update, STREAM* s, uint8 flags) { ORDER_INFO* orderInfo; rdpContext* context = update->context; rdpPrimaryUpdate* primary = update->primary; orderInfo = &(primary->order_info); if (flags & ORDER_TYPE_CHANGE) stream_read_uint8(s, orderInfo->orderType); /* orderType (1 byte) */ update_read_field_flags(s, &(orderInfo->fieldFlags), flags, PRIMARY_DRAWING_ORDER_FIELD_BYTES[orderInfo->orderType]); if (flags & ORDER_BOUNDS) { if (!(flags & ORDER_ZERO_BOUNDS_DELTAS)) update_read_bounds(s, &orderInfo->bounds); IFCALL(update->SetBounds, context, &orderInfo->bounds); } orderInfo->deltaCoordinates = (flags & ORDER_DELTA_COORDINATES) ? true : false; #ifdef WITH_DEBUG_ORDERS if (orderInfo->orderType < PRIMARY_DRAWING_ORDER_COUNT) printf("%s Primary Drawing Order (0x%02X)\n", PRIMARY_DRAWING_ORDER_STRINGS[orderInfo->orderType], orderInfo->orderType); else printf("Unknown Primary Drawing Order (0x%02X)\n", orderInfo->orderType); #endif switch (orderInfo->orderType) { case ORDER_TYPE_DSTBLT: update_read_dstblt_order(s, orderInfo, &(primary->dstblt)); IFCALL(primary->DstBlt, context, &primary->dstblt); break; case ORDER_TYPE_PATBLT: update_read_patblt_order(s, orderInfo, &(primary->patblt)); IFCALL(primary->PatBlt, context, &primary->patblt); break; case ORDER_TYPE_SCRBLT: update_read_scrblt_order(s, orderInfo, &(primary->scrblt)); IFCALL(primary->ScrBlt, context, &primary->scrblt); break; case ORDER_TYPE_OPAQUE_RECT: update_read_opaque_rect_order(s, orderInfo, &(primary->opaque_rect)); IFCALL(primary->OpaqueRect, context, &primary->opaque_rect); break; case ORDER_TYPE_DRAW_NINE_GRID: update_read_draw_nine_grid_order(s, orderInfo, &(primary->draw_nine_grid)); IFCALL(primary->DrawNineGrid, context, &primary->draw_nine_grid); break; case ORDER_TYPE_MULTI_DSTBLT: update_read_multi_dstblt_order(s, orderInfo, &(primary->multi_dstblt)); IFCALL(primary->MultiDstBlt, context, &primary->multi_dstblt); break; case ORDER_TYPE_MULTI_PATBLT: update_read_multi_patblt_order(s, orderInfo, &(primary->multi_patblt)); IFCALL(primary->MultiPatBlt, context, &primary->multi_patblt); break; case ORDER_TYPE_MULTI_SCRBLT: update_read_multi_scrblt_order(s, orderInfo, &(primary->multi_scrblt)); IFCALL(primary->MultiScrBlt, context, &primary->multi_scrblt); break; case ORDER_TYPE_MULTI_OPAQUE_RECT: update_read_multi_opaque_rect_order(s, orderInfo, &(primary->multi_opaque_rect)); IFCALL(primary->MultiOpaqueRect, context, &primary->multi_opaque_rect); break; case ORDER_TYPE_MULTI_DRAW_NINE_GRID: update_read_multi_draw_nine_grid_order(s, orderInfo, &(primary->multi_draw_nine_grid)); IFCALL(primary->MultiDrawNineGrid, context, &primary->multi_draw_nine_grid); break; case ORDER_TYPE_LINE_TO: update_read_line_to_order(s, orderInfo, &(primary->line_to)); IFCALL(primary->LineTo, context, &primary->line_to); break; case ORDER_TYPE_POLYLINE: update_read_polyline_order(s, orderInfo, &(primary->polyline)); IFCALL(primary->Polyline, context, &primary->polyline); break; case ORDER_TYPE_MEMBLT: update_read_memblt_order(s, orderInfo, &(primary->memblt)); IFCALL(primary->MemBlt, context, &primary->memblt); break; case ORDER_TYPE_MEM3BLT: update_read_mem3blt_order(s, orderInfo, &(primary->mem3blt)); IFCALL(primary->Mem3Blt, context, &primary->mem3blt); break; case ORDER_TYPE_SAVE_BITMAP: update_read_save_bitmap_order(s, orderInfo, &(primary->save_bitmap)); IFCALL(primary->SaveBitmap, context, &primary->save_bitmap); break; case ORDER_TYPE_GLYPH_INDEX: update_read_glyph_index_order(s, orderInfo, &(primary->glyph_index)); IFCALL(primary->GlyphIndex, context, &primary->glyph_index); break; case ORDER_TYPE_FAST_INDEX: update_read_fast_index_order(s, orderInfo, &(primary->fast_index)); IFCALL(primary->FastIndex, context, &primary->fast_index); break; case ORDER_TYPE_FAST_GLYPH: update_read_fast_glyph_order(s, orderInfo, &(primary->fast_glyph)); IFCALL(primary->FastGlyph, context, &primary->fast_glyph); break; case ORDER_TYPE_POLYGON_SC: update_read_polygon_sc_order(s, orderInfo, &(primary->polygon_sc)); IFCALL(primary->PolygonSC, context, &primary->polygon_sc); break; case ORDER_TYPE_POLYGON_CB: update_read_polygon_cb_order(s, orderInfo, &(primary->polygon_cb)); IFCALL(primary->PolygonCB, context, &primary->polygon_cb); break; case ORDER_TYPE_ELLIPSE_SC: update_read_ellipse_sc_order(s, orderInfo, &(primary->ellipse_sc)); IFCALL(primary->EllipseSC, context, &primary->ellipse_sc); break; case ORDER_TYPE_ELLIPSE_CB: update_read_ellipse_cb_order(s, orderInfo, &(primary->ellipse_cb)); IFCALL(primary->EllipseCB, context, &primary->ellipse_cb); break; default: break; } if (flags & ORDER_BOUNDS) { IFCALL(update->SetBounds, context, NULL); } } void update_recv_secondary_order(rdpUpdate* update, STREAM* s, uint8 flags) { uint8* next; uint8 orderType; uint16 extraFlags; uint16 orderLength; rdpContext* context = update->context; rdpSecondaryUpdate* secondary = update->secondary; stream_read_uint16(s, orderLength); /* orderLength (2 bytes) */ stream_read_uint16(s, extraFlags); /* extraFlags (2 bytes) */ stream_read_uint8(s, orderType); /* orderType (1 byte) */ next = s->p + ((sint16) orderLength) + 7; #ifdef WITH_DEBUG_ORDERS if (orderType < SECONDARY_DRAWING_ORDER_COUNT) printf("%s Secondary Drawing Order (0x%02X)\n", SECONDARY_DRAWING_ORDER_STRINGS[orderType], orderType); else printf("Unknown Secondary Drawing Order (0x%02X)\n", orderType); #endif switch (orderType) { case ORDER_TYPE_BITMAP_UNCOMPRESSED: update_read_cache_bitmap_order(s, &(secondary->cache_bitmap_order), false, extraFlags); IFCALL(secondary->CacheBitmap, context, &(secondary->cache_bitmap_order)); break; case ORDER_TYPE_CACHE_BITMAP_COMPRESSED: update_read_cache_bitmap_order(s, &(secondary->cache_bitmap_order), true, extraFlags); IFCALL(secondary->CacheBitmap, context, &(secondary->cache_bitmap_order)); break; case ORDER_TYPE_BITMAP_UNCOMPRESSED_V2: update_read_cache_bitmap_v2_order(s, &(secondary->cache_bitmap_v2_order), false, extraFlags); IFCALL(secondary->CacheBitmapV2, context, &(secondary->cache_bitmap_v2_order)); break; case ORDER_TYPE_BITMAP_COMPRESSED_V2: update_read_cache_bitmap_v2_order(s, &(secondary->cache_bitmap_v2_order), true, extraFlags); IFCALL(secondary->CacheBitmapV2, context, &(secondary->cache_bitmap_v2_order)); break; case ORDER_TYPE_BITMAP_COMPRESSED_V3: update_read_cache_bitmap_v3_order(s, &(secondary->cache_bitmap_v3_order), true, extraFlags); IFCALL(secondary->CacheBitmapV3, context, &(secondary->cache_bitmap_v3_order)); break; case ORDER_TYPE_CACHE_COLOR_TABLE: update_read_cache_color_table_order(s, &(secondary->cache_color_table_order), extraFlags); IFCALL(secondary->CacheColorTable, context, &(secondary->cache_color_table_order)); break; case ORDER_TYPE_CACHE_GLYPH: if (secondary->glyph_v2) { update_read_cache_glyph_v2_order(s, &(secondary->cache_glyph_v2_order), extraFlags); IFCALL(secondary->CacheGlyphV2, context, &(secondary->cache_glyph_v2_order)); } else { update_read_cache_glyph_order(s, &(secondary->cache_glyph_order), extraFlags); IFCALL(secondary->CacheGlyph, context, &(secondary->cache_glyph_order)); } break; case ORDER_TYPE_CACHE_BRUSH: update_read_cache_brush_order(s, &(secondary->cache_brush_order), extraFlags); IFCALL(secondary->CacheBrush, context, &(secondary->cache_brush_order)); break; default: break; } s->p = next; } void update_recv_altsec_order(rdpUpdate* update, STREAM* s, uint8 flags) { uint8 orderType; rdpContext* context = update->context; rdpAltSecUpdate* altsec = update->altsec; orderType = flags >>= 2; /* orderType is in higher 6 bits of flags field */ #ifdef WITH_DEBUG_ORDERS if (orderType < ALTSEC_DRAWING_ORDER_COUNT) printf("%s Alternate Secondary Drawing Order (0x%02X)\n", ALTSEC_DRAWING_ORDER_STRINGS[orderType], orderType); else printf("Unknown Alternate Secondary Drawing Order: 0x%02X\n", orderType); #endif switch (orderType) { case ORDER_TYPE_CREATE_OFFSCREEN_BITMAP: update_read_create_offscreen_bitmap_order(s, &(altsec->create_offscreen_bitmap)); IFCALL(altsec->CreateOffscreenBitmap, context, &(altsec->create_offscreen_bitmap)); break; case ORDER_TYPE_SWITCH_SURFACE: update_read_switch_surface_order(s, &(altsec->switch_surface)); IFCALL(altsec->SwitchSurface, context, &(altsec->switch_surface)); break; case ORDER_TYPE_CREATE_NINE_GRID_BITMAP: update_read_create_nine_grid_bitmap_order(s, &(altsec->create_nine_grid_bitmap)); IFCALL(altsec->CreateNineGridBitmap, context, &(altsec->create_nine_grid_bitmap)); break; case ORDER_TYPE_FRAME_MARKER: update_read_frame_marker_order(s, &(altsec->frame_marker)); IFCALL(altsec->FrameMarker, context, &(altsec->frame_marker)); break; case ORDER_TYPE_STREAM_BITMAP_FIRST: update_read_stream_bitmap_first_order(s, &(altsec->stream_bitmap_first)); IFCALL(altsec->StreamBitmapFirst, context, &(altsec->stream_bitmap_first)); break; case ORDER_TYPE_STREAM_BITMAP_NEXT: update_read_stream_bitmap_next_order(s, &(altsec->stream_bitmap_next)); IFCALL(altsec->StreamBitmapNext, context, &(altsec->stream_bitmap_next)); break; case ORDER_TYPE_GDIPLUS_FIRST: update_read_draw_gdiplus_first_order(s, &(altsec->draw_gdiplus_first)); IFCALL(altsec->DrawGdiPlusFirst, context, &(altsec->draw_gdiplus_first)); break; case ORDER_TYPE_GDIPLUS_NEXT: update_read_draw_gdiplus_next_order(s, &(altsec->draw_gdiplus_next)); IFCALL(altsec->DrawGdiPlusNext, context, &(altsec->draw_gdiplus_next)); break; case ORDER_TYPE_GDIPLUS_END: update_read_draw_gdiplus_end_order(s, &(altsec->draw_gdiplus_end)); IFCALL(altsec->DrawGdiPlusEnd, context, &(altsec->draw_gdiplus_end)); break; case ORDER_TYPE_GDIPLUS_CACHE_FIRST: update_read_draw_gdiplus_cache_first_order(s, &(altsec->draw_gdiplus_cache_first)); IFCALL(altsec->DrawGdiPlusCacheFirst, context, &(altsec->draw_gdiplus_cache_first)); break; case ORDER_TYPE_GDIPLUS_CACHE_NEXT: update_read_draw_gdiplus_cache_next_order(s, &(altsec->draw_gdiplus_cache_next)); IFCALL(altsec->DrawGdiPlusCacheNext, context, &(altsec->draw_gdiplus_cache_next)); break; case ORDER_TYPE_GDIPLUS_CACHE_END: update_read_draw_gdiplus_cache_end_order(s, &(altsec->draw_gdiplus_cache_end)); IFCALL(altsec->DrawGdiPlusCacheEnd, context, &(altsec->draw_gdiplus_cache_end)); break; case ORDER_TYPE_WINDOW: update_recv_altsec_window_order(update, s); break; case ORDER_TYPE_COMPDESK_FIRST: break; default: break; } } void update_recv_order(rdpUpdate* update, STREAM* s) { uint8 controlFlags; stream_read_uint8(s, controlFlags); /* controlFlags (1 byte) */ if (!(controlFlags & ORDER_STANDARD)) update_recv_altsec_order(update, s, controlFlags); else if (controlFlags & ORDER_SECONDARY) update_recv_secondary_order(update, s, controlFlags); else update_recv_primary_order(update, s, controlFlags); } FreeRDP-1.0.2/libfreerdp-core/orders.h000066400000000000000000000244461207112532300174620ustar00rootroot00000000000000/** * FreeRDP: A Remote Desktop Protocol Client * Drawing Orders * * Copyright 2011 Marc-Andre Moreau * * 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. */ #ifndef __ORDERS_H #define __ORDERS_H #include "rdp.h" #include #include #include /* Order Control Flags */ #define ORDER_STANDARD 0x01 #define ORDER_SECONDARY 0x02 #define ORDER_BOUNDS 0x04 #define ORDER_TYPE_CHANGE 0x08 #define ORDER_DELTA_COORDINATES 0x10 #define ORDER_ZERO_BOUNDS_DELTAS 0x20 #define ORDER_ZERO_FIELD_BYTE_BIT0 0x40 #define ORDER_ZERO_FIELD_BYTE_BIT1 0x80 /* Bound Field Flags */ #define BOUND_LEFT 0x01 #define BOUND_TOP 0x02 #define BOUND_RIGHT 0x04 #define BOUND_BOTTOM 0x08 #define BOUND_DELTA_LEFT 0x10 #define BOUND_DELTA_TOP 0x20 #define BOUND_DELTA_RIGHT 0x40 #define BOUND_DELTA_BOTTOM 0x80 /* Field Presence Flags */ #define ORDER_FIELD_01 0x000001 #define ORDER_FIELD_02 0x000002 #define ORDER_FIELD_03 0x000004 #define ORDER_FIELD_04 0x000008 #define ORDER_FIELD_05 0x000010 #define ORDER_FIELD_06 0x000020 #define ORDER_FIELD_07 0x000040 #define ORDER_FIELD_08 0x000080 #define ORDER_FIELD_09 0x000100 #define ORDER_FIELD_10 0x000200 #define ORDER_FIELD_11 0x000400 #define ORDER_FIELD_12 0x000800 #define ORDER_FIELD_13 0x001000 #define ORDER_FIELD_14 0x002000 #define ORDER_FIELD_15 0x004000 #define ORDER_FIELD_16 0x008000 #define ORDER_FIELD_17 0x010000 #define ORDER_FIELD_18 0x020000 #define ORDER_FIELD_19 0x040000 #define ORDER_FIELD_20 0x080000 #define ORDER_FIELD_21 0x100000 #define ORDER_FIELD_22 0x200000 #define ORDER_FIELD_23 0x400000 /* Bitmap Cache Flags */ #define CBR2_8BPP 0x3 #define CBR2_16BPP 0x4 #define CBR2_24BPP 0x5 #define CBR2_32BPP 0x6 #define CBR23_8BPP 0x3 #define CBR23_16BPP 0x4 #define CBR23_24BPP 0x5 #define CBR23_32BPP 0x6 #define CBR3_IGNORABLE_FLAG 0x08 #define CBR3_DO_NOT_CACHE 0x10 /* Primary Drawing Orders */ #define ORDER_TYPE_DSTBLT 0x00 #define ORDER_TYPE_PATBLT 0x01 #define ORDER_TYPE_SCRBLT 0x02 #define ORDER_TYPE_DRAW_NINE_GRID 0x07 #define ORDER_TYPE_MULTI_DRAW_NINE_GRID 0x08 #define ORDER_TYPE_LINE_TO 0x09 #define ORDER_TYPE_OPAQUE_RECT 0x0A #define ORDER_TYPE_SAVE_BITMAP 0x0B #define ORDER_TYPE_MEMBLT 0x0D #define ORDER_TYPE_MEM3BLT 0x0E #define ORDER_TYPE_MULTI_DSTBLT 0x0F #define ORDER_TYPE_MULTI_PATBLT 0x10 #define ORDER_TYPE_MULTI_SCRBLT 0x11 #define ORDER_TYPE_MULTI_OPAQUE_RECT 0x12 #define ORDER_TYPE_FAST_INDEX 0x13 #define ORDER_TYPE_POLYGON_SC 0x14 #define ORDER_TYPE_POLYGON_CB 0x15 #define ORDER_TYPE_POLYLINE 0x16 #define ORDER_TYPE_FAST_GLYPH 0x18 #define ORDER_TYPE_ELLIPSE_SC 0x19 #define ORDER_TYPE_ELLIPSE_CB 0x1A #define ORDER_TYPE_GLYPH_INDEX 0x1B /* Primary Drawing Orders Fields */ #define DSTBLT_ORDER_FIELDS 5 #define PATBLT_ORDER_FIELDS 12 #define SCRBLT_ORDER_FIELDS 7 #define DRAW_NINE_GRID_ORDER_FIELDS 5 #define MULTI_DRAW_NINE_GRID_ORDER_FIELDS 7 #define LINE_TO_ORDER_FIELDS 10 #define OPAQUE_RECT_ORDER_FIELDS 7 #define SAVE_BITMAP_ORDER_FIELDS 6 #define MEMBLT_ORDER_FIELDS 9 #define MEM3BLT_ORDER_FIELDS 16 #define MULTI_DSTBLT_ORDER_FIELDS 7 #define MULTI_PATBLT_ORDER_FIELDS 14 #define MULTI_SCRBLT_ORDER_FIELDS 9 #define MULTI_OPAQUE_RECT_ORDER_FIELDS 9 #define FAST_INDEX_ORDER_FIELDS 15 #define POLYGON_SC_ORDER_FIELDS 7 #define POLYGON_CB_ORDER_FIELDS 13 #define POLYLINE_ORDER_FIELDS 7 #define FAST_GLYPH_ORDER_FIELDS 15 #define ELLIPSE_SC_ORDER_FIELDS 7 #define ELLIPSE_CB_ORDER_FIELDS 13 #define GLYPH_INDEX_ORDER_FIELDS 22 /* Primary Drawing Orders Field Bytes */ #define DSTBLT_ORDER_FIELD_BYTES 1 #define PATBLT_ORDER_FIELD_BYTES 2 #define SCRBLT_ORDER_FIELD_BYTES 1 #define DRAW_NINE_GRID_ORDER_FIELD_BYTES 1 #define MULTI_DRAW_NINE_GRID_ORDER_FIELD_BYTES 1 #define LINE_TO_ORDER_FIELD_BYTES 2 #define OPAQUE_RECT_ORDER_FIELD_BYTES 1 #define SAVE_BITMAP_ORDER_FIELD_BYTES 1 #define MEMBLT_ORDER_FIELD_BYTES 2 #define MEM3BLT_ORDER_FIELD_BYTES 3 #define MULTI_DSTBLT_ORDER_FIELD_BYTES 1 #define MULTI_PATBLT_ORDER_FIELD_BYTES 2 #define MULTI_SCRBLT_ORDER_FIELD_BYTES 2 #define MULTI_OPAQUE_RECT_ORDER_FIELD_BYTES 2 #define FAST_INDEX_ORDER_FIELD_BYTES 2 #define POLYGON_SC_ORDER_FIELD_BYTES 1 #define POLYGON_CB_ORDER_FIELD_BYTES 2 #define POLYLINE_ORDER_FIELD_BYTES 1 #define FAST_GLYPH_ORDER_FIELD_BYTES 2 #define ELLIPSE_SC_ORDER_FIELD_BYTES 1 #define ELLIPSE_CB_ORDER_FIELD_BYTES 2 #define GLYPH_INDEX_ORDER_FIELD_BYTES 3 /* Secondary Drawing Orders */ #define ORDER_TYPE_BITMAP_UNCOMPRESSED 0x00 #define ORDER_TYPE_CACHE_COLOR_TABLE 0x01 #define ORDER_TYPE_CACHE_BITMAP_COMPRESSED 0x02 #define ORDER_TYPE_CACHE_GLYPH 0x03 #define ORDER_TYPE_BITMAP_UNCOMPRESSED_V2 0x04 #define ORDER_TYPE_BITMAP_COMPRESSED_V2 0x05 #define ORDER_TYPE_CACHE_BRUSH 0x07 #define ORDER_TYPE_BITMAP_COMPRESSED_V3 0x08 /* Alternate Secondary Drawing Orders */ #define ORDER_TYPE_SWITCH_SURFACE 0x00 #define ORDER_TYPE_CREATE_OFFSCREEN_BITMAP 0x01 #define ORDER_TYPE_STREAM_BITMAP_FIRST 0x02 #define ORDER_TYPE_STREAM_BITMAP_NEXT 0x03 #define ORDER_TYPE_CREATE_NINE_GRID_BITMAP 0x04 #define ORDER_TYPE_GDIPLUS_FIRST 0x05 #define ORDER_TYPE_GDIPLUS_NEXT 0x06 #define ORDER_TYPE_GDIPLUS_END 0x07 #define ORDER_TYPE_GDIPLUS_CACHE_FIRST 0x08 #define ORDER_TYPE_GDIPLUS_CACHE_NEXT 0x09 #define ORDER_TYPE_GDIPLUS_CACHE_END 0x0A #define ORDER_TYPE_WINDOW 0x0B #define ORDER_TYPE_COMPDESK_FIRST 0x0C #define ORDER_TYPE_FRAME_MARKER 0x0D #define CG_GLYPH_UNICODE_PRESENT 0x0010 void update_recv_order(rdpUpdate* update, STREAM* s); void update_read_dstblt_order(STREAM* s, ORDER_INFO* orderInfo, DSTBLT_ORDER* dstblt); void update_read_patblt_order(STREAM* s, ORDER_INFO* orderInfo, PATBLT_ORDER* patblt); void update_read_scrblt_order(STREAM* s, ORDER_INFO* orderInfo, SCRBLT_ORDER* scrblt); void update_read_opaque_rect_order(STREAM* s, ORDER_INFO* orderInfo, OPAQUE_RECT_ORDER* opaque_rect); void update_read_draw_nine_grid_order(STREAM* s, ORDER_INFO* orderInfo, DRAW_NINE_GRID_ORDER* draw_nine_grid); void update_read_multi_dstblt_order(STREAM* s, ORDER_INFO* orderInfo, MULTI_DSTBLT_ORDER* multi_dstblt); void update_read_multi_patblt_order(STREAM* s, ORDER_INFO* orderInfo, MULTI_PATBLT_ORDER* multi_patblt); void update_read_multi_scrblt_order(STREAM* s, ORDER_INFO* orderInfo, MULTI_SCRBLT_ORDER* multi_scrblt); void update_read_multi_opaque_rect_order(STREAM* s, ORDER_INFO* orderInfo, MULTI_OPAQUE_RECT_ORDER* multi_opaque_rect); void update_read_multi_draw_nine_grid_order(STREAM* s, ORDER_INFO* orderInfo, MULTI_DRAW_NINE_GRID_ORDER* multi_draw_nine_grid); void update_read_line_to_order(STREAM* s, ORDER_INFO* orderInfo, LINE_TO_ORDER* line_to); void update_read_polyline_order(STREAM* s, ORDER_INFO* orderInfo, POLYLINE_ORDER* polyline); void update_read_memblt_order(STREAM* s, ORDER_INFO* orderInfo, MEMBLT_ORDER* memblt); void update_read_mem3blt_order(STREAM* s, ORDER_INFO* orderInfo, MEM3BLT_ORDER* mem3blt); void update_read_save_bitmap_order(STREAM* s, ORDER_INFO* orderInfo, SAVE_BITMAP_ORDER* save_bitmap); void update_read_glyph_index_order(STREAM* s, ORDER_INFO* orderInfo, GLYPH_INDEX_ORDER* glyph_index); void update_read_fast_index_order(STREAM* s, ORDER_INFO* orderInfo, FAST_INDEX_ORDER* fast_index); void update_read_fast_glyph_order(STREAM* s, ORDER_INFO* orderInfo, FAST_GLYPH_ORDER* fast_glyph); void update_read_polygon_sc_order(STREAM* s, ORDER_INFO* orderInfo, POLYGON_SC_ORDER* polygon_sc); void update_read_polygon_cb_order(STREAM* s, ORDER_INFO* orderInfo, POLYGON_CB_ORDER* polygon_cb); void update_read_ellipse_sc_order(STREAM* s, ORDER_INFO* orderInfo, ELLIPSE_SC_ORDER* ellipse_sc); void update_read_ellipse_cb_order(STREAM* s, ORDER_INFO* orderInfo, ELLIPSE_CB_ORDER* ellipse_cb); void update_read_cache_bitmap_order(STREAM* s, CACHE_BITMAP_ORDER* cache_bitmap_order, boolean compressed, uint16 flags); void update_read_cache_bitmap_v2_order(STREAM* s, CACHE_BITMAP_V2_ORDER* cache_bitmap_v2_order, boolean compressed, uint16 flags); void update_read_cache_bitmap_v3_order(STREAM* s, CACHE_BITMAP_V3_ORDER* cache_bitmap_v3_order, boolean compressed, uint16 flags); void update_read_cache_color_table_order(STREAM* s, CACHE_COLOR_TABLE_ORDER* cache_color_table_order, uint16 flags); void update_read_cache_glyph_order(STREAM* s, CACHE_GLYPH_ORDER* cache_glyph_order, uint16 flags); void update_read_cache_glyph_v2_order(STREAM* s, CACHE_GLYPH_V2_ORDER* cache_glyph_v2_order, uint16 flags); void update_read_cache_brush_order(STREAM* s, CACHE_BRUSH_ORDER* cache_brush_order, uint16 flags); void update_read_create_offscreen_bitmap_order(STREAM* s, CREATE_OFFSCREEN_BITMAP_ORDER* create_offscreen_bitmap); void update_read_switch_surface_order(STREAM* s, SWITCH_SURFACE_ORDER* switch_surface); void update_read_create_nine_grid_bitmap_order(STREAM* s, CREATE_NINE_GRID_BITMAP_ORDER* create_nine_grid_bitmap); void update_read_frame_marker_order(STREAM* s, FRAME_MARKER_ORDER* frame_marker); void update_read_stream_bitmap_first_order(STREAM* s, STREAM_BITMAP_FIRST_ORDER* stream_bitmap_first); void update_read_stream_bitmap_next_order(STREAM* s, STREAM_BITMAP_FIRST_ORDER* stream_bitmap_next); void update_read_draw_gdiplus_first_order(STREAM* s, DRAW_GDIPLUS_FIRST_ORDER* draw_gdiplus_first); void update_read_draw_gdiplus_next_order(STREAM* s, DRAW_GDIPLUS_NEXT_ORDER* draw_gdiplus_next); void update_read_draw_gdiplus_end_order(STREAM* s, DRAW_GDIPLUS_END_ORDER* draw_gdiplus_end); void update_read_draw_gdiplus_cache_first_order(STREAM* s, DRAW_GDIPLUS_CACHE_FIRST_ORDER* draw_gdiplus_cache_first); void update_read_draw_gdiplus_cache_next_order(STREAM* s, DRAW_GDIPLUS_CACHE_NEXT_ORDER* draw_gdiplus_cache_next); void update_read_draw_gdiplus_cache_end_order(STREAM* s, DRAW_GDIPLUS_CACHE_END_ORDER* draw_gdiplus_cache_end); #endif /* __ORDERS_H */ FreeRDP-1.0.2/libfreerdp-core/peer.c000066400000000000000000000205101207112532300170760ustar00rootroot00000000000000/** * FreeRDP: A Remote Desktop Protocol client. * RDP Server Peer * * Copyright 2011 Vic Lee * * 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. */ #include "peer.h" static boolean freerdp_peer_initialize(freerdp_peer* client) { client->context->rdp->settings->server_mode = true; client->context->rdp->state = CONNECTION_STATE_INITIAL; if (client->context->rdp->settings->rdp_key_file != NULL) { client->context->rdp->settings->server_key = key_new(client->context->rdp->settings->rdp_key_file); } return true; } static boolean freerdp_peer_get_fds(freerdp_peer* client, void** rfds, int* rcount) { rfds[*rcount] = (void*)(long)(client->context->rdp->transport->tcp->sockfd); (*rcount)++; return true; } static boolean freerdp_peer_check_fds(freerdp_peer* client) { rdpRdp* rdp; int status; rdp = client->context->rdp; status = rdp_check_fds(rdp); if (status < 0) return false; return true; } static boolean peer_recv_data_pdu(freerdp_peer* client, STREAM* s) { uint8 type; uint16 length; uint32 share_id; uint8 compressed_type; uint16 compressed_len; if (!rdp_read_share_data_header(s, &length, &type, &share_id, &compressed_type, &compressed_len)) return false; switch (type) { case DATA_PDU_TYPE_SYNCHRONIZE: if (!rdp_recv_client_synchronize_pdu(client->context->rdp, s)) return false; break; case DATA_PDU_TYPE_CONTROL: if (!rdp_server_accept_client_control_pdu(client->context->rdp, s)) return false; break; case DATA_PDU_TYPE_INPUT: if (!input_recv(client->context->rdp->input, s)) return false; break; case DATA_PDU_TYPE_BITMAP_CACHE_PERSISTENT_LIST: /* TODO: notify server bitmap cache data */ break; case DATA_PDU_TYPE_FONT_LIST: if (!rdp_server_accept_client_font_list_pdu(client->context->rdp, s)) return false; if (client->PostConnect) { if (!client->PostConnect(client)) return false; /** * PostConnect should only be called once and should not be called * after a reactivation sequence. */ client->PostConnect = NULL; } if (client->Activate) { /* Activate will be called everytime after the client is activated/reactivated. */ if (!client->Activate(client)) return false; } break; case DATA_PDU_TYPE_SHUTDOWN_REQUEST: mcs_send_disconnect_provider_ultimatum(client->context->rdp->mcs); return false; default: printf("Data PDU type %d\n", type); break; } return true; } static boolean peer_recv_tpkt_pdu(freerdp_peer* client, STREAM* s) { rdpRdp *rdp; uint16 length; uint16 pduType; uint16 pduLength; uint16 pduSource; uint16 channelId; uint16 securityFlags; rdp = client->context->rdp; if (!rdp_read_header(rdp, s, &length, &channelId)) { printf("Incorrect RDP header.\n"); return false; } if (rdp->settings->encryption) { rdp_read_security_header(s, &securityFlags); if (securityFlags & SEC_ENCRYPT) { if (!rdp_decrypt(rdp, s, length - 4, securityFlags)) { printf("rdp_decrypt failed\n"); return false; } } } if (channelId != MCS_GLOBAL_CHANNEL_ID) { freerdp_channel_peer_process(client, s, channelId); } else { if (!rdp_read_share_control_header(s, &pduLength, &pduType, &pduSource)) return false; client->settings->pdu_source = pduSource; switch (pduType) { case PDU_TYPE_DATA: if (!peer_recv_data_pdu(client, s)) return false; break; default: printf("Client sent pduType %d\n", pduType); return false; } } return true; } static boolean peer_recv_fastpath_pdu(freerdp_peer* client, STREAM* s) { uint16 length; rdpRdp* rdp; rdpFastPath* fastpath; rdp = client->context->rdp; fastpath = rdp->fastpath; length = fastpath_read_header_rdp(fastpath, s); if (length == 0 || length > stream_get_left(s)) { printf("incorrect FastPath PDU header length %d\n", length); return false; } if (fastpath->encryptionFlags & FASTPATH_OUTPUT_ENCRYPTED) { rdp_decrypt(rdp, s, length, (fastpath->encryptionFlags & FASTPATH_OUTPUT_SECURE_CHECKSUM) ? SEC_SECURE_CHECKSUM : 0); } return fastpath_recv_inputs(fastpath, s); } static boolean peer_recv_pdu(freerdp_peer* client, STREAM* s) { if (tpkt_verify_header(s)) return peer_recv_tpkt_pdu(client, s); else return peer_recv_fastpath_pdu(client, s); } static boolean peer_recv_callback(rdpTransport* transport, STREAM* s, void* extra) { freerdp_peer* client = (freerdp_peer*) extra; switch (client->context->rdp->state) { case CONNECTION_STATE_INITIAL: if (!rdp_server_accept_nego(client->context->rdp, s)) return false; break; case CONNECTION_STATE_NEGO: if (!rdp_server_accept_mcs_connect_initial(client->context->rdp, s)) return false; break; case CONNECTION_STATE_MCS_CONNECT: if (!rdp_server_accept_mcs_erect_domain_request(client->context->rdp, s)) return false; break; case CONNECTION_STATE_MCS_ERECT_DOMAIN: if (!rdp_server_accept_mcs_attach_user_request(client->context->rdp, s)) return false; break; case CONNECTION_STATE_MCS_ATTACH_USER: if (!rdp_server_accept_mcs_channel_join_request(client->context->rdp, s)) return false; break; case CONNECTION_STATE_MCS_CHANNEL_JOIN: if (client->context->rdp->settings->encryption) { if (!rdp_server_accept_client_keys(client->context->rdp, s)) return false; break; } client->context->rdp->state = CONNECTION_STATE_ESTABLISH_KEYS; /* FALLTHROUGH */ case CONNECTION_STATE_ESTABLISH_KEYS: if (!rdp_server_accept_client_info(client->context->rdp, s)) return false; IFCALL(client->Capabilities, client); if (!rdp_send_demand_active(client->context->rdp)) return false; break; case CONNECTION_STATE_LICENSE: if (!rdp_server_accept_confirm_active(client->context->rdp, s)) { /** * During reactivation sequence the client might sent some input or channel data * before receiving the Deactivate All PDU. We need to process them as usual. */ stream_set_pos(s, 0); return peer_recv_pdu(client, s); } break; case CONNECTION_STATE_ACTIVE: if (!peer_recv_pdu(client, s)) return false; break; default: printf("Invalid state %d\n", client->context->rdp->state); return false; } return true; } static void freerdp_peer_disconnect(freerdp_peer* client) { transport_disconnect(client->context->rdp->transport); } static int freerdp_peer_send_channel_data(freerdp_peer* client, int channelId, uint8* data, int size) { return rdp_send_channel_data(client->context->rdp, channelId, data, size); } void freerdp_peer_context_new(freerdp_peer* client) { rdpRdp* rdp; rdp = rdp_new(NULL); client->input = rdp->input; client->update = rdp->update; client->settings = rdp->settings; client->context = (rdpContext*) xzalloc(client->context_size); client->context->rdp = rdp; client->context->peer = client; client->update->context = client->context; client->input->context = client->context; update_register_server_callbacks(client->update); transport_attach(rdp->transport, client->sockfd); rdp->transport->recv_callback = peer_recv_callback; rdp->transport->recv_extra = client; transport_set_blocking_mode(rdp->transport, false); IFCALL(client->ContextNew, client, client->context); } void freerdp_peer_context_free(freerdp_peer* client) { IFCALL(client->ContextFree, client, client->context); } freerdp_peer* freerdp_peer_new(int sockfd) { freerdp_peer* client; client = xnew(freerdp_peer); if (client != NULL) { client->sockfd = sockfd; client->context_size = sizeof(rdpContext); client->Initialize = freerdp_peer_initialize; client->GetFileDescriptor = freerdp_peer_get_fds; client->CheckFileDescriptor = freerdp_peer_check_fds; client->Disconnect = freerdp_peer_disconnect; client->SendChannelData = freerdp_peer_send_channel_data; } return client; } void freerdp_peer_free(freerdp_peer* client) { if (client) { rdp_free(client->context->rdp); xfree(client); } } FreeRDP-1.0.2/libfreerdp-core/peer.h000066400000000000000000000013651207112532300171120ustar00rootroot00000000000000/** * FreeRDP: A Remote Desktop Protocol client. * RDP Server Peer * * Copyright 2011 Vic Lee * * 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. */ #ifndef __PEER #define __PEER #include "rdp.h" #include #endif /* __PEER */ FreeRDP-1.0.2/libfreerdp-core/per.c000066400000000000000000000177511207112532300167460ustar00rootroot00000000000000/** * FreeRDP: A Remote Desktop Protocol Client * ASN.1 Packed Encoding Rules (BER) * * Copyright 2011 Marc-Andre Moreau * * 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. */ #include "per.h" /** * Read PER length. * @param s stream * @param length length * @return */ boolean per_read_length(STREAM* s, uint16* length) { uint8 byte; stream_read_uint8(s, byte); if (byte & 0x80) { byte &= ~(0x80); *length = (byte << 8); stream_read_uint8(s, byte); *length += byte; } else { *length = byte; } return true; } /** * Write PER length. * @param s stream * @param length length */ void per_write_length(STREAM* s, int length) { if (length > 0x7F) stream_write_uint16_be(s, (length | 0x8000)); else stream_write_uint8(s, length); } /** * Read PER choice. * @param s stream * @param choice choice * @return */ boolean per_read_choice(STREAM* s, uint8* choice) { stream_read_uint8(s, *choice); return true; } /** * Write PER CHOICE. * @param s stream * @param choice index of chosen field */ void per_write_choice(STREAM* s, uint8 choice) { stream_write_uint8(s, choice); } /** * Read PER selection. * @param s stream * @param selection selection * @return */ boolean per_read_selection(STREAM* s, uint8* selection) { stream_read_uint8(s, *selection); return true; } /** * Write PER selection for OPTIONAL fields. * @param s stream * @param selection bit map of selected fields */ void per_write_selection(STREAM* s, uint8 selection) { stream_write_uint8(s, selection); } /** * Read PER number of sets. * @param s stream * @param number number of sets * @return */ boolean per_read_number_of_sets(STREAM* s, uint8* number) { stream_read_uint8(s, *number); return true; } /** * Write PER number of sets for SET OF. * @param s stream * @param number number of sets */ void per_write_number_of_sets(STREAM* s, uint8 number) { stream_write_uint8(s, number); } /** * Read PER padding with zeros. * @param s stream * @param length */ boolean per_read_padding(STREAM* s, int length) { stream_seek(s, length); return true; } /** * Write PER padding with zeros. * @param s stream * @param length */ void per_write_padding(STREAM* s, int length) { int i; for (i = 0; i < length; i++) stream_write_uint8(s, 0); } /** * Read PER INTEGER. * @param s stream * @param integer integer * @return */ boolean per_read_integer(STREAM* s, uint32* integer) { uint16 length; per_read_length(s, &length); if (length == 1) stream_read_uint8(s, *integer); else if (length == 2) stream_read_uint16_be(s, *integer); else return false; return true; } /** * Write PER INTEGER. * @param s stream * @param integer integer */ void per_write_integer(STREAM* s, uint32 integer) { if (integer <= 0xFF) { per_write_length(s, 1); stream_write_uint8(s, integer); } else if (integer <= 0xFFFF) { per_write_length(s, 2); stream_write_uint16_be(s, integer); } else if (integer <= 0xFFFFFFFF) { per_write_length(s, 4); stream_write_uint32_be(s, integer); } } /** * Read PER INTEGER (uint16). * @param s stream * @param integer integer * @param min minimum value * @return */ boolean per_read_integer16(STREAM* s, uint16* integer, uint16 min) { stream_read_uint16_be(s, *integer); if (*integer + min > 0xFFFF) return false; *integer += min; return true; } /** * Write PER INTEGER (uint16). * @param s stream * @param integer integer * @param min minimum value */ void per_write_integer16(STREAM* s, uint16 integer, uint16 min) { stream_write_uint16_be(s, integer - min); } /** * Read PER ENUMERATED. * @param s stream * @param enumerated enumerated * @param count enumeration count * @return */ boolean per_read_enumerated(STREAM* s, uint8* enumerated, uint8 count) { stream_read_uint8(s, *enumerated); /* check that enumerated value falls within expected range */ if (*enumerated + 1 > count) return false; return true; } /** * Write PER ENUMERATED. * @param s stream * @param enumerated enumerated * @param count enumeration count * @return */ void per_write_enumerated(STREAM* s, uint8 enumerated, uint8 count) { stream_write_uint8(s, enumerated); } /** * Read PER OBJECT_IDENTIFIER (OID). * @param s stream * @param oid object identifier (OID) * @return */ boolean per_read_object_identifier(STREAM* s, uint8 oid[6]) { uint8 t12; uint16 length; uint8 a_oid[6]; per_read_length(s, &length); /* length */ if (length != 5) return false; stream_read_uint8(s, t12); /* first two tuples */ a_oid[0] = (t12 >> 4); a_oid[1] = (t12 & 0x0F); stream_read_uint8(s, a_oid[2]); /* tuple 3 */ stream_read_uint8(s, a_oid[3]); /* tuple 4 */ stream_read_uint8(s, a_oid[4]); /* tuple 5 */ stream_read_uint8(s, a_oid[5]); /* tuple 6 */ if ((a_oid[0] == oid[0]) && (a_oid[1] == oid[1]) && (a_oid[2] == oid[2]) && (a_oid[3] == oid[3]) && (a_oid[4] == oid[4]) && (a_oid[5] == oid[5])) { return true; } else { return false; } } /** * Write PER OBJECT_IDENTIFIER (OID) * @param s stream * @param oid object identifier (oid) */ void per_write_object_identifier(STREAM* s, uint8 oid[6]) { uint8 t12 = (oid[0] << 4) & (oid[1] & 0x0F); stream_write_uint8(s, 5); /* length */ stream_write_uint8(s, t12); /* first two tuples */ stream_write_uint8(s, oid[2]); /* tuple 3 */ stream_write_uint8(s, oid[3]); /* tuple 4 */ stream_write_uint8(s, oid[4]); /* tuple 5 */ stream_write_uint8(s, oid[5]); /* tuple 6 */ } /** * Write PER string. * @param s stream * @param str string * @param length string length */ void per_write_string(STREAM* s, uint8* str, int length) { int i; for (i = 0; i < length; i++) stream_write_uint8(s, str[i]); } /** * Read PER OCTET_STRING. * @param s stream * @param oct_str octet string * @param length string length * @param min minimum length * @return */ boolean per_read_octet_string(STREAM* s, uint8* oct_str, int length, int min) { int i; uint16 mlength; uint8* a_oct_str; per_read_length(s, &mlength); if (mlength + min != length) return false; a_oct_str = s->p; stream_seek(s, length); for (i = 0; i < length; i++) { if (a_oct_str[i] != oct_str[i]) return false; } return true; } /** * Write PER OCTET_STRING * @param s stream * @param oct_str octet string * @param length string length * @param min minimum string length */ void per_write_octet_string(STREAM* s, uint8* oct_str, int length, int min) { int i; int mlength; mlength = (length - min >= 0) ? length - min : min; per_write_length(s, mlength); for (i = 0; i < length; i++) stream_write_uint8(s, oct_str[i]); } /** * Read PER NumericString. * @param s stream * @param num_str numeric string * @param length string length * @param min minimum string length */ boolean per_read_numeric_string(STREAM* s, int min) { int i; int length; uint16 mlength; per_read_length(s, &mlength); length = mlength + min; for (i = 0; i < length; i += 2) { stream_seek(s, 1); } return true; } /** * Write PER NumericString. * @param s stream * @param num_str numeric string * @param length string length * @param min minimum string length */ void per_write_numeric_string(STREAM* s, uint8* num_str, int length, int min) { int i; int mlength; uint8 num, c1, c2; mlength = (length - min >= 0) ? length - min : min; per_write_length(s, mlength); for (i = 0; i < length; i += 2) { c1 = num_str[i]; c2 = ((i + 1) < length) ? num_str[i + 1] : 0x30; c1 = (c1 - 0x30) % 10; c2 = (c2 - 0x30) % 10; num = (c1 << 4) | c2; stream_write_uint8(s, num); /* string */ } } FreeRDP-1.0.2/libfreerdp-core/per.h000066400000000000000000000041011207112532300167340ustar00rootroot00000000000000/** * FreeRDP: A Remote Desktop Protocol Client * ASN.1 Packed Encoding Rules (BER) * * Copyright 2011 Marc-Andre Moreau * * 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. */ #ifndef __PER_H #define __PER_H #include boolean per_read_length(STREAM* s, uint16* length); void per_write_length(STREAM* s, int length); boolean per_read_choice(STREAM* s, uint8* choice); void per_write_choice(STREAM* s, uint8 choice); boolean per_read_selection(STREAM* s, uint8* selection); void per_write_selection(STREAM* s, uint8 selection); boolean per_read_number_of_sets(STREAM* s, uint8* number); void per_write_number_of_sets(STREAM* s, uint8 number); boolean per_read_padding(STREAM* s, int length); void per_write_padding(STREAM* s, int length); boolean per_read_integer(STREAM* s, uint32* integer); boolean per_read_integer16(STREAM* s, uint16* integer, uint16 min); void per_write_integer(STREAM* s, uint32 integer); void per_write_integer16(STREAM* s, uint16 integer, uint16 min); boolean per_read_enumerated(STREAM* s, uint8* enumerated, uint8 count); void per_write_enumerated(STREAM* s, uint8 enumerated, uint8 count); void per_write_object_identifier(STREAM* s, uint8 oid[6]); boolean per_read_object_identifier(STREAM* s, uint8 oid[6]); boolean per_read_octet_string(STREAM* s, uint8* oct_str, int length, int min); void per_write_octet_string(STREAM* s, uint8* oct_str, int length, int min); boolean per_read_numeric_string(STREAM* s, int min); void per_write_numeric_string(STREAM* s, uint8* num_str, int length, int min); #endif /* __PER_H */ FreeRDP-1.0.2/libfreerdp-core/rdp.c000066400000000000000000000512521207112532300167370ustar00rootroot00000000000000/** * FreeRDP: A Remote Desktop Protocol Client * RDP Core * * Copyright 2011 Marc-Andre Moreau * * 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. */ #include "rdp.h" #include "info.h" #include "per.h" #include "redirection.h" static const char* const DATA_PDU_TYPE_STRINGS[] = { "", "", /* 0x00 - 0x01 */ "Update", /* 0x02 */ "", "", "", "", "", "", "", "", /* 0x03 - 0x0A */ "", "", "", "", "", "", "", "", "", /* 0x0B - 0x13 */ "Control", /* 0x14 */ "", "", "", "", "", "", /* 0x15 - 0x1A */ "Pointer", /* 0x1B */ "Input", /* 0x1C */ "", "", /* 0x1D - 0x1E */ "Synchronize", /* 0x1F */ "", /* 0x20 */ "Refresh Rect", /* 0x21 */ "Play Sound", /* 0x22 */ "Suppress Output", /* 0x23 */ "Shutdown Request", /* 0x24 */ "Shutdown Denied", /* 0x25 */ "Save Session Info", /* 0x26 */ "Font List", /* 0x27 */ "Font Map", /* 0x28 */ "Set Keyboard Indicators", /* 0x29 */ "", /* 0x2A */ "Bitmap Cache Persistent List", /* 0x2B */ "Bitmap Cache Error", /* 0x2C */ "Set Keyboard IME Status", /* 0x2D */ "Offscreen Cache Error", /* 0x2E */ "Set Error Info", /* 0x2F */ "Draw Nine Grid Error", /* 0x30 */ "Draw GDI+ Error", /* 0x31 */ "ARC Status", /* 0x32 */ "", "", "", /* 0x33 - 0x35 */ "Status Info", /* 0x36 */ "Monitor Layout" /* 0x37 */ "", "", "", /* 0x38 - 0x40 */ "", "", "", "", "", "" /* 0x41 - 0x46 */ }; /** * Read RDP Security Header.\n * @msdn{cc240579} * @param s stream * @param flags security flags */ void rdp_read_security_header(STREAM* s, uint16* flags) { /* Basic Security Header */ stream_read_uint16(s, *flags); /* flags */ stream_seek(s, 2); /* flagsHi (unused) */ } /** * Write RDP Security Header.\n * @msdn{cc240579} * @param s stream * @param flags security flags */ void rdp_write_security_header(STREAM* s, uint16 flags) { /* Basic Security Header */ stream_write_uint16(s, flags); /* flags */ stream_write_uint16(s, 0); /* flagsHi (unused) */ } boolean rdp_read_share_control_header(STREAM* s, uint16* length, uint16* type, uint16* channel_id) { /* Share Control Header */ stream_read_uint16(s, *length); /* totalLength */ if (*length - 2 > stream_get_left(s)) return false; stream_read_uint16(s, *type); /* pduType */ *type &= 0x0F; /* type is in the 4 least significant bits */ if (*length > 4) stream_read_uint16(s, *channel_id); /* pduSource */ else /* Windows XP can send such short DEACTIVATE_ALL PDUs. */ *channel_id = 0; return true; } void rdp_write_share_control_header(STREAM* s, uint16 length, uint16 type, uint16 channel_id) { length -= RDP_PACKET_HEADER_MAX_LENGTH; /* Share Control Header */ stream_write_uint16(s, length); /* totalLength */ stream_write_uint16(s, type | 0x10); /* pduType */ stream_write_uint16(s, channel_id); /* pduSource */ } boolean rdp_read_share_data_header(STREAM* s, uint16* length, uint8* type, uint32* share_id, uint8 *compressed_type, uint16 *compressed_len) { if (stream_get_left(s) < 12) return false; /* Share Data Header */ stream_read_uint32(s, *share_id); /* shareId (4 bytes) */ stream_seek_uint8(s); /* pad1 (1 byte) */ stream_seek_uint8(s); /* streamId (1 byte) */ stream_read_uint16(s, *length); /* uncompressedLength (2 bytes) */ stream_read_uint8(s, *type); /* pduType2, Data PDU Type (1 byte) */ if (*type & 0x80) { stream_read_uint8(s, *compressed_type); /* compressedType (1 byte) */ stream_read_uint16(s, *compressed_len); /* compressedLength (2 bytes) */ } else { stream_seek(s, 3); *compressed_type = 0; *compressed_len = 0; } return true; } void rdp_write_share_data_header(STREAM* s, uint16 length, uint8 type, uint32 share_id) { length -= RDP_PACKET_HEADER_MAX_LENGTH; length -= RDP_SHARE_CONTROL_HEADER_LENGTH; length -= RDP_SHARE_DATA_HEADER_LENGTH; /* Share Data Header */ stream_write_uint32(s, share_id); /* shareId (4 bytes) */ stream_write_uint8(s, 0); /* pad1 (1 byte) */ stream_write_uint8(s, STREAM_LOW); /* streamId (1 byte) */ stream_write_uint16(s, length); /* uncompressedLength (2 bytes) */ stream_write_uint8(s, type); /* pduType2, Data PDU Type (1 byte) */ stream_write_uint8(s, 0); /* compressedType (1 byte) */ stream_write_uint16(s, 0); /* compressedLength (2 bytes) */ } static int rdp_security_stream_init(rdpRdp* rdp, STREAM* s) { if (rdp->do_crypt) { stream_seek(s, 12); if (rdp->settings->encryption_method == ENCRYPTION_METHOD_FIPS) stream_seek(s, 4); rdp->sec_flags |= SEC_ENCRYPT; if (rdp->do_secure_checksum) rdp->sec_flags |= SEC_SECURE_CHECKSUM; } else if (rdp->sec_flags != 0) { stream_seek(s, 4); } return 0; } /** * Initialize an RDP packet stream.\n * @param rdp rdp module * @return */ STREAM* rdp_send_stream_init(rdpRdp* rdp) { STREAM* s; s = transport_send_stream_init(rdp->transport, 2048); stream_seek(s, RDP_PACKET_HEADER_MAX_LENGTH); rdp_security_stream_init(rdp, s); return s; } STREAM* rdp_pdu_init(rdpRdp* rdp) { STREAM* s; s = transport_send_stream_init(rdp->transport, 2048); stream_seek(s, RDP_PACKET_HEADER_MAX_LENGTH); rdp_security_stream_init(rdp, s); stream_seek(s, RDP_SHARE_CONTROL_HEADER_LENGTH); return s; } STREAM* rdp_data_pdu_init(rdpRdp* rdp) { STREAM* s; s = transport_send_stream_init(rdp->transport, 2048); stream_seek(s, RDP_PACKET_HEADER_MAX_LENGTH); rdp_security_stream_init(rdp, s); stream_seek(s, RDP_SHARE_CONTROL_HEADER_LENGTH); stream_seek(s, RDP_SHARE_DATA_HEADER_LENGTH); return s; } /** * Read an RDP packet header.\n * @param rdp rdp module * @param s stream * @param length RDP packet length * @param channel_id channel id */ boolean rdp_read_header(rdpRdp* rdp, STREAM* s, uint16* length, uint16* channel_id) { uint16 initiator; enum DomainMCSPDU MCSPDU; MCSPDU = (rdp->settings->server_mode) ? DomainMCSPDU_SendDataRequest : DomainMCSPDU_SendDataIndication; mcs_read_domain_mcspdu_header(s, &MCSPDU, length); if (*length - 8 > stream_get_left(s)) return false; if (MCSPDU == DomainMCSPDU_DisconnectProviderUltimatum) { uint8 reason; (void) per_read_enumerated(s, &reason, 0); rdp->disconnect = true; return true; } per_read_integer16(s, &initiator, MCS_BASE_CHANNEL_ID); /* initiator (UserId) */ per_read_integer16(s, channel_id, 0); /* channelId */ stream_seek(s, 1); /* dataPriority + Segmentation (0x70) */ per_read_length(s, length); /* userData (OCTET_STRING) */ if (*length > stream_get_left(s)) return false; return true; } /** * Write an RDP packet header.\n * @param rdp rdp module * @param s stream * @param length RDP packet length * @param channel_id channel id */ void rdp_write_header(rdpRdp* rdp, STREAM* s, uint16 length, uint16 channel_id) { int body_length; enum DomainMCSPDU MCSPDU; MCSPDU = (rdp->settings->server_mode) ? DomainMCSPDU_SendDataIndication : DomainMCSPDU_SendDataRequest; if ((rdp->sec_flags & SEC_ENCRYPT) && (rdp->settings->encryption_method == ENCRYPTION_METHOD_FIPS)) { int pad; body_length = length - RDP_PACKET_HEADER_MAX_LENGTH - 16; pad = 8 - (body_length % 8); if (pad != 8) length += pad; } mcs_write_domain_mcspdu_header(s, MCSPDU, length, 0); per_write_integer16(s, rdp->mcs->user_id, MCS_BASE_CHANNEL_ID); /* initiator */ per_write_integer16(s, channel_id, 0); /* channelId */ stream_write_uint8(s, 0x70); /* dataPriority + segmentation */ /* * We always encode length in two bytes, eventhough we could use * only one byte if length <= 0x7F. It is just easier that way, * because we can leave room for fixed-length header, store all * the data first and then store the header. */ length = (length - RDP_PACKET_HEADER_MAX_LENGTH) | 0x8000; stream_write_uint16_be(s, length); /* userData (OCTET_STRING) */ } static uint32 rdp_security_stream_out(rdpRdp* rdp, STREAM* s, int length) { uint8* data; uint32 sec_flags; uint32 pad = 0; sec_flags = rdp->sec_flags; if (sec_flags != 0) { rdp_write_security_header(s, sec_flags); if (sec_flags & SEC_ENCRYPT) { if (rdp->settings->encryption_method == ENCRYPTION_METHOD_FIPS) { data = s->p + 12; length = length - (data - s->data); stream_write_uint16(s, 0x10); /* length */ stream_write_uint8(s, 0x1); /* TSFIPS_VERSION 1*/ /* handle padding */ pad = 8 - (length % 8); if (pad == 8) pad = 0; if (pad) memset(data+length, 0, pad); stream_write_uint8(s, pad); security_hmac_signature(data, length, s->p, rdp); stream_seek(s, 8); security_fips_encrypt(data, length + pad, rdp); } else { data = s->p + 8; length = length - (data - s->data); if (sec_flags & SEC_SECURE_CHECKSUM) security_salted_mac_signature(rdp, data, length, true, s->p); else security_mac_signature(rdp, data, length, s->p); stream_seek(s, 8); security_encrypt(s->p, length, rdp); } } rdp->sec_flags = 0; } return pad; } static uint32 rdp_get_sec_bytes(rdpRdp* rdp) { uint32 sec_bytes; if (rdp->sec_flags & SEC_ENCRYPT) { sec_bytes = 12; if (rdp->settings->encryption_method == ENCRYPTION_METHOD_FIPS) sec_bytes += 4; } else if (rdp->sec_flags != 0) { sec_bytes = 4; } else { sec_bytes = 0; } return sec_bytes; } /** * Send an RDP packet.\n * @param rdp RDP module * @param s stream * @param channel_id channel id */ boolean rdp_send(rdpRdp* rdp, STREAM* s, uint16 channel_id) { uint16 length; uint32 sec_bytes; uint8* sec_hold; length = stream_get_length(s); stream_set_pos(s, 0); rdp_write_header(rdp, s, length, channel_id); sec_bytes = rdp_get_sec_bytes(rdp); sec_hold = s->p; stream_seek(s, sec_bytes); s->p = sec_hold; length += rdp_security_stream_out(rdp, s, length); stream_set_pos(s, length); if (transport_write(rdp->transport, s) < 0) return false; return true; } boolean rdp_send_pdu(rdpRdp* rdp, STREAM* s, uint16 type, uint16 channel_id) { uint16 length; uint32 sec_bytes; uint8* sec_hold; length = stream_get_length(s); stream_set_pos(s, 0); rdp_write_header(rdp, s, length, MCS_GLOBAL_CHANNEL_ID); sec_bytes = rdp_get_sec_bytes(rdp); sec_hold = s->p; stream_seek(s, sec_bytes); rdp_write_share_control_header(s, length - sec_bytes, type, channel_id); s->p = sec_hold; length += rdp_security_stream_out(rdp, s, length); stream_set_pos(s, length); if (transport_write(rdp->transport, s) < 0) return false; return true; } boolean rdp_send_data_pdu(rdpRdp* rdp, STREAM* s, uint8 type, uint16 channel_id) { uint16 length; uint32 sec_bytes; uint8* sec_hold; length = stream_get_length(s); stream_set_pos(s, 0); rdp_write_header(rdp, s, length, MCS_GLOBAL_CHANNEL_ID); sec_bytes = rdp_get_sec_bytes(rdp); sec_hold = s->p; stream_seek(s, sec_bytes); rdp_write_share_control_header(s, length - sec_bytes, PDU_TYPE_DATA, channel_id); rdp_write_share_data_header(s, length - sec_bytes, type, rdp->settings->share_id); s->p = sec_hold; length += rdp_security_stream_out(rdp, s, length); stream_set_pos(s, length); if (transport_write(rdp->transport, s) < 0) return false; return true; } void rdp_recv_set_error_info_data_pdu(rdpRdp* rdp, STREAM* s) { stream_read_uint32(s, rdp->errorInfo); /* errorInfo (4 bytes) */ if (rdp->errorInfo != ERRINFO_SUCCESS) rdp_print_errinfo(rdp->errorInfo); } void rdp_recv_data_pdu(rdpRdp* rdp, STREAM* s) { uint8 type; uint16 length; uint32 share_id; uint8 compressed_type; uint16 compressed_len; rdp_read_share_data_header(s, &length, &type, &share_id, &compressed_type, &compressed_len); #ifdef WITH_DEBUG_RDP if (type != DATA_PDU_TYPE_UPDATE) printf("recv %s Data PDU (0x%02X), length:%d\n", DATA_PDU_TYPE_STRINGS[type], type, length); #endif switch (type) { case DATA_PDU_TYPE_UPDATE: update_recv(rdp->update, s); break; case DATA_PDU_TYPE_CONTROL: rdp_recv_server_control_pdu(rdp, s); break; case DATA_PDU_TYPE_POINTER: update_recv_pointer(rdp->update, s); break; case DATA_PDU_TYPE_INPUT: break; case DATA_PDU_TYPE_SYNCHRONIZE: rdp_recv_synchronize_pdu(rdp, s); break; case DATA_PDU_TYPE_REFRESH_RECT: break; case DATA_PDU_TYPE_PLAY_SOUND: update_recv_play_sound(rdp->update, s); break; case DATA_PDU_TYPE_SUPPRESS_OUTPUT: break; case DATA_PDU_TYPE_SHUTDOWN_REQUEST: break; case DATA_PDU_TYPE_SHUTDOWN_DENIED: break; case DATA_PDU_TYPE_SAVE_SESSION_INFO: rdp_recv_save_session_info(rdp, s); break; case DATA_PDU_TYPE_FONT_LIST: break; case DATA_PDU_TYPE_FONT_MAP: rdp_recv_font_map_pdu(rdp, s); break; case DATA_PDU_TYPE_SET_KEYBOARD_INDICATORS: break; case DATA_PDU_TYPE_BITMAP_CACHE_PERSISTENT_LIST: break; case DATA_PDU_TYPE_BITMAP_CACHE_ERROR: break; case DATA_PDU_TYPE_SET_KEYBOARD_IME_STATUS: break; case DATA_PDU_TYPE_OFFSCREEN_CACHE_ERROR: break; case DATA_PDU_TYPE_SET_ERROR_INFO: rdp_recv_set_error_info_data_pdu(rdp, s); break; case DATA_PDU_TYPE_DRAW_NINEGRID_ERROR: break; case DATA_PDU_TYPE_DRAW_GDIPLUS_ERROR: break; case DATA_PDU_TYPE_ARC_STATUS: break; case DATA_PDU_TYPE_STATUS_INFO: break; case DATA_PDU_TYPE_MONITOR_LAYOUT: break; default: break; } } boolean rdp_recv_out_of_sequence_pdu(rdpRdp* rdp, STREAM* s) { uint16 type; uint16 length; uint16 channelId; rdp_read_share_control_header(s, &length, &type, &channelId); if (type == PDU_TYPE_DATA) { rdp_recv_data_pdu(rdp, s); return true; } else if (type == PDU_TYPE_SERVER_REDIRECTION) { rdp_recv_enhanced_security_redirection_packet(rdp, s); return true; } else { return false; } } /** * Decrypt an RDP packet.\n * @param rdp RDP module * @param s stream * @param length int */ boolean rdp_decrypt(rdpRdp* rdp, STREAM* s, int length, uint16 securityFlags) { uint8 cmac[8], wmac[8]; if (rdp->settings->encryption_method == ENCRYPTION_METHOD_FIPS) { uint16 len; uint8 version, pad; uint8 *sig; stream_read_uint16(s, len); /* 0x10 */ stream_read_uint8(s, version); /* 0x1 */ stream_read_uint8(s, pad); sig = s->p; stream_seek(s, 8); /* signature */ length -= 12; if (!security_fips_decrypt(s->p, length, rdp)) { printf("FATAL: cannot decrypt\n"); return false; /* TODO */ } if (!security_fips_check_signature(s->p, length - pad, sig, rdp)) { printf("FATAL: invalid packet signature\n"); return false; /* TODO */ } /* is this what needs adjusting? */ s->size -= pad; return true; } stream_read(s, wmac, sizeof(wmac)); length -= sizeof(wmac); security_decrypt(s->p, length, rdp); if (securityFlags & SEC_SECURE_CHECKSUM) security_salted_mac_signature(rdp, s->p, length, false, cmac); else security_mac_signature(rdp, s->p, length, cmac); if (memcmp(wmac, cmac, sizeof(wmac)) != 0) { printf("WARNING: invalid packet signature\n"); /* * Because Standard RDP Security is totally broken, * and cannot protect against MITM, don't treat signature * verification failure as critical. This at least enables * us to work with broken RDP clients and servers that * generate invalid signatures. */ //return false; } return true; } /** * Process an RDP packet.\n * @param rdp RDP module * @param s stream */ static boolean rdp_recv_tpkt_pdu(rdpRdp* rdp, STREAM* s) { uint16 length; uint16 pduType; uint16 pduLength; uint16 pduSource; uint16 channelId; uint16 securityFlags; if (!rdp_read_header(rdp, s, &length, &channelId)) { printf("Incorrect RDP header.\n"); return false; } if (rdp->settings->encryption) { rdp_read_security_header(s, &securityFlags); if (securityFlags & (SEC_ENCRYPT|SEC_REDIRECTION_PKT)) { if (!rdp_decrypt(rdp, s, length - 4, securityFlags)) { printf("rdp_decrypt failed\n"); return false; } } if (securityFlags & SEC_REDIRECTION_PKT) { /* * [MS-RDPBCGR] 2.2.13.2.1 * - no share control header, nor the 2 byte pad */ s->p -= 2; rdp_recv_enhanced_security_redirection_packet(rdp, s); return true; } } if (channelId != MCS_GLOBAL_CHANNEL_ID) { freerdp_channel_process(rdp->instance, s, channelId); } else { rdp_read_share_control_header(s, &pduLength, &pduType, &pduSource); rdp->settings->pdu_source = pduSource; switch (pduType) { case PDU_TYPE_DATA: rdp_recv_data_pdu(rdp, s); break; case PDU_TYPE_DEACTIVATE_ALL: if (!rdp_recv_deactivate_all(rdp, s)) return false; break; case PDU_TYPE_SERVER_REDIRECTION: rdp_recv_enhanced_security_redirection_packet(rdp, s); break; default: printf("incorrect PDU type: 0x%04X\n", pduType); break; } } return true; } static boolean rdp_recv_fastpath_pdu(rdpRdp* rdp, STREAM* s) { uint16 length; rdpFastPath* fastpath; fastpath = rdp->fastpath; length = fastpath_read_header_rdp(fastpath, s); if (length == 0 || length > stream_get_left(s)) { printf("incorrect FastPath PDU header length %d\n", length); return false; } if (fastpath->encryptionFlags & FASTPATH_OUTPUT_ENCRYPTED) { rdp_decrypt(rdp, s, length, (fastpath->encryptionFlags & FASTPATH_OUTPUT_SECURE_CHECKSUM) ? SEC_SECURE_CHECKSUM : 0); } return fastpath_recv_updates(rdp->fastpath, s); } static boolean rdp_recv_pdu(rdpRdp* rdp, STREAM* s) { if (tpkt_verify_header(s)) return rdp_recv_tpkt_pdu(rdp, s); else return rdp_recv_fastpath_pdu(rdp, s); } /** * Receive an RDP packet.\n * @param rdp RDP module */ void rdp_recv(rdpRdp* rdp) { STREAM* s; s = transport_recv_stream_init(rdp->transport, 4096); transport_read(rdp->transport, s); rdp_recv_pdu(rdp, s); } static boolean rdp_recv_callback(rdpTransport* transport, STREAM* s, void* extra) { rdpRdp* rdp = (rdpRdp*) extra; switch (rdp->state) { case CONNECTION_STATE_NEGO: if (!rdp_client_connect_mcs_connect_response(rdp, s)) return false; break; case CONNECTION_STATE_MCS_ATTACH_USER: if (!rdp_client_connect_mcs_attach_user_confirm(rdp, s)) return false; break; case CONNECTION_STATE_MCS_CHANNEL_JOIN: if (!rdp_client_connect_mcs_channel_join_confirm(rdp, s)) return false; break; case CONNECTION_STATE_LICENSE: if (!rdp_client_connect_license(rdp, s)) return false; break; case CONNECTION_STATE_CAPABILITY: if (!rdp_client_connect_demand_active(rdp, s)) { printf("rdp_client_connect_demand_active failed\n"); return false; } break; case CONNECTION_STATE_FINALIZATION: if (!rdp_recv_pdu(rdp, s)) return false; if (rdp->finalize_sc_pdus == FINALIZE_SC_COMPLETE) rdp->state = CONNECTION_STATE_ACTIVE; break; case CONNECTION_STATE_ACTIVE: if (!rdp_recv_pdu(rdp, s)) return false; break; default: printf("Invalid state %d\n", rdp->state); return false; } return true; } int rdp_send_channel_data(rdpRdp* rdp, int channel_id, uint8* data, int size) { return freerdp_channel_send(rdp, channel_id, data, size); } /** * Set non-blocking mode information. * @param rdp RDP module * @param blocking blocking mode */ void rdp_set_blocking_mode(rdpRdp* rdp, boolean blocking) { rdp->transport->recv_callback = rdp_recv_callback; rdp->transport->recv_extra = rdp; transport_set_blocking_mode(rdp->transport, blocking); } int rdp_check_fds(rdpRdp* rdp) { return transport_check_fds(&(rdp->transport)); } /** * Instantiate new RDP module. * @return new RDP module */ rdpRdp* rdp_new(freerdp* instance) { rdpRdp* rdp; rdp = (rdpRdp*) xzalloc(sizeof(rdpRdp)); if (rdp != NULL) { rdp->instance = instance; rdp->settings = settings_new((void*) instance); if (instance != NULL) instance->settings = rdp->settings; rdp->transport = transport_new(rdp->settings); rdp->license = license_new(rdp); rdp->input = input_new(rdp); rdp->update = update_new(rdp); rdp->fastpath = fastpath_new(rdp); rdp->nego = nego_new(rdp->transport); rdp->mcs = mcs_new(rdp->transport); rdp->redirection = redirection_new(); rdp->mppc = mppc_new(rdp); } return rdp; } /** * Free RDP module. * @param rdp RDP module to be freed */ void rdp_free(rdpRdp* rdp) { if (rdp != NULL) { crypto_rc4_free(rdp->rc4_decrypt_key); crypto_rc4_free(rdp->rc4_encrypt_key); crypto_des3_free(rdp->fips_encrypt); crypto_des3_free(rdp->fips_decrypt); crypto_hmac_free(rdp->fips_hmac); extension_free(rdp->extension); settings_free(rdp->settings); transport_free(rdp->transport); license_free(rdp->license); input_free(rdp->input); update_free(rdp->update); fastpath_free(rdp->fastpath); nego_free(rdp->nego); mcs_free(rdp->mcs); redirection_free(rdp->redirection); mppc_free(rdp); xfree(rdp); } } FreeRDP-1.0.2/libfreerdp-core/rdp.h000066400000000000000000000150511207112532300167410ustar00rootroot00000000000000/** * FreeRDP: A Remote Desktop Protocol Client * RDP Core * * Copyright 2011 Marc-Andre Moreau * * 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. */ #ifndef __RDP_H #define __RDP_H #include "mcs.h" #include "tpkt.h" #include "fastpath.h" #include "tpdu.h" #include "nego.h" #include "input.h" #include "update.h" #include "license.h" #include "errinfo.h" #include "extension.h" #include "security.h" #include "transport.h" #include "connection.h" #include "redirection.h" #include "capabilities.h" #include "channel.h" #include "mppc.h" #include #include #include #include /* Security Header Flags */ #define SEC_EXCHANGE_PKT 0x0001 #define SEC_ENCRYPT 0x0008 #define SEC_RESET_SEQNO 0x0010 #define SEC_IGNORE_SEQNO 0x0020 #define SEC_INFO_PKT 0x0040 #define SEC_LICENSE_PKT 0x0080 #define SEC_LICENSE_ENCRYPT_CS 0x0200 #define SEC_LICENSE_ENCRYPT_SC 0x0200 #define SEC_REDIRECTION_PKT 0x0400 #define SEC_SECURE_CHECKSUM 0x0800 #define SEC_FLAGSHI_VALID 0x8000 #define SEC_PKT_CS_MASK (SEC_EXCHANGE_PKT | SEC_INFO_PKT) #define SEC_PKT_SC_MASK (SEC_LICENSE_PKT | SEC_REDIRECTION_PKT) #define SEC_PKT_MASK (SEC_PKT_CS_MASK | SEC_PKT_SC_MASK) #define RDP_SECURITY_HEADER_LENGTH 4 #define RDP_SHARE_CONTROL_HEADER_LENGTH 6 #define RDP_SHARE_DATA_HEADER_LENGTH 12 #define RDP_PACKET_HEADER_MAX_LENGTH (TPDU_DATA_LENGTH + MCS_SEND_DATA_HEADER_MAX_LENGTH) #define PDU_TYPE_DEMAND_ACTIVE 0x1 #define PDU_TYPE_CONFIRM_ACTIVE 0x3 #define PDU_TYPE_DEACTIVATE_ALL 0x6 #define PDU_TYPE_DATA 0x7 #define PDU_TYPE_SERVER_REDIRECTION 0xA #define FINALIZE_SC_SYNCHRONIZE_PDU 0x01 #define FINALIZE_SC_CONTROL_COOPERATE_PDU 0x02 #define FINALIZE_SC_CONTROL_GRANTED_PDU 0x04 #define FINALIZE_SC_FONT_MAP_PDU 0x08 #define FINALIZE_SC_COMPLETE 0x0F /* Data PDU Types */ #define DATA_PDU_TYPE_UPDATE 0x02 #define DATA_PDU_TYPE_CONTROL 0x14 #define DATA_PDU_TYPE_POINTER 0x1B #define DATA_PDU_TYPE_INPUT 0x1C #define DATA_PDU_TYPE_SYNCHRONIZE 0x1F #define DATA_PDU_TYPE_REFRESH_RECT 0x21 #define DATA_PDU_TYPE_PLAY_SOUND 0x22 #define DATA_PDU_TYPE_SUPPRESS_OUTPUT 0x23 #define DATA_PDU_TYPE_SHUTDOWN_REQUEST 0x24 #define DATA_PDU_TYPE_SHUTDOWN_DENIED 0x25 #define DATA_PDU_TYPE_SAVE_SESSION_INFO 0x26 #define DATA_PDU_TYPE_FONT_LIST 0x27 #define DATA_PDU_TYPE_FONT_MAP 0x28 #define DATA_PDU_TYPE_SET_KEYBOARD_INDICATORS 0x29 #define DATA_PDU_TYPE_BITMAP_CACHE_PERSISTENT_LIST 0x2B #define DATA_PDU_TYPE_BITMAP_CACHE_ERROR 0x2C #define DATA_PDU_TYPE_SET_KEYBOARD_IME_STATUS 0x2D #define DATA_PDU_TYPE_OFFSCREEN_CACHE_ERROR 0x2E #define DATA_PDU_TYPE_SET_ERROR_INFO 0x2F #define DATA_PDU_TYPE_DRAW_NINEGRID_ERROR 0x30 #define DATA_PDU_TYPE_DRAW_GDIPLUS_ERROR 0x31 #define DATA_PDU_TYPE_ARC_STATUS 0x32 #define DATA_PDU_TYPE_STATUS_INFO 0x36 #define DATA_PDU_TYPE_MONITOR_LAYOUT 0x37 /* Compression Types */ #define PACKET_COMPRESSED 0x20 #define PACKET_AT_FRONT 0x40 #define PACKET_FLUSHED 0x80 #define PACKET_COMPR_TYPE_8K 0x00 #define PACKET_COMPR_TYPE_64K 0x01 #define PACKET_COMPR_TYPE_RDP6 0x02 #define PACKET_COMPR_TYPE_RDP61 0x03 #define CompressionTypeMask 0x0F /* Stream Identifiers */ #define STREAM_UNDEFINED 0x00 #define STREAM_LOW 0x01 #define STREAM_MED 0x02 #define STREAM_HI 0x04 struct rdp_rdp { int state; freerdp* instance; struct rdp_mcs* mcs; struct rdp_nego* nego; struct rdp_input* input; struct rdp_update* update; struct rdp_fastpath* fastpath; struct rdp_license* license; struct rdp_redirection* redirection; struct rdp_settings* settings; struct rdp_transport* transport; struct rdp_extension* extension; struct rdp_mppc* mppc; struct crypto_rc4_struct* rc4_decrypt_key; int decrypt_use_count; int decrypt_checksum_use_count; struct crypto_rc4_struct* rc4_encrypt_key; int encrypt_use_count; int encrypt_checksum_use_count; struct crypto_des3_struct* fips_encrypt; struct crypto_des3_struct* fips_decrypt; struct crypto_hmac_struct* fips_hmac; uint32 sec_flags; boolean do_crypt; boolean do_secure_checksum; uint8 sign_key[16]; uint8 decrypt_key[16]; uint8 encrypt_key[16]; uint8 decrypt_update_key[16]; uint8 encrypt_update_key[16]; int rc4_key_len; uint8 fips_sign_key[20]; uint8 fips_encrypt_key[24]; uint8 fips_decrypt_key[24]; uint32 errorInfo; uint32 finalize_sc_pdus; boolean disconnect; }; void rdp_read_security_header(STREAM* s, uint16* flags); void rdp_write_security_header(STREAM* s, uint16 flags); boolean rdp_read_share_control_header(STREAM* s, uint16* length, uint16* type, uint16* channel_id); void rdp_write_share_control_header(STREAM* s, uint16 length, uint16 type, uint16 channel_id); boolean rdp_read_share_data_header(STREAM* s, uint16* length, uint8* type, uint32* share_id, uint8 *compressed_type, uint16 *compressed_len); void rdp_write_share_data_header(STREAM* s, uint16 length, uint8 type, uint32 share_id); STREAM* rdp_send_stream_init(rdpRdp* rdp); boolean rdp_read_header(rdpRdp* rdp, STREAM* s, uint16* length, uint16* channel_id); void rdp_write_header(rdpRdp* rdp, STREAM* s, uint16 length, uint16 channel_id); STREAM* rdp_pdu_init(rdpRdp* rdp); boolean rdp_send_pdu(rdpRdp* rdp, STREAM* s, uint16 type, uint16 channel_id); STREAM* rdp_data_pdu_init(rdpRdp* rdp); boolean rdp_send_data_pdu(rdpRdp* rdp, STREAM* s, uint8 type, uint16 channel_id); void rdp_recv_data_pdu(rdpRdp* rdp, STREAM* s); boolean rdp_send(rdpRdp* rdp, STREAM* s, uint16 channel_id); void rdp_recv(rdpRdp* rdp); int rdp_send_channel_data(rdpRdp* rdp, int channel_id, uint8* data, int size); boolean rdp_recv_out_of_sequence_pdu(rdpRdp* rdp, STREAM* s); void rdp_set_blocking_mode(rdpRdp* rdp, boolean blocking); int rdp_check_fds(rdpRdp* rdp); rdpRdp* rdp_new(freerdp* instance); void rdp_free(rdpRdp* rdp); #ifdef WITH_DEBUG_RDP #define DEBUG_RDP(fmt, ...) DEBUG_CLASS(RDP, fmt, ## __VA_ARGS__) #else #define DEBUG_RDP(fmt, ...) DEBUG_NULL(fmt, ## __VA_ARGS__) #endif boolean rdp_decrypt(rdpRdp* rdp, STREAM* s, int length, uint16 securityFlags); #endif /* __RDP_H */ FreeRDP-1.0.2/libfreerdp-core/redirection.c000066400000000000000000000151361207112532300204620ustar00rootroot00000000000000/** * FreeRDP: A Remote Desktop Protocol Client * RDP Server Redirection * * Copyright 2011 Marc-Andre Moreau * * 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. */ #include "connection.h" #include "redirection.h" void rdp_print_redirection_flags(uint32 flags) { printf("redirectionFlags = {\n"); if (flags & LB_TARGET_NET_ADDRESS) printf("\tLB_TARGET_NET_ADDRESS\n"); if (flags & LB_LOAD_BALANCE_INFO) printf("\tLB_LOAD_BALANCE_INFO\n"); if (flags & LB_USERNAME) printf("\tLB_USERNAME\n"); if (flags & LB_DOMAIN) printf("\tLB_DOMAIN\n"); if (flags & LB_PASSWORD) printf("\tLB_PASSWORD\n"); if (flags & LB_DONTSTOREUSERNAME) printf("\tLB_DONTSTOREUSERNAME\n"); if (flags & LB_SMARTCARD_LOGON) printf("\tLB_SMARTCARD_LOGON\n"); if (flags & LB_NOREDIRECT) printf("\tLB_NOREDIRECT\n"); if (flags & LB_TARGET_FQDN) printf("\tLB_TARGET_FQDN\n"); if (flags & LB_TARGET_NETBIOS_NAME) printf("\tLB_TARGET_NETBIOS_NAME\n"); if (flags & LB_TARGET_NET_ADDRESSES) printf("\tLB_TARGET_NET_ADDRESSES\n"); if (flags & LB_CLIENT_TSV_URL) printf("\tLB_CLIENT_TSV_URL\n"); if (flags & LB_SERVER_TSV_CAPABLE) printf("\tLB_SERVER_TSV_CAPABLE\n"); printf("}\n"); } boolean rdp_recv_server_redirection_pdu(rdpRdp* rdp, STREAM* s) { uint16 flags; uint16 length; rdpRedirection* redirection = rdp->redirection; stream_read_uint16(s, flags); /* flags (2 bytes) */ stream_read_uint16(s, length); /* length (2 bytes) */ stream_read_uint32(s, redirection->sessionID); /* sessionID (4 bytes) */ stream_read_uint32(s, redirection->flags); /* redirFlags (4 bytes) */ DEBUG_REDIR("flags: 0x%04X, length:%d, sessionID:0x%08X", flags, length, redirection->sessionID); #ifdef WITH_DEBUG_REDIR rdp_print_redirection_flags(redirection->flags); #endif if (redirection->flags & LB_TARGET_NET_ADDRESS) { freerdp_string_read_length32(s, &redirection->targetNetAddress, rdp->settings->uniconv); DEBUG_REDIR("targetNetAddress: %s", redirection->targetNetAddress.ascii); } if (redirection->flags & LB_LOAD_BALANCE_INFO) { uint32 loadBalanceInfoLength; stream_read_uint32(s, loadBalanceInfoLength); freerdp_blob_alloc(&redirection->loadBalanceInfo, loadBalanceInfoLength); stream_read(s, redirection->loadBalanceInfo.data, loadBalanceInfoLength); #ifdef WITH_DEBUG_REDIR DEBUG_REDIR("loadBalanceInfo:"); freerdp_hexdump(redirection->loadBalanceInfo.data, redirection->loadBalanceInfo.length); #endif } if (redirection->flags & LB_USERNAME) { freerdp_string_read_length32(s, &redirection->username, rdp->settings->uniconv); DEBUG_REDIR("username: %s", redirection->username.ascii); } if (redirection->flags & LB_DOMAIN) { freerdp_string_read_length32(s, &redirection->domain, rdp->settings->uniconv); DEBUG_REDIR("domain: %s", redirection->domain.ascii); } if (redirection->flags & LB_PASSWORD) { uint32 passwordLength; stream_read_uint32(s, passwordLength); /* Note: length (hopefully) includes double zero termination */ freerdp_blob_alloc(&redirection->password_cookie, passwordLength); stream_read(s, redirection->password_cookie.data, passwordLength); #ifdef WITH_DEBUG_REDIR DEBUG_REDIR("password_cookie:"); freerdp_hexdump(redirection->password_cookie.data, redirection->password_cookie.length); #endif } if (redirection->flags & LB_TARGET_FQDN) { freerdp_string_read_length32(s, &redirection->targetFQDN, rdp->settings->uniconv); DEBUG_REDIR("targetFQDN: %s", redirection->targetFQDN.ascii); } if (redirection->flags & LB_TARGET_NETBIOS_NAME) { freerdp_string_read_length32(s, &redirection->targetNetBiosName, rdp->settings->uniconv); DEBUG_REDIR("targetNetBiosName: %s", redirection->targetNetBiosName.ascii); } if (redirection->flags & LB_CLIENT_TSV_URL) { freerdp_string_read_length32(s, &redirection->tsvUrl, rdp->settings->uniconv); DEBUG_REDIR("tsvUrl: %s", redirection->tsvUrl.ascii); } if (redirection->flags & LB_TARGET_NET_ADDRESSES) { int i; uint32 count; uint32 targetNetAddressesLength; stream_read_uint32(s, targetNetAddressesLength); stream_read_uint32(s, redirection->targetNetAddressesCount); count = redirection->targetNetAddressesCount; redirection->targetNetAddresses = (rdpString*) xzalloc(count * sizeof(rdpString)); for (i = 0; i < (int) count; i++) { freerdp_string_read_length32(s, &redirection->targetNetAddresses[i], rdp->settings->uniconv); DEBUG_REDIR("targetNetAddresses: %s", (&redirection->targetNetAddresses[i])->ascii); } } stream_seek(s, 8); /* pad (8 bytes) */ if (redirection->flags & LB_NOREDIRECT) return true; else return rdp_client_redirect(rdp); } boolean rdp_recv_redirection_packet(rdpRdp* rdp, STREAM* s) { rdp_recv_server_redirection_pdu(rdp, s); return true; } boolean rdp_recv_enhanced_security_redirection_packet(rdpRdp* rdp, STREAM* s) { stream_seek_uint16(s); /* pad2Octets (2 bytes) */ rdp_recv_server_redirection_pdu(rdp, s); stream_seek_uint8(s); /* pad2Octets (1 byte) */ return true; } rdpRedirection* redirection_new() { rdpRedirection* redirection; redirection = (rdpRedirection*) xzalloc(sizeof(rdpRedirection)); if (redirection != NULL) { } return redirection; } void redirection_free(rdpRedirection* redirection) { if (redirection != NULL) { //these four have already been freed in settings_free() and freerdp_string_free() checks for NULL redirection->username.ascii = NULL; redirection->domain.ascii = NULL; redirection->targetNetAddress.ascii = NULL; redirection->targetNetBiosName.ascii = NULL; freerdp_string_free(&redirection->tsvUrl); freerdp_string_free(&redirection->username); freerdp_string_free(&redirection->domain); freerdp_blob_free(&redirection->password_cookie); freerdp_string_free(&redirection->targetFQDN); freerdp_string_free(&redirection->targetNetBiosName); freerdp_string_free(&redirection->targetNetAddress); freerdp_blob_free(&redirection->loadBalanceInfo); if (redirection->targetNetAddresses != NULL) { int i; for (i = 0; i < (int) redirection->targetNetAddressesCount; i++) freerdp_string_free(&redirection->targetNetAddresses[i]); xfree(redirection->targetNetAddresses); } xfree(redirection); } } FreeRDP-1.0.2/libfreerdp-core/redirection.h000066400000000000000000000043171207112532300204660ustar00rootroot00000000000000/** * FreeRDP: A Remote Desktop Protocol Client * RDP Server Redirection * * Copyright 2011 Marc-Andre Moreau * * 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. */ #ifndef __REDIRECTION_H #define __REDIRECTION_H #include "rdp.h" #include #include #include #include #include /* Redirection Flags */ #define LB_TARGET_NET_ADDRESS 0x00000001 #define LB_LOAD_BALANCE_INFO 0x00000002 #define LB_USERNAME 0x00000004 #define LB_DOMAIN 0x00000008 #define LB_PASSWORD 0x00000010 #define LB_DONTSTOREUSERNAME 0x00000020 #define LB_SMARTCARD_LOGON 0x00000040 #define LB_NOREDIRECT 0x00000080 #define LB_TARGET_FQDN 0x00000100 #define LB_TARGET_NETBIOS_NAME 0x00000200 #define LB_TARGET_NET_ADDRESSES 0x00000800 #define LB_CLIENT_TSV_URL 0x00001000 #define LB_SERVER_TSV_CAPABLE 0x00002000 struct rdp_redirection { uint32 flags; uint32 sessionID; rdpString tsvUrl; rdpString username; rdpString domain; rdpBlob password_cookie; rdpString targetFQDN; rdpBlob loadBalanceInfo; rdpString targetNetBiosName; rdpString targetNetAddress; uint32 targetNetAddressesCount; rdpString* targetNetAddresses; }; typedef struct rdp_redirection rdpRedirection; boolean rdp_recv_redirection_packet(rdpRdp* rdp, STREAM* s); boolean rdp_recv_enhanced_security_redirection_packet(rdpRdp* rdp, STREAM* s); rdpRedirection* redirection_new(); void redirection_free(rdpRedirection* redirection); #ifdef WITH_DEBUG_REDIR #define DEBUG_REDIR(fmt, ...) DEBUG_CLASS(REDIR, fmt, ## __VA_ARGS__) #else #define DEBUG_REDIR(fmt, ...) DEBUG_NULL(fmt, ## __VA_ARGS__) #endif #endif /* __REDIRECTION_H */ FreeRDP-1.0.2/libfreerdp-core/security.c000066400000000000000000000446311207112532300200240ustar00rootroot00000000000000/** * FreeRDP: A Remote Desktop Protocol Client * RDP Security * * Copyright 2011 Marc-Andre Moreau * * 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. */ #include "security.h" /* 0x36 repeated 40 times */ static const uint8 pad1[40] = { "\x36\x36\x36\x36\x36\x36\x36\x36" "\x36\x36\x36\x36\x36\x36\x36\x36" "\x36\x36\x36\x36\x36\x36\x36\x36" "\x36\x36\x36\x36\x36\x36\x36\x36" "\x36\x36\x36\x36\x36\x36\x36\x36" }; /* 0x5C repeated 48 times */ static const uint8 pad2[48] = { "\x5C\x5C\x5C\x5C\x5C\x5C\x5C\x5C" "\x5C\x5C\x5C\x5C\x5C\x5C\x5C\x5C" "\x5C\x5C\x5C\x5C\x5C\x5C\x5C\x5C" "\x5C\x5C\x5C\x5C\x5C\x5C\x5C\x5C" "\x5C\x5C\x5C\x5C\x5C\x5C\x5C\x5C" "\x5C\x5C\x5C\x5C\x5C\x5C\x5C\x5C" }; static const uint8 fips_reverse_table[256] = { 0x00, 0x80, 0x40, 0xc0, 0x20, 0xa0, 0x60, 0xe0, 0x10, 0x90, 0x50, 0xd0, 0x30, 0xb0, 0x70, 0xf0, 0x08, 0x88, 0x48, 0xc8, 0x28, 0xa8, 0x68, 0xe8, 0x18, 0x98, 0x58, 0xd8, 0x38, 0xb8, 0x78, 0xf8, 0x04, 0x84, 0x44, 0xc4, 0x24, 0xa4, 0x64, 0xe4, 0x14, 0x94, 0x54, 0xd4, 0x34, 0xb4, 0x74, 0xf4, 0x0c, 0x8c, 0x4c, 0xcc, 0x2c, 0xac, 0x6c, 0xec, 0x1c, 0x9c, 0x5c, 0xdc, 0x3c, 0xbc, 0x7c, 0xfc, 0x02, 0x82, 0x42, 0xc2, 0x22, 0xa2, 0x62, 0xe2, 0x12, 0x92, 0x52, 0xd2, 0x32, 0xb2, 0x72, 0xf2, 0x0a, 0x8a, 0x4a, 0xca, 0x2a, 0xaa, 0x6a, 0xea, 0x1a, 0x9a, 0x5a, 0xda, 0x3a, 0xba, 0x7a, 0xfa, 0x06, 0x86, 0x46, 0xc6, 0x26, 0xa6, 0x66, 0xe6, 0x16, 0x96, 0x56, 0xd6, 0x36, 0xb6, 0x76, 0xf6, 0x0e, 0x8e, 0x4e, 0xce, 0x2e, 0xae, 0x6e, 0xee, 0x1e, 0x9e, 0x5e, 0xde, 0x3e, 0xbe, 0x7e, 0xfe, 0x01, 0x81, 0x41, 0xc1, 0x21, 0xa1, 0x61, 0xe1, 0x11, 0x91, 0x51, 0xd1, 0x31, 0xb1, 0x71, 0xf1, 0x09, 0x89, 0x49, 0xc9, 0x29, 0xa9, 0x69, 0xe9, 0x19, 0x99, 0x59, 0xd9, 0x39, 0xb9, 0x79, 0xf9, 0x05, 0x85, 0x45, 0xc5, 0x25, 0xa5, 0x65, 0xe5, 0x15, 0x95, 0x55, 0xd5, 0x35, 0xb5, 0x75, 0xf5, 0x0d, 0x8d, 0x4d, 0xcd, 0x2d, 0xad, 0x6d, 0xed, 0x1d, 0x9d, 0x5d, 0xdd, 0x3d, 0xbd, 0x7d, 0xfd, 0x03, 0x83, 0x43, 0xc3, 0x23, 0xa3, 0x63, 0xe3, 0x13, 0x93, 0x53, 0xd3, 0x33, 0xb3, 0x73, 0xf3, 0x0b, 0x8b, 0x4b, 0xcb, 0x2b, 0xab, 0x6b, 0xeb, 0x1b, 0x9b, 0x5b, 0xdb, 0x3b, 0xbb, 0x7b, 0xfb, 0x07, 0x87, 0x47, 0xc7, 0x27, 0xa7, 0x67, 0xe7, 0x17, 0x97, 0x57, 0xd7, 0x37, 0xb7, 0x77, 0xf7, 0x0f, 0x8f, 0x4f, 0xcf, 0x2f, 0xaf, 0x6f, 0xef, 0x1f, 0x9f, 0x5f, 0xdf, 0x3f, 0xbf, 0x7f, 0xff }; static const uint8 fips_oddparity_table[256] = { 0x01, 0x01, 0x02, 0x02, 0x04, 0x04, 0x07, 0x07, 0x08, 0x08, 0x0b, 0x0b, 0x0d, 0x0d, 0x0e, 0x0e, 0x10, 0x10, 0x13, 0x13, 0x15, 0x15, 0x16, 0x16, 0x19, 0x19, 0x1a, 0x1a, 0x1c, 0x1c, 0x1f, 0x1f, 0x20, 0x20, 0x23, 0x23, 0x25, 0x25, 0x26, 0x26, 0x29, 0x29, 0x2a, 0x2a, 0x2c, 0x2c, 0x2f, 0x2f, 0x31, 0x31, 0x32, 0x32, 0x34, 0x34, 0x37, 0x37, 0x38, 0x38, 0x3b, 0x3b, 0x3d, 0x3d, 0x3e, 0x3e, 0x40, 0x40, 0x43, 0x43, 0x45, 0x45, 0x46, 0x46, 0x49, 0x49, 0x4a, 0x4a, 0x4c, 0x4c, 0x4f, 0x4f, 0x51, 0x51, 0x52, 0x52, 0x54, 0x54, 0x57, 0x57, 0x58, 0x58, 0x5b, 0x5b, 0x5d, 0x5d, 0x5e, 0x5e, 0x61, 0x61, 0x62, 0x62, 0x64, 0x64, 0x67, 0x67, 0x68, 0x68, 0x6b, 0x6b, 0x6d, 0x6d, 0x6e, 0x6e, 0x70, 0x70, 0x73, 0x73, 0x75, 0x75, 0x76, 0x76, 0x79, 0x79, 0x7a, 0x7a, 0x7c, 0x7c, 0x7f, 0x7f, 0x80, 0x80, 0x83, 0x83, 0x85, 0x85, 0x86, 0x86, 0x89, 0x89, 0x8a, 0x8a, 0x8c, 0x8c, 0x8f, 0x8f, 0x91, 0x91, 0x92, 0x92, 0x94, 0x94, 0x97, 0x97, 0x98, 0x98, 0x9b, 0x9b, 0x9d, 0x9d, 0x9e, 0x9e, 0xa1, 0xa1, 0xa2, 0xa2, 0xa4, 0xa4, 0xa7, 0xa7, 0xa8, 0xa8, 0xab, 0xab, 0xad, 0xad, 0xae, 0xae, 0xb0, 0xb0, 0xb3, 0xb3, 0xb5, 0xb5, 0xb6, 0xb6, 0xb9, 0xb9, 0xba, 0xba, 0xbc, 0xbc, 0xbf, 0xbf, 0xc1, 0xc1, 0xc2, 0xc2, 0xc4, 0xc4, 0xc7, 0xc7, 0xc8, 0xc8, 0xcb, 0xcb, 0xcd, 0xcd, 0xce, 0xce, 0xd0, 0xd0, 0xd3, 0xd3, 0xd5, 0xd5, 0xd6, 0xd6, 0xd9, 0xd9, 0xda, 0xda, 0xdc, 0xdc, 0xdf, 0xdf, 0xe0, 0xe0, 0xe3, 0xe3, 0xe5, 0xe5, 0xe6, 0xe6, 0xe9, 0xe9, 0xea, 0xea, 0xec, 0xec, 0xef, 0xef, 0xf1, 0xf1, 0xf2, 0xf2, 0xf4, 0xf4, 0xf7, 0xf7, 0xf8, 0xf8, 0xfb, 0xfb, 0xfd, 0xfd, 0xfe, 0xfe }; static void security_salted_hash(uint8* salt, uint8* input, int length, uint8* salt1, uint8* salt2, uint8* output) { CryptoMd5 md5; CryptoSha1 sha1; uint8 sha1_digest[CRYPTO_SHA1_DIGEST_LENGTH]; /* SaltedHash(Salt, Input, Salt1, Salt2) = MD5(S + SHA1(Input + Salt + Salt1 + Salt2)) */ /* SHA1_Digest = SHA1(Input + Salt + Salt1 + Salt2) */ sha1 = crypto_sha1_init(); crypto_sha1_update(sha1, input, length); /* Input */ crypto_sha1_update(sha1, salt, 48); /* Salt (48 bytes) */ crypto_sha1_update(sha1, salt1, 32); /* Salt1 (32 bytes) */ crypto_sha1_update(sha1, salt2, 32); /* Salt2 (32 bytes) */ crypto_sha1_final(sha1, sha1_digest); /* SaltedHash(Salt, Input, Salt1, Salt2) = MD5(S + SHA1_Digest) */ md5 = crypto_md5_init(); crypto_md5_update(md5, salt, 48); /* Salt (48 bytes) */ crypto_md5_update(md5, sha1_digest, sizeof(sha1_digest)); /* SHA1_Digest */ crypto_md5_final(md5, output); } static void security_premaster_hash(char* input, int length, uint8* premaster_secret, uint8* client_random, uint8* server_random, uint8* output) { /* PremasterHash(Input) = SaltedHash(PremasterSecret, Input, ClientRandom, ServerRandom) */ security_salted_hash(premaster_secret, (uint8*)input, length, client_random, server_random, output); } void security_master_secret(uint8* premaster_secret, uint8* client_random, uint8* server_random, uint8* output) { /* MasterSecret = PremasterHash('A') + PremasterHash('BB') + PremasterHash('CCC') */ security_premaster_hash("A", 1, premaster_secret, client_random, server_random, &output[0]); security_premaster_hash("BB", 2, premaster_secret, client_random, server_random, &output[16]); security_premaster_hash("CCC", 3, premaster_secret, client_random, server_random, &output[32]); } static void security_master_hash(char* input, int length, uint8* master_secret, uint8* client_random, uint8* server_random, uint8* output) { /* MasterHash(Input) = SaltedHash(MasterSecret, Input, ServerRandom, ClientRandom) */ security_salted_hash(master_secret, (uint8*)input, length, server_random, client_random, output); } void security_session_key_blob(uint8* master_secret, uint8* client_random, uint8* server_random, uint8* output) { /* MasterHash = MasterHash('A') + MasterHash('BB') + MasterHash('CCC') */ security_master_hash("A", 1, master_secret, client_random, server_random, &output[0]); security_master_hash("BB", 2, master_secret, client_random, server_random, &output[16]); security_master_hash("CCC", 3, master_secret, client_random, server_random, &output[32]); } void security_mac_salt_key(uint8* session_key_blob, uint8* client_random, uint8* server_random, uint8* output) { /* MacSaltKey = First128Bits(SessionKeyBlob) */ memcpy(output, session_key_blob, 16); } void security_md5_16_32_32(uint8* in0, uint8* in1, uint8* in2, uint8* output) { CryptoMd5 md5; md5 = crypto_md5_init(); crypto_md5_update(md5, in0, 16); crypto_md5_update(md5, in1, 32); crypto_md5_update(md5, in2, 32); crypto_md5_final(md5, output); } void security_licensing_encryption_key(uint8* session_key_blob, uint8* client_random, uint8* server_random, uint8* output) { /* LicensingEncryptionKey = MD5(Second128Bits(SessionKeyBlob) + ClientRandom + ServerRandom)) */ security_md5_16_32_32(&session_key_blob[16], client_random, server_random, output); } void security_uint32_le(uint8* output, uint32 value) { output[0] = (value) & 0xFF; output[1] = (value >> 8) & 0xFF; output[2] = (value >> 16) & 0xFF; output[3] = (value >> 24) & 0xFF; } void security_mac_data(uint8* mac_salt_key, uint8* data, uint32 length, uint8* output) { CryptoMd5 md5; CryptoSha1 sha1; uint8 length_le[4]; uint8 sha1_digest[CRYPTO_SHA1_DIGEST_LENGTH]; /* MacData = MD5(MacSaltKey + pad2 + SHA1(MacSaltKey + pad1 + length + data)) */ security_uint32_le(length_le, length); /* length must be little-endian */ /* SHA1_Digest = SHA1(MacSaltKey + pad1 + length + data) */ sha1 = crypto_sha1_init(); crypto_sha1_update(sha1, mac_salt_key, 16); /* MacSaltKey */ crypto_sha1_update(sha1, pad1, sizeof(pad1)); /* pad1 */ crypto_sha1_update(sha1, length_le, sizeof(length_le)); /* length */ crypto_sha1_update(sha1, data, length); /* data */ crypto_sha1_final(sha1, sha1_digest); /* MacData = MD5(MacSaltKey + pad2 + SHA1_Digest) */ md5 = crypto_md5_init(); crypto_md5_update(md5, mac_salt_key, 16); /* MacSaltKey */ crypto_md5_update(md5, pad2, sizeof(pad2)); /* pad2 */ crypto_md5_update(md5, sha1_digest, sizeof(sha1_digest)); /* SHA1_Digest */ crypto_md5_final(md5, output); } void security_mac_signature(rdpRdp *rdp, uint8* data, uint32 length, uint8* output) { CryptoMd5 md5; CryptoSha1 sha1; uint8 length_le[4]; uint8 md5_digest[CRYPTO_MD5_DIGEST_LENGTH]; uint8 sha1_digest[CRYPTO_SHA1_DIGEST_LENGTH]; security_uint32_le(length_le, length); /* length must be little-endian */ /* SHA1_Digest = SHA1(MACKeyN + pad1 + length + data) */ sha1 = crypto_sha1_init(); crypto_sha1_update(sha1, rdp->sign_key, rdp->rc4_key_len); /* MacKeyN */ crypto_sha1_update(sha1, pad1, sizeof(pad1)); /* pad1 */ crypto_sha1_update(sha1, length_le, sizeof(length_le)); /* length */ crypto_sha1_update(sha1, data, length); /* data */ crypto_sha1_final(sha1, sha1_digest); /* MACSignature = First64Bits(MD5(MACKeyN + pad2 + SHA1_Digest)) */ md5 = crypto_md5_init(); crypto_md5_update(md5, rdp->sign_key, rdp->rc4_key_len); /* MacKeyN */ crypto_md5_update(md5, pad2, sizeof(pad2)); /* pad2 */ crypto_md5_update(md5, sha1_digest, sizeof(sha1_digest)); /* SHA1_Digest */ crypto_md5_final(md5, md5_digest); memcpy(output, md5_digest, 8); } void security_salted_mac_signature(rdpRdp *rdp, uint8* data, uint32 length, boolean encryption, uint8* output) { CryptoMd5 md5; CryptoSha1 sha1; uint8 length_le[4]; uint8 use_count_le[4]; uint8 md5_digest[CRYPTO_MD5_DIGEST_LENGTH]; uint8 sha1_digest[CRYPTO_SHA1_DIGEST_LENGTH]; security_uint32_le(length_le, length); /* length must be little-endian */ if (encryption) { security_uint32_le(use_count_le, rdp->encrypt_checksum_use_count); } else { /* * We calculate checksum on plain text, so we must have already * decrypt it, which means decrypt_checksum_use_count is * off by one. */ security_uint32_le(use_count_le, rdp->decrypt_checksum_use_count - 1); } /* SHA1_Digest = SHA1(MACKeyN + pad1 + length + data) */ sha1 = crypto_sha1_init(); crypto_sha1_update(sha1, rdp->sign_key, rdp->rc4_key_len); /* MacKeyN */ crypto_sha1_update(sha1, pad1, sizeof(pad1)); /* pad1 */ crypto_sha1_update(sha1, length_le, sizeof(length_le)); /* length */ crypto_sha1_update(sha1, data, length); /* data */ crypto_sha1_update(sha1, use_count_le, sizeof(use_count_le)); /* encryptionCount */ crypto_sha1_final(sha1, sha1_digest); /* MACSignature = First64Bits(MD5(MACKeyN + pad2 + SHA1_Digest)) */ md5 = crypto_md5_init(); crypto_md5_update(md5, rdp->sign_key, rdp->rc4_key_len); /* MacKeyN */ crypto_md5_update(md5, pad2, sizeof(pad2)); /* pad2 */ crypto_md5_update(md5, sha1_digest, sizeof(sha1_digest)); /* SHA1_Digest */ crypto_md5_final(md5, md5_digest); memcpy(output, md5_digest, 8); } static void security_A(uint8* master_secret, uint8* client_random, uint8* server_random, uint8* output) { security_premaster_hash("A", 1, master_secret, client_random, server_random, &output[0]); security_premaster_hash("BB", 2, master_secret, client_random, server_random, &output[16]); security_premaster_hash("CCC", 3, master_secret, client_random, server_random, &output[32]); } static void security_X(uint8* master_secret, uint8* client_random, uint8* server_random, uint8* output) { security_premaster_hash("X", 1, master_secret, client_random, server_random, &output[0]); security_premaster_hash("YY", 2, master_secret, client_random, server_random, &output[16]); security_premaster_hash("ZZZ", 3, master_secret, client_random, server_random, &output[32]); } static void fips_expand_key_bits(uint8* in, uint8* out) { uint8 buf[21], c; int i, b, p, r; /* reverse every byte in the key */ for (i = 0; i < 21; i++) buf[i] = fips_reverse_table[in[i]]; /* insert a zero-bit after every 7th bit */ for (i = 0, b = 0; i < 24; i++, b += 7) { p = b / 8; r = b % 8; if (r == 0) { out[i] = buf[p] & 0xfe; } else { /* c is accumulator */ c = buf[p] << r; c |= buf[p + 1] >> (8 - r); out[i] = c & 0xfe; } } /* reverse every byte */ /* alter lsb so the byte has odd parity */ for (i = 0; i < 24; i++) out[i] = fips_oddparity_table[fips_reverse_table[out[i]]]; } boolean security_establish_keys(uint8* client_random, rdpRdp* rdp) { uint8 pre_master_secret[48]; uint8 master_secret[48]; uint8 session_key_blob[48]; uint8* server_random; uint8 salt40[] = { 0xD1, 0x26, 0x9E }; rdpSettings* settings; settings = rdp->settings; server_random = settings->server_random->data; if (settings->encryption_method == ENCRYPTION_METHOD_FIPS) { CryptoSha1 sha1; uint8 client_encrypt_key_t[CRYPTO_SHA1_DIGEST_LENGTH + 1]; uint8 client_decrypt_key_t[CRYPTO_SHA1_DIGEST_LENGTH + 1]; printf("FIPS Compliant encryption level.\n"); /* disable fastpath input; it doesnt handle FIPS encryption yet */ rdp->settings->fastpath_input = false; sha1 = crypto_sha1_init(); crypto_sha1_update(sha1, client_random + 16, 16); crypto_sha1_update(sha1, server_random + 16, 16); crypto_sha1_final(sha1, client_encrypt_key_t); client_encrypt_key_t[20] = client_encrypt_key_t[0]; fips_expand_key_bits(client_encrypt_key_t, rdp->fips_encrypt_key); sha1 = crypto_sha1_init(); crypto_sha1_update(sha1, client_random, 16); crypto_sha1_update(sha1, server_random, 16); crypto_sha1_final(sha1, client_decrypt_key_t); client_decrypt_key_t[20] = client_decrypt_key_t[0]; fips_expand_key_bits(client_decrypt_key_t, rdp->fips_decrypt_key); sha1 = crypto_sha1_init(); crypto_sha1_update(sha1, client_decrypt_key_t, 20); crypto_sha1_update(sha1, client_encrypt_key_t, 20); crypto_sha1_final(sha1, rdp->fips_sign_key); } memcpy(pre_master_secret, client_random, 24); memcpy(pre_master_secret + 24, server_random, 24); security_A(pre_master_secret, client_random, server_random, master_secret); security_X(master_secret, client_random, server_random, session_key_blob); memcpy(rdp->sign_key, session_key_blob, 16); if (rdp->settings->server_mode) { security_md5_16_32_32(&session_key_blob[16], client_random, server_random, rdp->encrypt_key); security_md5_16_32_32(&session_key_blob[32], client_random, server_random, rdp->decrypt_key); } else { security_md5_16_32_32(&session_key_blob[16], client_random, server_random, rdp->decrypt_key); security_md5_16_32_32(&session_key_blob[32], client_random, server_random, rdp->encrypt_key); } if (settings->encryption_method == 1) /* 40 and 56 bit */ { memcpy(rdp->sign_key, salt40, 3); /* TODO 56 bit */ memcpy(rdp->decrypt_key, salt40, 3); /* TODO 56 bit */ memcpy(rdp->encrypt_key, salt40, 3); /* TODO 56 bit */ rdp->rc4_key_len = 8; } else if (settings->encryption_method == 2) /* 128 bit */ { rdp->rc4_key_len = 16; } memcpy(rdp->decrypt_update_key, rdp->decrypt_key, 16); memcpy(rdp->encrypt_update_key, rdp->encrypt_key, 16); rdp->decrypt_use_count = 0; rdp->decrypt_checksum_use_count = 0; rdp->encrypt_use_count =0; rdp->encrypt_checksum_use_count =0; return true; } boolean security_key_update(uint8* key, uint8* update_key, int key_len) { uint8 sha1h[CRYPTO_SHA1_DIGEST_LENGTH]; CryptoMd5 md5; CryptoSha1 sha1; CryptoRc4 rc4; uint8 salt40[] = { 0xD1, 0x26, 0x9E }; sha1 = crypto_sha1_init(); crypto_sha1_update(sha1, update_key, key_len); crypto_sha1_update(sha1, pad1, sizeof(pad1)); crypto_sha1_update(sha1, key, key_len); crypto_sha1_final(sha1, sha1h); md5 = crypto_md5_init(); crypto_md5_update(md5, update_key, key_len); crypto_md5_update(md5, pad2, sizeof(pad2)); crypto_md5_update(md5, sha1h, sizeof(sha1h)); crypto_md5_final(md5, key); rc4 = crypto_rc4_init(key, key_len); crypto_rc4(rc4, key_len, key, key); crypto_rc4_free(rc4); if (key_len == 8) memcpy(key, salt40, 3); /* TODO 56 bit */ return true; } boolean security_encrypt(uint8* data, int length, rdpRdp* rdp) { if (rdp->encrypt_use_count >= 4096) { security_key_update(rdp->encrypt_key, rdp->encrypt_update_key, rdp->rc4_key_len); crypto_rc4_free(rdp->rc4_encrypt_key); rdp->rc4_encrypt_key = crypto_rc4_init(rdp->encrypt_key, rdp->rc4_key_len); rdp->encrypt_use_count = 0; } crypto_rc4(rdp->rc4_encrypt_key, length, data, data); rdp->encrypt_use_count++; rdp->encrypt_checksum_use_count++; return true; } boolean security_decrypt(uint8* data, int length, rdpRdp* rdp) { if (rdp->decrypt_use_count >= 4096) { security_key_update(rdp->decrypt_key, rdp->decrypt_update_key, rdp->rc4_key_len); crypto_rc4_free(rdp->rc4_decrypt_key); rdp->rc4_decrypt_key = crypto_rc4_init(rdp->decrypt_key, rdp->rc4_key_len); rdp->decrypt_use_count = 0; } crypto_rc4(rdp->rc4_decrypt_key, length, data, data); rdp->decrypt_use_count += 1; rdp->decrypt_checksum_use_count++; return true; } void security_hmac_signature(uint8* data, int length, uint8* output, rdpRdp* rdp) { uint8 buf[20]; uint8 use_count_le[4]; security_uint32_le(use_count_le, rdp->encrypt_use_count); crypto_hmac_sha1_init(rdp->fips_hmac, rdp->fips_sign_key, 20); crypto_hmac_update(rdp->fips_hmac, data, length); crypto_hmac_update(rdp->fips_hmac, use_count_le, 4); crypto_hmac_final(rdp->fips_hmac, buf, 20); memmove(output, buf, 8); } boolean security_fips_encrypt(uint8* data, int length, rdpRdp* rdp) { crypto_des3_encrypt(rdp->fips_encrypt, length, data, data); rdp->encrypt_use_count++; return true; } boolean security_fips_decrypt(uint8* data, int length, rdpRdp* rdp) { crypto_des3_decrypt(rdp->fips_decrypt, length, data, data); return true; } boolean security_fips_check_signature(uint8* data, int length, uint8* sig, rdpRdp* rdp) { uint8 buf[20]; uint8 use_count_le[4]; security_uint32_le(use_count_le, rdp->decrypt_use_count); crypto_hmac_sha1_init(rdp->fips_hmac, rdp->fips_sign_key, 20); crypto_hmac_update(rdp->fips_hmac, data, length); crypto_hmac_update(rdp->fips_hmac, use_count_le, 4); crypto_hmac_final(rdp->fips_hmac, buf, 20); rdp->decrypt_use_count++; if (memcmp(sig, buf, 8)) return false; return true; } FreeRDP-1.0.2/libfreerdp-core/security.h000066400000000000000000000041141207112532300200210ustar00rootroot00000000000000/** * FreeRDP: A Remote Desktop Protocol Client * RDP Security * * Copyright 2011 Marc-Andre Moreau * * 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. */ #ifndef __SECURITY_H #define __SECURITY_H #include "rdp.h" #include "crypto.h" #include #include void security_master_secret(uint8* premaster_secret, uint8* client_random, uint8* server_random, uint8* output); void security_session_key_blob(uint8* master_secret, uint8* client_random, uint8* server_random, uint8* output); void security_mac_salt_key(uint8* session_key_blob, uint8* client_random, uint8* server_random, uint8* output); void security_licensing_encryption_key(uint8* session_key_blob, uint8* client_random, uint8* server_random, uint8* output); void security_mac_data(uint8* mac_salt_key, uint8* data, uint32 length, uint8* output); void security_mac_signature(rdpRdp *rdp, uint8* data, uint32 length, uint8* output); void security_salted_mac_signature(rdpRdp *rdp, uint8* data, uint32 length, boolean encryption, uint8* output); boolean security_establish_keys(uint8* client_random, rdpRdp* rdp); boolean security_encrypt(uint8* data, int length, rdpRdp* rdp); boolean security_decrypt(uint8* data, int length, rdpRdp* rdp); void security_hmac_signature(uint8* data, int length, uint8* output, rdpRdp* rdp); boolean security_fips_encrypt(uint8* data, int length, rdpRdp* rdp); boolean security_fips_decrypt(uint8* data, int length, rdpRdp* rdp); boolean security_fips_check_signature(uint8* data, int length, uint8* sig, rdpRdp* rdp); #endif /* __SECURITY_H */ FreeRDP-1.0.2/libfreerdp-core/settings.c000066400000000000000000000163651207112532300200200ustar00rootroot00000000000000/** * FreeRDP: A Remote Desktop Protocol Client * RDP Settings * * Copyright 2009-2011 Jay Sorg * * 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. */ #include "config.h" #include "capabilities.h" #include #ifdef HAVE_UNISTD_H #include #endif #include #include static const char client_dll[] = "C:\\Windows\\System32\\mstscax.dll"; rdpSettings* settings_new(void* instance) { rdpSettings* settings; settings = (rdpSettings*) xzalloc(sizeof(rdpSettings)); if (settings != NULL) { settings->instance = instance; settings->width = 1024; settings->height = 768; settings->workarea = false; settings->fullscreen = false; settings->grab_keyboard = true; settings->decorations = true; settings->rdp_version = 7; settings->color_depth = 16; settings->nla_security = true; settings->tls_security = true; settings->rdp_security = true; settings->client_build = 2600; settings->kbd_type = 0; settings->kbd_subtype = 0; settings->kbd_fn_keys = 0; settings->kbd_layout = 0; settings->encryption = false; settings->secure_checksum = false; settings->port = 3389; settings->desktop_resize = true; settings->performance_flags = PERF_DISABLE_FULLWINDOWDRAG | PERF_DISABLE_MENUANIMATIONS | PERF_DISABLE_WALLPAPER; settings->auto_reconnection = true; settings->encryption_method = ENCRYPTION_METHOD_NONE; settings->encryption_level = ENCRYPTION_LEVEL_NONE; settings->authentication = true; settings->authentication_only = false; settings->from_stdin = false; settings->order_support[NEG_DSTBLT_INDEX] = true; settings->order_support[NEG_PATBLT_INDEX] = true; settings->order_support[NEG_SCRBLT_INDEX] = true; settings->order_support[NEG_OPAQUE_RECT_INDEX] = true; settings->order_support[NEG_DRAWNINEGRID_INDEX] = true; settings->order_support[NEG_MULTIDSTBLT_INDEX] = true; settings->order_support[NEG_MULTIPATBLT_INDEX] = true; settings->order_support[NEG_MULTISCRBLT_INDEX] = true; settings->order_support[NEG_MULTIOPAQUERECT_INDEX] = true; settings->order_support[NEG_MULTI_DRAWNINEGRID_INDEX] = true; settings->order_support[NEG_LINETO_INDEX] = true; settings->order_support[NEG_POLYLINE_INDEX] = true; settings->order_support[NEG_MEMBLT_INDEX] = true; settings->order_support[NEG_MEM3BLT_INDEX] = true; settings->order_support[NEG_SAVEBITMAP_INDEX] = true; settings->order_support[NEG_GLYPH_INDEX_INDEX] = true; settings->order_support[NEG_FAST_INDEX_INDEX] = true; settings->order_support[NEG_FAST_GLYPH_INDEX] = true; settings->order_support[NEG_POLYGON_SC_INDEX] = true; settings->order_support[NEG_POLYGON_CB_INDEX] = true; settings->order_support[NEG_ELLIPSE_SC_INDEX] = true; settings->order_support[NEG_ELLIPSE_CB_INDEX] = true; settings->color_pointer = true; settings->large_pointer = true; settings->pointer_cache_size = 20; settings->sound_beeps = true; settings->disable_wallpaper = false; settings->disable_full_window_drag = false; settings->disable_menu_animations = false; settings->disable_theming = false; settings->connection_type = 0; settings->draw_gdi_plus = false; settings->frame_marker = false; settings->bitmap_cache_v3 = false; settings->bitmap_cache = true; settings->persistent_bitmap_cache = false; settings->bitmapCacheV2CellInfo = xzalloc(sizeof(BITMAP_CACHE_V2_CELL_INFO) * 6); settings->refresh_rect = true; settings->suppress_output = true; settings->glyph_cache = true; settings->glyphSupportLevel = GLYPH_SUPPORT_NONE; settings->glyphCache = xzalloc(sizeof(GLYPH_CACHE_DEFINITION) * 10); settings->fragCache = xnew(GLYPH_CACHE_DEFINITION); settings->glyphCache[0].cacheEntries = 254; settings->glyphCache[0].cacheMaximumCellSize = 4; settings->glyphCache[1].cacheEntries = 254; settings->glyphCache[1].cacheMaximumCellSize = 4; settings->glyphCache[2].cacheEntries = 254; settings->glyphCache[2].cacheMaximumCellSize = 8; settings->glyphCache[3].cacheEntries = 254; settings->glyphCache[3].cacheMaximumCellSize = 8; settings->glyphCache[4].cacheEntries = 254; settings->glyphCache[4].cacheMaximumCellSize = 16; settings->glyphCache[5].cacheEntries = 254; settings->glyphCache[5].cacheMaximumCellSize = 32; settings->glyphCache[6].cacheEntries = 254; settings->glyphCache[6].cacheMaximumCellSize = 64; settings->glyphCache[7].cacheEntries = 254; settings->glyphCache[7].cacheMaximumCellSize = 128; settings->glyphCache[8].cacheEntries = 254; settings->glyphCache[8].cacheMaximumCellSize = 256; settings->glyphCache[9].cacheEntries = 64; settings->glyphCache[9].cacheMaximumCellSize = 256; settings->fragCache->cacheEntries = 256; settings->fragCache->cacheMaximumCellSize = 256; settings->offscreen_bitmap_cache = true; settings->offscreen_bitmap_cache_size = 7680; settings->offscreen_bitmap_cache_entries = 100; settings->draw_nine_grid_cache_size = 2560; settings->draw_nine_grid_cache_entries = 256; settings->client_dir = xstrdup(client_dll); settings->num_icon_caches = 3; settings->num_icon_cache_entries = 12; settings->vc_chunk_size = CHANNEL_CHUNK_LENGTH; settings->multifrag_max_request_size = 0x200000; settings->fastpath_input = true; settings->fastpath_output = true; settings->uniconv = freerdp_uniconv_new(); gethostname(settings->client_hostname, sizeof(settings->client_hostname) - 1); settings->mouse_motion = true; settings->client_auto_reconnect_cookie = xnew(ARC_CS_PRIVATE_PACKET); settings->server_auto_reconnect_cookie = xnew(ARC_SC_PRIVATE_PACKET); settings->client_time_zone = xnew(TIME_ZONE_INFO); settings->server_random = xnew(rdpBlob); settings->server_certificate = xnew(rdpBlob); freerdp_detect_paths(settings); } return settings; } void settings_free(rdpSettings* settings) { if (settings != NULL) { freerdp_uniconv_free(settings->uniconv); xfree(settings->hostname); xfree(settings->username); xfree(settings->password); xfree(settings->domain); xfree(settings->shell); xfree(settings->directory); xfree(settings->ip_address); xfree(settings->client_dir); xfree(settings->cert_file); xfree(settings->privatekey_file); freerdp_blob_free(settings->server_random); freerdp_blob_free(settings->server_certificate); xfree(settings->server_random); xfree(settings->server_certificate); xfree(settings->rdp_key_file); certificate_free(settings->server_cert); xfree(settings->client_auto_reconnect_cookie); xfree(settings->server_auto_reconnect_cookie); xfree(settings->client_time_zone); xfree(settings->bitmapCacheV2CellInfo); xfree(settings->glyphCache); xfree(settings->fragCache); key_free(settings->server_key); xfree(settings->config_path); xfree(settings->current_path); xfree(settings->development_path); xfree(settings); } } FreeRDP-1.0.2/libfreerdp-core/surface.c000066400000000000000000000065011207112532300175770ustar00rootroot00000000000000/** * FreeRDP: A Remote Desktop Protocol Client * Surface Commands * * Copyright 2011 Vic Lee * * 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. */ #include #include "surface.h" static int update_recv_surfcmd_surface_bits(rdpUpdate* update, STREAM* s) { int pos; SURFACE_BITS_COMMAND* cmd = &update->surface_bits_command; stream_read_uint16(s, cmd->destLeft); stream_read_uint16(s, cmd->destTop); stream_read_uint16(s, cmd->destRight); stream_read_uint16(s, cmd->destBottom); stream_read_uint8(s, cmd->bpp); stream_seek(s, 2); /* reserved1, reserved2 */ stream_read_uint8(s, cmd->codecID); stream_read_uint16(s, cmd->width); stream_read_uint16(s, cmd->height); stream_read_uint32(s, cmd->bitmapDataLength); pos = stream_get_pos(s) + cmd->bitmapDataLength; cmd->bitmapData = stream_get_tail(s); IFCALL(update->SurfaceBits, update->context, cmd); stream_set_pos(s, pos); return 20 + cmd->bitmapDataLength; } static int update_recv_surfcmd_frame_marker(rdpUpdate* update, STREAM* s) { SURFACE_FRAME_MARKER* marker = &update->surface_frame_marker; stream_read_uint16(s, marker->frameAction); stream_read_uint32(s, marker->frameId); IFCALL(update->SurfaceFrameMarker, update->context, marker); return 6; } boolean update_recv_surfcmds(rdpUpdate* update, uint32 size, STREAM* s) { uint8* mark; uint16 cmdType; uint32 cmdLength; while (size > 2) { stream_get_mark(s, mark); stream_read_uint16(s, cmdType); size -= 2; switch (cmdType) { case CMDTYPE_SET_SURFACE_BITS: case CMDTYPE_STREAM_SURFACE_BITS: cmdLength = update_recv_surfcmd_surface_bits(update, s); break; case CMDTYPE_FRAME_MARKER: cmdLength = update_recv_surfcmd_frame_marker(update, s); break; default: DEBUG_WARN("unknown cmdType 0x%X", cmdType); return false; } size -= cmdLength; if (update->dump_rfx) { pcap_add_record(update->pcap_rfx, mark, cmdLength + 2); pcap_flush(update->pcap_rfx); } } return true; } void update_write_surfcmd_surface_bits_header(STREAM* s, SURFACE_BITS_COMMAND* cmd) { stream_check_size(s, SURFCMD_SURFACE_BITS_HEADER_LENGTH); stream_write_uint16(s, CMDTYPE_STREAM_SURFACE_BITS); stream_write_uint16(s, cmd->destLeft); stream_write_uint16(s, cmd->destTop); stream_write_uint16(s, cmd->destRight); stream_write_uint16(s, cmd->destBottom); stream_write_uint8(s, cmd->bpp); stream_write_uint16(s, 0); /* reserved1, reserved2 */ stream_write_uint8(s, cmd->codecID); stream_write_uint16(s, cmd->width); stream_write_uint16(s, cmd->height); stream_write_uint32(s, cmd->bitmapDataLength); } void update_write_surfcmd_frame_marker(STREAM* s, uint16 frameAction, uint32 frameId) { stream_check_size(s, SURFCMD_FRAME_MARKER_LENGTH); stream_write_uint16(s, CMDTYPE_FRAME_MARKER); stream_write_uint16(s, frameAction); stream_write_uint32(s, frameId); } FreeRDP-1.0.2/libfreerdp-core/surface.h000066400000000000000000000025031207112532300176020ustar00rootroot00000000000000/** * FreeRDP: A Remote Desktop Protocol Client * Surface Commands * * Copyright 2011 Vic Lee * * 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. */ #ifndef __SURFACE #define __SURFACE #include "rdp.h" #include #define SURFCMD_SURFACE_BITS_HEADER_LENGTH 22 #define SURFCMD_FRAME_MARKER_LENGTH 8 enum SURFCMD_CMDTYPE { CMDTYPE_SET_SURFACE_BITS = 0x0001, CMDTYPE_FRAME_MARKER = 0x0004, CMDTYPE_STREAM_SURFACE_BITS = 0x0006 }; enum SURFCMD_FRAMEACTION { SURFACECMD_FRAMEACTION_BEGIN = 0x0000, SURFACECMD_FRAMEACTION_END = 0x0001 }; boolean update_recv_surfcmds(rdpUpdate* update, uint32 size, STREAM* s); void update_write_surfcmd_surface_bits_header(STREAM* s, SURFACE_BITS_COMMAND* cmd); void update_write_surfcmd_frame_marker(STREAM* s, uint16 frameAction, uint32 frameId); #endif /* __SURFACE */ FreeRDP-1.0.2/libfreerdp-core/tcp.c000066400000000000000000000150231207112532300167340ustar00rootroot00000000000000/** * FreeRDP: A Remote Desktop Protocol Client * Transmission Control Protocol (TCP) * * Copyright 2011 Vic Lee * Copyright 2011 Marc-Andre Moreau * * 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. */ #include #include #include #include #include #include #ifndef _WIN32 #include #include #include #include #include #include #include #ifdef __APPLE__ #ifndef TCP_KEEPIDLE #define TCP_KEEPIDLE TCP_KEEPALIVE #endif #endif #else #define SHUT_RDWR SD_BOTH #define close(_fd) closesocket(_fd) #endif #include #include #include #include "tcp.h" void tcp_get_ip_address(rdpTcp * tcp) { uint8* ip; socklen_t length; struct sockaddr_in sockaddr; length = sizeof(sockaddr); if (getsockname(tcp->sockfd, (struct sockaddr*) &sockaddr, &length) == 0) { ip = (uint8*) (&sockaddr.sin_addr); snprintf(tcp->ip_address, sizeof(tcp->ip_address), "%u.%u.%u.%u", ip[0], ip[1], ip[2], ip[3]); } else { strncpy(tcp->ip_address, "127.0.0.1", sizeof(tcp->ip_address)); } tcp->ip_address[sizeof(tcp->ip_address) - 1] = 0; tcp->settings->ipv6 = 0; tcp->settings->ip_address = xstrdup(tcp->ip_address); } void tcp_get_mac_address(rdpTcp * tcp) { #ifdef LINUX uint8* mac; struct ifreq if_req; struct if_nameindex* ni; ni = if_nameindex(); mac = tcp->mac_address; while (ni->if_name != NULL) { if (strcmp(ni->if_name, "lo") != 0) break; ni++; } strncpy(if_req.ifr_name, ni->if_name, IF_NAMESIZE); if (ioctl(tcp->sockfd, SIOCGIFHWADDR, &if_req) != 0) { printf("failed to obtain MAC address\n"); return; } memmove((void*) mac, (void*) &if_req.ifr_ifru.ifru_hwaddr.sa_data[0], 6); #endif /* printf("MAC: %02X:%02X:%02X:%02X:%02X:%02X\n", mac[0], mac[1], mac[2], mac[3], mac[4], mac[5]); */ } boolean tcp_connect(rdpTcp* tcp, const char* hostname, uint16 port) { int status; char servname[10]; uint32 option_value; socklen_t option_len; struct addrinfo hints = { 0 }; struct addrinfo * res, * ai; memset(&hints, 0, sizeof(struct addrinfo)); hints.ai_family = AF_UNSPEC; hints.ai_socktype = SOCK_STREAM; snprintf(servname, sizeof(servname), "%d", port); status = getaddrinfo(hostname, servname, &hints, &res); if (status != 0) { printf("transport_connect: getaddrinfo (%s)\n", gai_strerror(status)); return false; } tcp->sockfd = -1; for (ai = res; ai; ai = ai->ai_next) { tcp->sockfd = socket(ai->ai_family, ai->ai_socktype, ai->ai_protocol); if (tcp->sockfd < 0) continue; if (connect(tcp->sockfd, ai->ai_addr, ai->ai_addrlen) == 0) { printf("connected to %s:%s\n", hostname, servname); break; } close(tcp->sockfd); tcp->sockfd = -1; } freeaddrinfo(res); if (tcp->sockfd == -1) { printf("unable to connect to %s:%s\n", hostname, servname); return false; } tcp_get_ip_address(tcp); tcp_get_mac_address(tcp); option_value = 1; option_len = sizeof(option_value); setsockopt(tcp->sockfd, IPPROTO_TCP, TCP_NODELAY, (void*) &option_value, option_len); /* receive buffer must be a least 32 K */ if (getsockopt(tcp->sockfd, SOL_SOCKET, SO_RCVBUF, (void*) &option_value, &option_len) == 0) { if (option_value < (1024 * 32)) { option_value = 1024 * 32; option_len = sizeof(option_value); setsockopt(tcp->sockfd, SOL_SOCKET, SO_RCVBUF, (void*) &option_value, option_len); } } tcp_set_keep_alive_mode(tcp); return true; } int tcp_read(rdpTcp* tcp, uint8* data, int length) { int status; status = recv(tcp->sockfd, data, length, 0); if (status == 0) { /* Peer disconnected. */ return -1; } else if (status < 0) { #ifdef _WIN32 int wsa_error = WSAGetLastError(); /* No data available */ if (wsa_error == WSAEWOULDBLOCK) return 0; printf("recv() error: %d\n", wsa_error); #else /* No data available */ if (errno == EAGAIN || errno == EWOULDBLOCK) return 0; perror("recv"); #endif return -1; } return status; } int tcp_write(rdpTcp* tcp, uint8* data, int length) { int status; status = send(tcp->sockfd, data, length, MSG_NOSIGNAL); if (status < 0) { #ifdef _WIN32 int wsa_error = WSAGetLastError(); /* No data available */ if (wsa_error == WSAEWOULDBLOCK) status = 0; else perror("send"); #else if (errno == EAGAIN || errno == EWOULDBLOCK) status = 0; else perror("send"); #endif } return status; } boolean tcp_disconnect(rdpTcp * tcp) { if (tcp->sockfd != -1) { shutdown(tcp->sockfd, SHUT_RDWR); close(tcp->sockfd); tcp->sockfd = -1; } return true; } boolean tcp_set_blocking_mode(rdpTcp* tcp, boolean blocking) { #ifndef _WIN32 int flags; flags = fcntl(tcp->sockfd, F_GETFL); if (flags == -1) { printf("tcp_set_blocking_mode: fcntl failed.\n"); return false; } if (blocking == true) fcntl(tcp->sockfd, F_SETFL, flags & ~(O_NONBLOCK)); else fcntl(tcp->sockfd, F_SETFL, flags | O_NONBLOCK); #else u_long arg = blocking; ioctlsocket(tcp->sockfd, FIONBIO, &arg); tcp->wsa_event = WSACreateEvent(); WSAEventSelect(tcp->sockfd, tcp->wsa_event, FD_READ); #endif return true; } boolean tcp_set_keep_alive_mode(rdpTcp* tcp) { #ifndef _WIN32 uint32 option_value; socklen_t option_len; option_value = 1; option_len = sizeof(option_value); if (setsockopt(tcp->sockfd, SOL_SOCKET, SO_KEEPALIVE, (void*) &option_value, option_len) < 0) { perror("setsockopt() SOL_SOCKET, SO_KEEPALIVE:"); return false; } #ifdef TCP_KEEPIDLE option_value = 5; option_len = sizeof(option_value); if (setsockopt(tcp->sockfd, IPPROTO_TCP, TCP_KEEPIDLE, (void*) &option_value, option_len) < 0) { perror("setsockopt() IPPROTO_TCP, SO_KEEPIDLE:"); return false; } #endif #endif return true; } rdpTcp* tcp_new(rdpSettings* settings) { rdpTcp* tcp; tcp = (rdpTcp*) xzalloc(sizeof(rdpTcp)); if (tcp != NULL) { tcp->sockfd = -1; tcp->settings = settings; } return tcp; } void tcp_free(rdpTcp* tcp) { if (tcp != NULL) { xfree(tcp); } } FreeRDP-1.0.2/libfreerdp-core/tcp.h000066400000000000000000000031041207112532300167360ustar00rootroot00000000000000/** * FreeRDP: A Remote Desktop Protocol Client * Transmission Control Protocol (TCP) * * Copyright 2011 Vic Lee * Copyright 2011 Marc-Andre Moreau * * 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. */ #ifndef __TCP_H #define __TCP_H #ifdef _WIN32 #include #include #include #endif #include #include #include #ifndef MSG_NOSIGNAL #define MSG_NOSIGNAL 0 #endif typedef struct rdp_tcp rdpTcp; struct rdp_tcp { int sockfd; char ip_address[32]; uint8 mac_address[6]; struct rdp_settings* settings; #ifdef _WIN32 WSAEVENT wsa_event; #endif }; boolean tcp_connect(rdpTcp* tcp, const char* hostname, uint16 port); boolean tcp_disconnect(rdpTcp* tcp); int tcp_read(rdpTcp* tcp, uint8* data, int length); int tcp_write(rdpTcp* tcp, uint8* data, int length); boolean tcp_set_blocking_mode(rdpTcp* tcp, boolean blocking); boolean tcp_set_keep_alive_mode(rdpTcp* tcp); rdpTcp* tcp_new(rdpSettings* settings); void tcp_free(rdpTcp* tcp); #endif /* __TCP_H */ FreeRDP-1.0.2/libfreerdp-core/tls.c000066400000000000000000000253471207112532300167620ustar00rootroot00000000000000/** * FreeRDP: A Remote Desktop Protocol Client * Transport Layer Security * * Copyright 2011 Marc-Andre Moreau * * 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. */ #include #include #include "tls.h" boolean tls_connect(rdpTls* tls) { int connection_status; tls->ctx = SSL_CTX_new(TLSv1_client_method()); if (tls->ctx == NULL) { printf("SSL_CTX_new failed\n"); return false; } /* * This is necessary, because the Microsoft TLS implementation is not perfect. * SSL_OP_ALL enables a couple of workarounds for buggy TLS implementations, * but the most important workaround being SSL_OP_TLS_BLOCK_PADDING_BUG. * As the size of the encrypted payload may give hints about its contents, * block padding is normally used, but the Microsoft TLS implementation * won't recognize it and will disconnect you after sending a TLS alert. */ SSL_CTX_set_options(tls->ctx, SSL_OP_ALL); tls->ssl = SSL_new(tls->ctx); if (tls->ssl == NULL) { printf("SSL_new failed\n"); return false; } if (SSL_set_fd(tls->ssl, tls->sockfd) < 1) { printf("SSL_set_fd failed\n"); return false; } connection_status = SSL_connect(tls->ssl); if (connection_status <= 0) { if (tls_print_error("SSL_connect", tls->ssl, connection_status)) return false; } return true; } boolean tls_accept(rdpTls* tls, const char* cert_file, const char* privatekey_file) { int connection_status; tls->ctx = SSL_CTX_new(SSLv23_server_method()); if (tls->ctx == NULL) { printf("SSL_CTX_new failed\n"); return false; } /* * We only want SSLv3 and TLSv1, so disable SSLv2. * SSLv3 is used by, eg. Microsoft RDC for Mac OS X. */ SSL_CTX_set_options(tls->ctx, SSL_OP_NO_SSLv2); if (SSL_CTX_use_RSAPrivateKey_file(tls->ctx, privatekey_file, SSL_FILETYPE_PEM) <= 0) { printf("SSL_CTX_use_RSAPrivateKey_file failed\n"); return false; } tls->ssl = SSL_new(tls->ctx); if (tls->ssl == NULL) { printf("SSL_new failed\n"); return false; } if (SSL_use_certificate_file(tls->ssl, cert_file, SSL_FILETYPE_PEM) <= 0) { printf("SSL_use_certificate_file failed\n"); return false; } if (SSL_set_fd(tls->ssl, tls->sockfd) < 1) { printf("SSL_set_fd failed\n"); return false; } connection_status = SSL_accept(tls->ssl); if (connection_status <= 0) { if (tls_print_error("SSL_accept", tls->ssl, connection_status)) return false; } printf("TLS connection accepted\n"); return true; } boolean tls_disconnect(rdpTls* tls) { SSL_shutdown(tls->ssl); return true; } int tls_read(rdpTls* tls, uint8* data, int length) { int status; status = SSL_read(tls->ssl, data, length); switch (SSL_get_error(tls->ssl, status)) { case SSL_ERROR_NONE: break; case SSL_ERROR_WANT_READ: case SSL_ERROR_WANT_WRITE: status = 0; break; default: tls_print_error("SSL_read", tls->ssl, status); status = -1; break; } return status; } int tls_write(rdpTls* tls, uint8* data, int length) { int status; status = SSL_write(tls->ssl, data, length); switch (SSL_get_error(tls->ssl, status)) { case SSL_ERROR_NONE: break; case SSL_ERROR_WANT_READ: case SSL_ERROR_WANT_WRITE: status = 0; break; default: tls_print_error("SSL_write", tls->ssl, status); status = -1; break; } return status; } boolean tls_print_error(char* func, SSL* connection, int value) { switch (SSL_get_error(connection, value)) { case SSL_ERROR_ZERO_RETURN: printf("%s: Server closed TLS connection\n", func); return true; case SSL_ERROR_WANT_READ: printf("SSL_ERROR_WANT_READ\n"); return false; case SSL_ERROR_WANT_WRITE: printf("SSL_ERROR_WANT_WRITE\n"); return false; case SSL_ERROR_SYSCALL: printf("%s: I/O error\n", func); return true; case SSL_ERROR_SSL: printf("%s: Failure in SSL library (protocol error?)\n", func); return true; default: printf("%s: Unknown error\n", func); return true; } } CryptoCert tls_get_certificate(rdpTls* tls) { CryptoCert cert; X509* server_cert; server_cert = SSL_get_peer_certificate(tls->ssl); if (!server_cert) { printf("ssl_verify: failed to get the server SSL certificate\n"); cert = NULL; } else { cert = xmalloc(sizeof(*cert)); cert->px509 = server_cert; } return cert; } boolean tls_verify_certificate(rdpTls* tls, CryptoCert cert, char* hostname) { int match; int index; char* common_name; int common_name_length; char** alt_names; int alt_names_count; int* alt_names_lengths; boolean certificate_status; boolean hostname_match = false; rdpCertificateData* certificate_data; /* ignore certificate verification if user explicitly required it (discouraged) */ if (tls->settings->ignore_certificate) return true; /* success! */ /* if user explicitly specified a certificate name, use it instead of the hostname */ if (tls->settings->certificate_name) hostname = tls->settings->certificate_name; /* attempt verification using OpenSSL and the ~/.freerdp/certs certificate store */ certificate_status = x509_verify_certificate(cert, tls->certificate_store->path); /* verify certificate name match */ certificate_data = crypto_get_certificate_data(cert->px509, hostname); /* extra common name and alternative names */ common_name = crypto_cert_subject_common_name(cert->px509, &common_name_length); alt_names = crypto_cert_subject_alt_name(cert->px509, &alt_names_count, &alt_names_lengths); /* compare against common name */ if (common_name != NULL) { if (strlen(hostname) == common_name_length) { if (memcmp((void*) hostname, (void*) common_name, common_name_length) == 0) hostname_match = true; } } /* compare against alternative names */ if (alt_names != NULL) { for (index = 0; index < alt_names_count; index++) { if (strlen(hostname) == alt_names_lengths[index]) { if (memcmp((void*) hostname, (void*) alt_names[index], alt_names_lengths[index]) == 0) hostname_match = true; } } } /* if the certificate is valid and the certificate name matches, verification succeeds */ if (certificate_status && hostname_match) return true; /* success! */ /* if the certificate is valid but the certificate name does not match, warn user, do not accept */ if (certificate_status && !hostname_match) tls_print_certificate_name_mismatch_error(hostname, common_name, alt_names, alt_names_count); /* verification could not succeed with OpenSSL, use known_hosts file and prompt user for manual verification */ if (!certificate_status) { char* issuer; char* subject; char* fingerprint; boolean accept_certificate = false; boolean verification_status = false; issuer = crypto_cert_issuer(cert->px509); subject = crypto_cert_subject(cert->px509); fingerprint = crypto_cert_fingerprint(cert->px509); /* search for matching entry in known_hosts file */ match = certificate_data_match(tls->certificate_store, certificate_data); if (match == 1) { /* no entry was found in known_hosts file, prompt user for manual verification */ freerdp* instance = (freerdp*) tls->settings->instance; if (!hostname_match) tls_print_certificate_name_mismatch_error(hostname, common_name, alt_names, alt_names_count); if (instance->VerifyCertificate) accept_certificate = instance->VerifyCertificate(instance, subject, issuer, fingerprint); if (!accept_certificate) { /* user did not accept, abort and do not add entry in known_hosts file */ verification_status = false; /* failure! */ } else { /* user accepted certificate, add entry in known_hosts file */ certificate_data_print(tls->certificate_store, certificate_data); verification_status = true; /* success! */ } } else if (match == -1) { /* entry was found in known_hosts file, but fingerprint does not match */ tls_print_certificate_error(hostname, fingerprint); verification_status = false; /* failure! */ } else if (match == 0) { verification_status = true; /* success! */ } xfree(issuer); xfree(subject); xfree(fingerprint); return verification_status; } return false; } void tls_print_certificate_error(char* hostname, char* fingerprint) { printf("The host key for %s has changed\n", hostname); printf("@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@\n"); printf("@ WARNING: REMOTE HOST IDENTIFICATION HAS CHANGED! @\n"); printf("@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@\n"); printf("IT IS POSSIBLE THAT SOMEONE IS DOING SOMETHING NASTY!\n"); printf("Someone could be eavesdropping on you right now (man-in-the-middle attack)!\n"); printf("It is also possible that a host key has just been changed.\n"); printf("The fingerprint for the host key sent by the remote host is\n%s\n", fingerprint); printf("Please contact your system administrator.\n"); printf("Add correct host key in ~/.freerdp/known_hosts to get rid of this message.\n"); printf("Host key for %s has changed and you have requested strict checking.\n", hostname); printf("Host key verification failed.\n"); } void tls_print_certificate_name_mismatch_error(char* hostname, char* common_name, char** alt_names, int alt_names_count) { int index; printf("@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@\n"); printf("@ WARNING: CERTIFICATE NAME MISMATCH! @\n"); printf("@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@\n"); printf("The hostname used for this connection (%s) \n", hostname); if (alt_names_count < 1) { printf("does not match the name given in the certificate:\n"); printf("%s\n", common_name); } else { printf("does not match the names given in the certificate:\n"); printf("%s", common_name); for (index = 0; index < alt_names_count; index++) { printf(", %s", alt_names[index]); } printf("\n"); } printf("A valid certificate for the wrong name should NOT be trusted!\n"); } rdpTls* tls_new(rdpSettings* settings) { rdpTls* tls; tls = (rdpTls*) xzalloc(sizeof(rdpTls)); if (tls != NULL) { SSL_load_error_strings(); SSL_library_init(); tls->settings = settings; tls->certificate_store = certificate_store_new(settings); } return tls; } void tls_free(rdpTls* tls) { if (tls != NULL) { if (tls->ssl) SSL_free(tls->ssl); if (tls->ctx) SSL_CTX_free(tls->ctx); certificate_store_free(tls->certificate_store); xfree(tls); } } FreeRDP-1.0.2/libfreerdp-core/tls.h000066400000000000000000000033771207112532300167660ustar00rootroot00000000000000/** * FreeRDP: A Remote Desktop Protocol Client * Transport Layer Security * * Copyright 2011 Marc-Andre Moreau * * 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. */ #ifndef __TLS_H #define __TLS_H #include "crypto.h" #include "certificate.h" #include #include #include #include typedef struct rdp_tls rdpTls; struct rdp_tls { SSL* ssl; int sockfd; SSL_CTX* ctx; rdpSettings* settings; rdpCertificateStore* certificate_store; }; boolean tls_connect(rdpTls* tls); boolean tls_accept(rdpTls* tls, const char* cert_file, const char* privatekey_file); boolean tls_disconnect(rdpTls* tls); int tls_read(rdpTls* tls, uint8* data, int length); int tls_write(rdpTls* tls, uint8* data, int length); CryptoCert tls_get_certificate(rdpTls* tls); boolean tls_verify_certificate(rdpTls* tls, CryptoCert cert, char* hostname); void tls_print_certificate_error(char* hostname, char* fingerprint); void tls_print_certificate_name_mismatch_error(char* hostname, char* common_name, char** alt_names, int alt_names_count); boolean tls_print_error(char* func, SSL* connection, int value); rdpTls* tls_new(rdpSettings* settings); void tls_free(rdpTls* tls); #endif /* __TLS_H */ FreeRDP-1.0.2/libfreerdp-core/tpdu.c000066400000000000000000000103451207112532300171240ustar00rootroot00000000000000/** * FreeRDP: A Remote Desktop Protocol Client * X.224 Transport Protocol Data Units (TPDUs) * * Copyright 2011 Marc-Andre Moreau * * 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. */ #include #include "tpdu.h" /** * TPDUs are defined in: * * http://www.itu.int/rec/T-REC-X.224-199511-I/ * X.224: Information technology - Open Systems Interconnection - Protocol for providing the connection-mode transport service * * RDP uses only TPDUs of class 0, the "simple class" defined in section 8 of X.224 * * TPDU Header * ____________________ byte * | | * | LI | 1 * |____________________| * | | * | Code | 2 * |____________________| * | | * | | 3 * |_______DST-REF______| * | | * | | 4 * |____________________| * | | * | | 5 * |_______SRC-REF______| * | | * | | 6 * |____________________| * | | * | Class | 7 * |____________________| * | ... | */ /** * Read TPDU header. * @param s stream * @param code variable pointer to receive TPDU code * @return TPDU length indicator (LI) */ uint8 tpdu_read_header(STREAM* s, uint8* code) { uint8 li; stream_read_uint8(s, li); /* LI */ stream_read_uint8(s, *code); /* Code */ if (*code == X224_TPDU_DATA) { /* EOT (1 byte) */ stream_seek(s, 1); } else { /* DST-REF (2 bytes) */ /* SRC-REF (2 bytes) */ /* Class 0 (1 byte) */ stream_seek(s, 5); } return li; } /** * Write TDPU header. * @param s stream * @param length length * @param code TPDU code */ void tpdu_write_header(STREAM* s, uint16 length, uint8 code) { stream_write_uint8(s, length); /* LI */ stream_write_uint8(s, code); /* code */ if (code == X224_TPDU_DATA) { stream_write_uint8(s, 0x80); /* EOT */ } else { stream_write_uint16(s, 0); /* DST-REF */ stream_write_uint16(s, 0); /* SRC-REF */ stream_write_uint8(s, 0); /* Class 0 */ } } /** * Read Connection Request TPDU * @param s stream * @return length indicator (LI) */ uint8 tpdu_read_connection_request(STREAM* s) { uint8 li; uint8 code; li = tpdu_read_header(s, &code); if (code != X224_TPDU_CONNECTION_REQUEST) { printf("Error: expected X224_TPDU_CONNECTION_REQUEST\n"); return 0; } return li; } /** * Write Connection Request TPDU. * @param s stream * @param length TPDU length */ void tpdu_write_connection_request(STREAM* s, uint16 length) { tpdu_write_header(s, length, X224_TPDU_CONNECTION_REQUEST); } /** * Read Connection Confirm TPDU. * @param s stream * @return length indicator (LI) */ uint8 tpdu_read_connection_confirm(STREAM* s) { uint8 li; uint8 code; li = tpdu_read_header(s, &code); if (code != X224_TPDU_CONNECTION_CONFIRM) { printf("Error: expected X224_TPDU_CONNECTION_CONFIRM\n"); return 0; } return li; } /** * Write Connection Confirm TPDU. * @param s stream * @param length TPDU length */ void tpdu_write_connection_confirm(STREAM* s, uint16 length) { tpdu_write_header(s, length, X224_TPDU_CONNECTION_CONFIRM); } /** * Write Disconnect Request TPDU. * @param s stream * @param length TPDU length */ void tpdu_write_disconnect_request(STREAM* s, uint16 length) { tpdu_write_header(s, length, X224_TPDU_DISCONNECT_REQUEST); } /** * Write Data TPDU. * @param s stream */ void tpdu_write_data(STREAM* s) { tpdu_write_header(s, 2, X224_TPDU_DATA); } /** * Read Data TPDU. * @param s stream */ uint16 tpdu_read_data(STREAM* s) { uint8 code; uint16 li; li = tpdu_read_header(s, &code); if (code != X224_TPDU_DATA) return 0; return li; } FreeRDP-1.0.2/libfreerdp-core/tpdu.h000066400000000000000000000037501207112532300171330ustar00rootroot00000000000000/** * FreeRDP: A Remote Desktop Protocol Client * X.224 Transport Protocol Data Units (TPDUs) * * Copyright 2011 Marc-Andre Moreau * * 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. */ #ifndef __TPDU_H #define __TPDU_H #include enum X224_TPDU_TYPE { X224_TPDU_CONNECTION_REQUEST = 0xE0, X224_TPDU_CONNECTION_CONFIRM = 0xD0, X224_TPDU_DISCONNECT_REQUEST = 0x80, X224_TPDU_DATA = 0xF0, X224_TPDU_ERROR = 0x70 }; #define TPDU_DATA_HEADER_LENGTH 3 #define TPDU_CONNECTION_REQUEST_HEADER_LENGTH 7 #define TPDU_CONNECTION_CONFIRM_HEADER_LENGTH 7 #define TPDU_DISCONNECT_REQUEST_HEADER_LENGTH 7 #define TPDU_DATA_LENGTH (TPKT_HEADER_LENGTH + TPDU_DATA_HEADER_LENGTH) #define TPDU_CONNECTION_REQUEST_LENGTH (TPKT_HEADER_LENGTH + TPDU_CONNECTION_REQUEST_HEADER_LENGTH) #define TPDU_CONNECTION_CONFIRM_LENGTH (TPKT_HEADER_LENGTH + TPDU_CONNECTION_CONFIRM_HEADER_LENGTH) #define TPDU_DISCONNECT_REQUEST_LENGTH (TPKT_HEADER_LENGTH + TPDU_DISCONNECT_REQUEST_HEADER_LENGTH) uint8 tpdu_read_header(STREAM* s, uint8* code); void tpdu_write_header(STREAM* s, uint16 length, uint8 code); uint8 tpdu_read_connection_request(STREAM* s); void tpdu_write_connection_request(STREAM* s, uint16 length); uint8 tpdu_read_connection_confirm(STREAM* s); void tpdu_write_connection_confirm(STREAM* s, uint16 length); void tpdu_write_disconnect_request(STREAM* s, uint16 length); uint16 tpdu_read_data(STREAM* s); void tpdu_write_data(STREAM* s); #endif /* __TPDU_H */ FreeRDP-1.0.2/libfreerdp-core/tpkt.c000066400000000000000000000050041207112532300171260ustar00rootroot00000000000000/** * FreeRDP: A Remote Desktop Protocol Client * Transport Packets (TPKTs) * * Copyright 2011 Marc-Andre Moreau * * 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. */ #include "tpdu.h" #include "tpkt.h" /** * TPKTs are defined in: * * http://tools.ietf.org/html/rfc1006/ * RFC 1006 - ISO Transport Service on top of the TCP * * http://www.itu.int/rec/T-REC-T.123/ * ITU-T T.123 (01/2007) - Network-specific data protocol stacks for multimedia conferencing * * TPKT Header * ____________________ byte * | | * | 3 (version) | 1 * |____________________| * | | * | Reserved | 2 * |____________________| * | | * | Length (MSB) | 3 * |____________________| * | | * | Length (LSB) | 4 * |____________________| * | | * | X.224 TPDU | 5 - ? * .... * * A TPKT header is of fixed length 4, and the following X.224 TPDU is at least three bytes long. * Therefore, the minimum TPKT length is 7, and the maximum TPKT length is 65535. Because the TPKT * length includes the TPKT header (4 bytes), the maximum X.224 TPDU length is 65531. */ /** * Verify if a packet has valid TPKT header.\n * @param s * @return boolean */ boolean tpkt_verify_header(STREAM* s) { uint8 version; stream_peek_uint8(s, version); if (version == 3) return true; else return false; } /** * Read a TPKT header.\n * @param s * @return length */ uint16 tpkt_read_header(STREAM* s) { uint8 version; uint16 length; stream_peek_uint8(s, version); if (version == 3) { stream_seek(s, 2); stream_read_uint16_be(s, length); } else { /* not a TPKT header */ length = 0; } return length; } /** * Write a TPKT header.\n * @param s * @param length */ void tpkt_write_header(STREAM* s, uint16 length) { stream_write_uint8(s, 3); /* version */ stream_write_uint8(s, 0); /* reserved */ stream_write_uint16_be(s, length); /* length */ } FreeRDP-1.0.2/libfreerdp-core/tpkt.h000066400000000000000000000017471207112532300171450ustar00rootroot00000000000000/** * FreeRDP: A Remote Desktop Protocol Client * Transport Packets (TPKTs) * * Copyright 2011 Marc-Andre Moreau * * 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. */ #ifndef __TPKT_H #define __TPKT_H #include "tpdu.h" #include "transport.h" #include #define TPKT_HEADER_LENGTH 4 boolean tpkt_verify_header(STREAM* s); uint16 tpkt_read_header(STREAM* s); void tpkt_write_header(STREAM* s, uint16 length); #endif /* __TPKT_H */ FreeRDP-1.0.2/libfreerdp-core/transport.c000066400000000000000000000232101207112532300201770ustar00rootroot00000000000000/** * FreeRDP: A Remote Desktop Protocol Client * Network Transport Layer * * Copyright 2011 Vic Lee * * 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. */ #include "config.h" #include #include #include #include #include #include #include #include #include #include #ifndef _WIN32 #include #include #endif #include "tpkt.h" #include "fastpath.h" #include "credssp.h" #include "transport.h" #define BUFFER_SIZE 16384 STREAM* transport_recv_stream_init(rdpTransport* transport, int size) { STREAM* s = transport->recv_stream; stream_check_size(s, size); stream_set_pos(s, 0); return s; } STREAM* transport_send_stream_init(rdpTransport* transport, int size) { STREAM* s = transport->send_stream; stream_check_size(s, size); stream_set_pos(s, 0); return s; } boolean transport_connect(rdpTransport* transport, const char* hostname, uint16 port) { return tcp_connect(transport->tcp, hostname, port); } void transport_attach(rdpTransport* transport, int sockfd) { transport->tcp->sockfd = sockfd; } boolean transport_disconnect(rdpTransport* transport) { if (transport->layer == TRANSPORT_LAYER_TLS) tls_disconnect(transport->tls); return tcp_disconnect(transport->tcp); } boolean transport_connect_rdp(rdpTransport* transport) { /* RDP encryption */ return true; } boolean transport_connect_tls(rdpTransport* transport) { if (transport->tls == NULL) transport->tls = tls_new(transport->settings); transport->layer = TRANSPORT_LAYER_TLS; transport->tls->sockfd = transport->tcp->sockfd; if (tls_connect(transport->tls) != true) return false; return true; } boolean transport_connect_nla(rdpTransport* transport) { if (transport->tls == NULL) transport->tls = tls_new(transport->settings); transport->layer = TRANSPORT_LAYER_TLS; transport->tls->sockfd = transport->tcp->sockfd; if (tls_connect(transport->tls) != true) return false; /* Network Level Authentication */ if (transport->settings->authentication != true) return true; if (transport->credssp == NULL) transport->credssp = credssp_new(transport); if (credssp_authenticate(transport->credssp) < 0) { printf("Authentication failure, check credentials.\n" "If credentials are valid, the NTLMSSP implementation may be to blame.\n"); credssp_free(transport->credssp); return false; } credssp_free(transport->credssp); return true; } boolean transport_accept_rdp(rdpTransport* transport) { /* RDP encryption */ return true; } boolean transport_accept_tls(rdpTransport* transport) { if (transport->tls == NULL) transport->tls = tls_new(transport->settings); transport->layer = TRANSPORT_LAYER_TLS; transport->tls->sockfd = transport->tcp->sockfd; if (tls_accept(transport->tls, transport->settings->cert_file, transport->settings->privatekey_file) != true) return false; return true; } boolean transport_accept_nla(rdpTransport* transport) { if (transport->tls == NULL) transport->tls = tls_new(transport->settings); transport->layer = TRANSPORT_LAYER_TLS; transport->tls->sockfd = transport->tcp->sockfd; if (tls_accept(transport->tls, transport->settings->cert_file, transport->settings->privatekey_file) != true) return false; /* Network Level Authentication */ if (transport->settings->authentication != true) return true; /* Blocking here until NLA is complete */ return true; } int transport_read(rdpTransport* transport, STREAM* s) { int status = -1; while (true) { if (transport->layer == TRANSPORT_LAYER_TLS) status = tls_read(transport->tls, stream_get_tail(s), stream_get_left(s)); else if (transport->layer == TRANSPORT_LAYER_TCP) status = tcp_read(transport->tcp, stream_get_tail(s), stream_get_left(s)); if (status == 0 && transport->blocking) { freerdp_usleep(transport->usleep_interval); continue; } break; } #ifdef WITH_DEBUG_TRANSPORT if (status > 0) { printf("Local < Remote\n"); freerdp_hexdump(s->data, status); } #endif return status; } static int transport_read_nonblocking(rdpTransport* transport) { int status; stream_check_size(transport->recv_buffer, 4096); status = transport_read(transport, transport->recv_buffer); if (status <= 0) return status; stream_seek(transport->recv_buffer, status); return status; } int transport_write(rdpTransport* transport, STREAM* s) { int status = -1; int length; length = stream_get_length(s); stream_set_pos(s, 0); #ifdef WITH_DEBUG_TRANSPORT if (length > 0) { printf("Local > Remote\n"); freerdp_hexdump(s->data, length); } #endif while (length > 0) { if (transport->layer == TRANSPORT_LAYER_TLS) status = tls_write(transport->tls, stream_get_tail(s), length); else if (transport->layer == TRANSPORT_LAYER_TCP) status = tcp_write(transport->tcp, stream_get_tail(s), length); if (status < 0) break; /* error occurred */ if (status == 0) { /* blocking while sending */ freerdp_usleep(transport->usleep_interval); /* when sending is blocked in nonblocking mode, the receiving buffer should be checked */ if (!transport->blocking) { /* and in case we do have buffered some data, we set the event so next loop will get it */ if (transport_read_nonblocking(transport) > 0) wait_obj_set(transport->recv_event); } } length -= status; stream_seek(s, status); } if (status < 0) { /* A write error indicates that the peer has dropped the connection */ transport->layer = TRANSPORT_LAYER_CLOSED; } return status; } void transport_get_fds(rdpTransport* transport, void** rfds, int* rcount) { rfds[*rcount] = (void*)(long)(transport->tcp->sockfd); (*rcount)++; wait_obj_get_fds(transport->recv_event, rfds, rcount); } int transport_check_fds(rdpTransport** ptransport) { int pos; int status; uint16 length; STREAM* received; rdpTransport* transport = *ptransport; wait_obj_clear(transport->recv_event); status = transport_read_nonblocking(transport); if (status < 0) return status; while ((pos = stream_get_pos(transport->recv_buffer)) > 0) { stream_set_pos(transport->recv_buffer, 0); if (tpkt_verify_header(transport->recv_buffer)) /* TPKT */ { /* Ensure the TPKT header is available. */ if (pos <= 4) { stream_set_pos(transport->recv_buffer, pos); return 0; } length = tpkt_read_header(transport->recv_buffer); } else /* Fast Path */ { /* Ensure the Fast Path header is available. */ if (pos <= 2) { stream_set_pos(transport->recv_buffer, pos); return 0; } /* Fastpath header can be two or three bytes long. */ length = fastpath_header_length(transport->recv_buffer); if (pos < length) { stream_set_pos(transport->recv_buffer, pos); return 0; } length = fastpath_read_header(NULL, transport->recv_buffer); } if (length == 0) { printf("transport_check_fds: protocol error, not a TPKT or Fast Path header.\n"); freerdp_hexdump(stream_get_head(transport->recv_buffer), pos); return -1; } if (pos < length) { stream_set_pos(transport->recv_buffer, pos); return 0; /* Packet is not yet completely received. */ } /* * A complete packet has been received. In case there are trailing data * for the next packet, we copy it to the new receive buffer. */ received = transport->recv_buffer; transport->recv_buffer = stream_new(BUFFER_SIZE); if (pos > length) { stream_set_pos(received, length); stream_check_size(transport->recv_buffer, pos - length); stream_copy(transport->recv_buffer, received, pos - length); } stream_set_pos(received, length); stream_seal(received); stream_set_pos(received, 0); if (transport->recv_callback(transport, received, transport->recv_extra) == false) status = -1; stream_free(received); if (status < 0) return status; /* transport might now have been freed by rdp_client_redirect and a new rdp->transport created */ transport = *ptransport; } return 0; } boolean transport_set_blocking_mode(rdpTransport* transport, boolean blocking) { transport->blocking = blocking; return tcp_set_blocking_mode(transport->tcp, blocking); } rdpTransport* transport_new(rdpSettings* settings) { rdpTransport* transport; transport = (rdpTransport*) xzalloc(sizeof(rdpTransport)); if (transport != NULL) { transport->tcp = tcp_new(settings); transport->settings = settings; /* a small 0.1ms delay when transport is blocking. */ transport->usleep_interval = 100; /* receive buffer for non-blocking read. */ transport->recv_buffer = stream_new(BUFFER_SIZE); transport->recv_event = wait_obj_new(); /* buffers for blocking read/write */ transport->recv_stream = stream_new(BUFFER_SIZE); transport->send_stream = stream_new(BUFFER_SIZE); transport->blocking = true; transport->layer = TRANSPORT_LAYER_TCP; } return transport; } void transport_free(rdpTransport* transport) { if (transport != NULL) { stream_free(transport->recv_buffer); stream_free(transport->recv_stream); stream_free(transport->send_stream); wait_obj_free(transport->recv_event); if (transport->tls) tls_free(transport->tls); tcp_free(transport->tcp); xfree(transport); } } FreeRDP-1.0.2/libfreerdp-core/transport.h000066400000000000000000000050511207112532300202070ustar00rootroot00000000000000/** * FreeRDP: A Remote Desktop Protocol Client * Network Transport Layer * * Copyright 2011 Vic Lee * * 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. */ #ifndef __TRANSPORT_H #define __TRANSPORT_H typedef enum { TRANSPORT_LAYER_TCP, TRANSPORT_LAYER_TLS, TRANSPORT_LAYER_CLOSED } TRANSPORT_LAYER; typedef struct rdp_transport rdpTransport; #include "tcp.h" #include "tls.h" #include "credssp.h" #include #include #include #include #include typedef boolean (*TransportRecv) (rdpTransport* transport, STREAM* stream, void* extra); struct rdp_transport { STREAM* recv_stream; STREAM* send_stream; TRANSPORT_LAYER layer; struct rdp_tcp* tcp; struct rdp_tls* tls; struct rdp_settings* settings; struct rdp_credssp* credssp; uint32 usleep_interval; void* recv_extra; STREAM* recv_buffer; TransportRecv recv_callback; struct wait_obj* recv_event; boolean blocking; }; STREAM* transport_recv_stream_init(rdpTransport* transport, int size); STREAM* transport_send_stream_init(rdpTransport* transport, int size); boolean transport_connect(rdpTransport* transport, const char* hostname, uint16 port); void transport_attach(rdpTransport* transport, int sockfd); boolean transport_disconnect(rdpTransport* transport); boolean transport_connect_rdp(rdpTransport* transport); boolean transport_connect_tls(rdpTransport* transport); boolean transport_connect_nla(rdpTransport* transport); boolean transport_accept_rdp(rdpTransport* transport); boolean transport_accept_tls(rdpTransport* transport); boolean transport_accept_nla(rdpTransport* transport); int transport_read(rdpTransport* transport, STREAM* s); int transport_write(rdpTransport* transport, STREAM* s); void transport_get_fds(rdpTransport* transport, void** rfds, int* rcount); int transport_check_fds(rdpTransport** ptransport); boolean transport_set_blocking_mode(rdpTransport* transport, boolean blocking); rdpTransport* transport_new(rdpSettings* settings); void transport_free(rdpTransport* transport); #endif FreeRDP-1.0.2/libfreerdp-core/update.c000066400000000000000000000444671207112532300174460ustar00rootroot00000000000000/** * FreeRDP: A Remote Desktop Protocol Client * Update Data PDUs * * Copyright 2011 Marc-Andre Moreau * * 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. */ #include "update.h" #include "surface.h" #include #include /* static const char* const UPDATE_TYPE_STRINGS[] = { "Orders", "Bitmap", "Palette", "Synchronize" }; */ void update_recv_orders(rdpUpdate* update, STREAM* s) { uint16 numberOrders; stream_seek_uint16(s); /* pad2OctetsA (2 bytes) */ stream_read_uint16(s, numberOrders); /* numberOrders (2 bytes) */ stream_seek_uint16(s); /* pad2OctetsB (2 bytes) */ while (numberOrders > 0) { update_recv_order(update, s); numberOrders--; } } void update_read_bitmap_data(STREAM* s, BITMAP_DATA* bitmap_data) { stream_read_uint16(s, bitmap_data->destLeft); stream_read_uint16(s, bitmap_data->destTop); stream_read_uint16(s, bitmap_data->destRight); stream_read_uint16(s, bitmap_data->destBottom); stream_read_uint16(s, bitmap_data->width); stream_read_uint16(s, bitmap_data->height); stream_read_uint16(s, bitmap_data->bitsPerPixel); stream_read_uint16(s, bitmap_data->flags); stream_read_uint16(s, bitmap_data->bitmapLength); if (bitmap_data->flags & BITMAP_COMPRESSION) { if (!(bitmap_data->flags & NO_BITMAP_COMPRESSION_HDR)) { stream_read_uint16(s, bitmap_data->cbCompFirstRowSize); /* cbCompFirstRowSize (2 bytes) */ stream_read_uint16(s, bitmap_data->cbCompMainBodySize); /* cbCompMainBodySize (2 bytes) */ stream_read_uint16(s, bitmap_data->cbScanWidth); /* cbScanWidth (2 bytes) */ stream_read_uint16(s, bitmap_data->cbUncompressedSize); /* cbUncompressedSize (2 bytes) */ bitmap_data->bitmapLength = bitmap_data->cbCompMainBodySize; } bitmap_data->compressed = true; stream_get_mark(s, bitmap_data->bitmapDataStream); stream_seek(s, bitmap_data->bitmapLength); } else { bitmap_data->compressed = false; stream_get_mark(s, bitmap_data->bitmapDataStream); stream_seek(s, bitmap_data->bitmapLength); } } void update_read_bitmap(rdpUpdate* update, STREAM* s, BITMAP_UPDATE* bitmap_update) { int i; stream_read_uint16(s, bitmap_update->number); /* numberRectangles (2 bytes) */ if (bitmap_update->number > bitmap_update->count) { uint16 count; count = bitmap_update->number * 2; bitmap_update->rectangles = (BITMAP_DATA*) xrealloc(bitmap_update->rectangles, sizeof(BITMAP_DATA) * count); memset(&bitmap_update->rectangles[bitmap_update->count], 0, sizeof(BITMAP_DATA) * (count - bitmap_update->count)); bitmap_update->count = count; } /* rectangles */ for (i = 0; i < (int) bitmap_update->number; i++) { update_read_bitmap_data(s, &bitmap_update->rectangles[i]); } } void update_read_palette(rdpUpdate* update, STREAM* s, PALETTE_UPDATE* palette_update) { int i; PALETTE_ENTRY* entry; stream_seek_uint16(s); /* pad2Octets (2 bytes) */ stream_read_uint32(s, palette_update->number); /* numberColors (4 bytes), must be set to 256 */ if (palette_update->number > 256) palette_update->number = 256; /* paletteEntries */ for (i = 0; i < (int) palette_update->number; i++) { entry = &palette_update->entries[i]; stream_read_uint8(s, entry->blue); stream_read_uint8(s, entry->green); stream_read_uint8(s, entry->red); } } void update_read_synchronize(rdpUpdate* update, STREAM* s) { stream_seek_uint16(s); /* pad2Octets (2 bytes) */ /** * The Synchronize Update is an artifact from the * T.128 protocol and should be ignored. */ } void update_read_play_sound(STREAM* s, PLAY_SOUND_UPDATE* play_sound) { stream_read_uint32(s, play_sound->duration); /* duration (4 bytes) */ stream_read_uint32(s, play_sound->frequency); /* frequency (4 bytes) */ } void update_recv_play_sound(rdpUpdate* update, STREAM* s) { update_read_play_sound(s, &update->play_sound); IFCALL(update->PlaySound, update->context, &update->play_sound); } void update_read_pointer_position(STREAM* s, POINTER_POSITION_UPDATE* pointer_position) { stream_read_uint16(s, pointer_position->xPos); /* xPos (2 bytes) */ stream_read_uint16(s, pointer_position->yPos); /* yPos (2 bytes) */ } void update_read_pointer_system(STREAM* s, POINTER_SYSTEM_UPDATE* pointer_system) { stream_read_uint32(s, pointer_system->type); /* systemPointerType (4 bytes) */ } void update_read_pointer_color(STREAM* s, POINTER_COLOR_UPDATE* pointer_color) { stream_read_uint16(s, pointer_color->cacheIndex); /* cacheIndex (2 bytes) */ stream_read_uint16(s, pointer_color->xPos); /* xPos (2 bytes) */ stream_read_uint16(s, pointer_color->yPos); /* yPos (2 bytes) */ stream_read_uint16(s, pointer_color->width); /* width (2 bytes) */ stream_read_uint16(s, pointer_color->height); /* height (2 bytes) */ stream_read_uint16(s, pointer_color->lengthAndMask); /* lengthAndMask (2 bytes) */ stream_read_uint16(s, pointer_color->lengthXorMask); /* lengthXorMask (2 bytes) */ /** * There does not seem to be any documentation on why * xPos / yPos can be larger than width / height * so it is missing in documentation or a bug in implementation * 2.2.9.1.1.4.4 Color Pointer Update (TS_COLORPOINTERATTRIBUTE) */ if (pointer_color->xPos >= pointer_color->width) pointer_color->xPos = 0; if (pointer_color->yPos >= pointer_color->height) pointer_color->yPos = 0; if (pointer_color->lengthXorMask > 0) { pointer_color->xorMaskData = (uint8*) xmalloc(pointer_color->lengthXorMask); stream_read(s, pointer_color->xorMaskData, pointer_color->lengthXorMask); } if (pointer_color->lengthAndMask > 0) { pointer_color->andMaskData = (uint8*) xmalloc(pointer_color->lengthAndMask); stream_read(s, pointer_color->andMaskData, pointer_color->lengthAndMask); } if (stream_get_left(s) > 0) stream_seek_uint8(s); /* pad (1 byte) */ } void update_read_pointer_new(STREAM* s, POINTER_NEW_UPDATE* pointer_new) { stream_read_uint16(s, pointer_new->xorBpp); /* xorBpp (2 bytes) */ update_read_pointer_color(s, &pointer_new->colorPtrAttr); /* colorPtrAttr */ } void update_read_pointer_cached(STREAM* s, POINTER_CACHED_UPDATE* pointer_cached) { stream_read_uint16(s, pointer_cached->cacheIndex); /* cacheIndex (2 bytes) */ } void update_recv_pointer(rdpUpdate* update, STREAM* s) { uint16 messageType; rdpContext* context = update->context; rdpPointerUpdate* pointer = update->pointer; stream_read_uint16(s, messageType); /* messageType (2 bytes) */ stream_seek_uint16(s); /* pad2Octets (2 bytes) */ switch (messageType) { case PTR_MSG_TYPE_POSITION: update_read_pointer_position(s, &pointer->pointer_position); IFCALL(pointer->PointerPosition, context, &pointer->pointer_position); break; case PTR_MSG_TYPE_SYSTEM: update_read_pointer_system(s, &pointer->pointer_system); IFCALL(pointer->PointerSystem, context, &pointer->pointer_system); break; case PTR_MSG_TYPE_COLOR: update_read_pointer_color(s, &pointer->pointer_color); IFCALL(pointer->PointerColor, context, &pointer->pointer_color); break; case PTR_MSG_TYPE_POINTER: update_read_pointer_new(s, &pointer->pointer_new); IFCALL(pointer->PointerNew, context, &pointer->pointer_new); break; case PTR_MSG_TYPE_CACHED: update_read_pointer_cached(s, &pointer->pointer_cached); IFCALL(pointer->PointerCached, context, &pointer->pointer_cached); break; default: break; } } void update_recv(rdpUpdate* update, STREAM* s) { uint16 updateType; rdpContext* context = update->context; stream_read_uint16(s, updateType); /* updateType (2 bytes) */ //printf("%s Update Data PDU\n", UPDATE_TYPE_STRINGS[updateType]); IFCALL(update->BeginPaint, context); switch (updateType) { case UPDATE_TYPE_ORDERS: update_recv_orders(update, s); break; case UPDATE_TYPE_BITMAP: update_read_bitmap(update, s, &update->bitmap_update); IFCALL(update->BitmapUpdate, context, &update->bitmap_update); break; case UPDATE_TYPE_PALETTE: update_read_palette(update, s, &update->palette_update); IFCALL(update->Palette, context, &update->palette_update); break; case UPDATE_TYPE_SYNCHRONIZE: update_read_synchronize(update, s); IFCALL(update->Synchronize, context); break; } IFCALL(update->EndPaint, context); if (stream_get_left(s) > RDP_SHARE_DATA_HEADER_LENGTH) { uint16 pduType; uint16 length; uint16 source; rdp_read_share_control_header(s, &length, &pduType, &source); if (pduType != PDU_TYPE_DATA) return; rdp_recv_data_pdu(update->context->rdp, s); } } void update_reset_state(rdpUpdate* update) { rdpPrimaryUpdate* primary = update->primary; rdpAltSecUpdate* altsec = update->altsec; memset(&primary->order_info, 0, sizeof(ORDER_INFO)); memset(&primary->dstblt, 0, sizeof(DSTBLT_ORDER)); memset(&primary->patblt, 0, sizeof(PATBLT_ORDER)); memset(&primary->scrblt, 0, sizeof(SCRBLT_ORDER)); memset(&primary->opaque_rect, 0, sizeof(OPAQUE_RECT_ORDER)); memset(&primary->draw_nine_grid, 0, sizeof(DRAW_NINE_GRID_ORDER)); memset(&primary->multi_dstblt, 0, sizeof(MULTI_DSTBLT_ORDER)); memset(&primary->multi_patblt, 0, sizeof(MULTI_PATBLT_ORDER)); memset(&primary->multi_scrblt, 0, sizeof(MULTI_SCRBLT_ORDER)); memset(&primary->multi_opaque_rect, 0, sizeof(MULTI_OPAQUE_RECT_ORDER)); memset(&primary->multi_draw_nine_grid, 0, sizeof(MULTI_DRAW_NINE_GRID_ORDER)); memset(&primary->line_to, 0, sizeof(LINE_TO_ORDER)); memset(&primary->polyline, 0, sizeof(POLYLINE_ORDER)); memset(&primary->memblt, 0, sizeof(MEMBLT_ORDER)); memset(&primary->mem3blt, 0, sizeof(MEM3BLT_ORDER)); memset(&primary->save_bitmap, 0, sizeof(SAVE_BITMAP_ORDER)); memset(&primary->glyph_index, 0, sizeof(GLYPH_INDEX_ORDER)); memset(&primary->fast_index, 0, sizeof(FAST_INDEX_ORDER)); memset(&primary->fast_glyph, 0, sizeof(FAST_GLYPH_ORDER)); memset(&primary->polygon_sc, 0, sizeof(POLYGON_SC_ORDER)); memset(&primary->polygon_cb, 0, sizeof(POLYGON_CB_ORDER)); memset(&primary->ellipse_sc, 0, sizeof(ELLIPSE_SC_ORDER)); memset(&primary->ellipse_cb, 0, sizeof(ELLIPSE_CB_ORDER)); primary->order_info.orderType = ORDER_TYPE_PATBLT; altsec->switch_surface.bitmapId = SCREEN_BITMAP_SURFACE; IFCALL(altsec->SwitchSurface, update->context, &(altsec->switch_surface)); } static void update_begin_paint(rdpContext* context) { } static void update_end_paint(rdpContext* context) { } static void update_write_refresh_rect(STREAM* s, uint8 count, RECTANGLE_16* areas) { int i; stream_write_uint8(s, count); /* numberOfAreas (1 byte) */ stream_seek(s, 3); /* pad3Octets (3 bytes) */ for (i = 0; i < count; i++) freerdp_write_rectangle_16(s, &areas[i]); } static void update_send_refresh_rect(rdpContext* context, uint8 count, RECTANGLE_16* areas) { STREAM* s; rdpRdp* rdp = context->rdp; s = rdp_data_pdu_init(rdp); update_write_refresh_rect(s, count, areas); rdp_send_data_pdu(rdp, s, DATA_PDU_TYPE_REFRESH_RECT, rdp->mcs->user_id); } static void update_write_suppress_output(STREAM* s, uint8 allow, RECTANGLE_16* area) { stream_write_uint8(s, allow); /* allowDisplayUpdates (1 byte) */ stream_seek(s, 3); /* pad3Octets (3 bytes) */ if (allow > 0) freerdp_write_rectangle_16(s, area); } static void update_send_suppress_output(rdpContext* context, uint8 allow, RECTANGLE_16* area) { STREAM* s; rdpRdp* rdp = context->rdp; s = rdp_data_pdu_init(rdp); update_write_suppress_output(s, allow, area); rdp_send_data_pdu(rdp, s, DATA_PDU_TYPE_SUPPRESS_OUTPUT, rdp->mcs->user_id); } static void update_send_surface_command(rdpContext* context, STREAM* s) { STREAM* update; rdpRdp* rdp = context->rdp; update = fastpath_update_pdu_init(rdp->fastpath); stream_check_size(update, stream_get_length(s)); stream_write(update, stream_get_head(s), stream_get_length(s)); fastpath_send_update_pdu(rdp->fastpath, FASTPATH_UPDATETYPE_SURFCMDS, update); } static void update_send_surface_bits(rdpContext* context, SURFACE_BITS_COMMAND* surface_bits_command) { STREAM* s; rdpRdp* rdp = context->rdp; s = fastpath_update_pdu_init(rdp->fastpath); stream_check_size(s, SURFCMD_SURFACE_BITS_HEADER_LENGTH + (int) surface_bits_command->bitmapDataLength); update_write_surfcmd_surface_bits_header(s, surface_bits_command); stream_write(s, surface_bits_command->bitmapData, surface_bits_command->bitmapDataLength); fastpath_send_update_pdu(rdp->fastpath, FASTPATH_UPDATETYPE_SURFCMDS, s); } static void update_send_surface_frame_marker(rdpContext* context, SURFACE_FRAME_MARKER* surface_frame_marker) { STREAM* s; rdpRdp* rdp = context->rdp; s = fastpath_update_pdu_init(rdp->fastpath); update_write_surfcmd_frame_marker(s, surface_frame_marker->frameAction, surface_frame_marker->frameId); fastpath_send_update_pdu(rdp->fastpath, FASTPATH_UPDATETYPE_SURFCMDS, s); } static void update_send_synchronize(rdpContext* context) { STREAM* s; rdpRdp* rdp = context->rdp; s = fastpath_update_pdu_init(rdp->fastpath); stream_write_zero(s, 2); /* pad2Octets (2 bytes) */ fastpath_send_update_pdu(rdp->fastpath, FASTPATH_UPDATETYPE_SYNCHRONIZE, s); } static void update_send_desktop_resize(rdpContext* context) { rdp_server_reactivate(context->rdp); } static void update_send_scrblt(rdpContext* context, SCRBLT_ORDER* scrblt) { STREAM* s; rdpRdp* rdp = context->rdp; s = fastpath_update_pdu_init(rdp->fastpath); stream_write_uint16(s, 1); /* numberOrders (2 bytes) */ stream_write_uint8(s, ORDER_STANDARD | ORDER_TYPE_CHANGE); /* controlFlags (1 byte) */ stream_write_uint8(s, ORDER_TYPE_SCRBLT); /* orderType (1 byte) */ stream_write_uint8(s, 0x7F); /* fieldFlags (variable) */ stream_write_uint16(s, scrblt->nLeftRect); stream_write_uint16(s, scrblt->nTopRect); stream_write_uint16(s, scrblt->nWidth); stream_write_uint16(s, scrblt->nHeight); stream_write_uint8(s, scrblt->bRop); stream_write_uint16(s, scrblt->nXSrc); stream_write_uint16(s, scrblt->nYSrc); fastpath_send_update_pdu(rdp->fastpath, FASTPATH_UPDATETYPE_ORDERS, s); } static void update_send_pointer_system(rdpContext* context, POINTER_SYSTEM_UPDATE* pointer_system) { STREAM* s; uint8 updateCode; rdpRdp* rdp = context->rdp; s = fastpath_update_pdu_init(rdp->fastpath); if (pointer_system->type == SYSPTR_NULL) updateCode = FASTPATH_UPDATETYPE_PTR_NULL; else updateCode = FASTPATH_UPDATETYPE_PTR_DEFAULT; fastpath_send_update_pdu(rdp->fastpath, updateCode, s); } static void update_write_pointer_color(STREAM* s, POINTER_COLOR_UPDATE* pointer_color) { stream_check_size(s, 15 + (int) pointer_color->lengthAndMask + (int) pointer_color->lengthXorMask); stream_write_uint16(s, pointer_color->cacheIndex); stream_write_uint16(s, pointer_color->xPos); stream_write_uint16(s, pointer_color->yPos); stream_write_uint16(s, pointer_color->width); stream_write_uint16(s, pointer_color->height); stream_write_uint16(s, pointer_color->lengthAndMask); stream_write_uint16(s, pointer_color->lengthXorMask); if (pointer_color->lengthXorMask > 0) stream_write(s, pointer_color->xorMaskData, pointer_color->lengthXorMask); if (pointer_color->lengthAndMask > 0) stream_write(s, pointer_color->andMaskData, pointer_color->lengthAndMask); stream_write_uint8(s, 0); /* pad (1 byte) */ } static void update_send_pointer_color(rdpContext* context, POINTER_COLOR_UPDATE* pointer_color) { STREAM* s; rdpRdp* rdp = context->rdp; s = fastpath_update_pdu_init(rdp->fastpath); update_write_pointer_color(s, pointer_color); fastpath_send_update_pdu(rdp->fastpath, FASTPATH_UPDATETYPE_COLOR, s); } static void update_send_pointer_new(rdpContext* context, POINTER_NEW_UPDATE* pointer_new) { STREAM* s; rdpRdp* rdp = context->rdp; s = fastpath_update_pdu_init(rdp->fastpath); stream_write_uint16(s, pointer_new->xorBpp); /* xorBpp (2 bytes) */ update_write_pointer_color(s, &pointer_new->colorPtrAttr); fastpath_send_update_pdu(rdp->fastpath, FASTPATH_UPDATETYPE_POINTER, s); } static void update_send_pointer_cached(rdpContext* context, POINTER_CACHED_UPDATE* pointer_cached) { STREAM* s; rdpRdp* rdp = context->rdp; s = fastpath_update_pdu_init(rdp->fastpath); stream_write_uint16(s, pointer_cached->cacheIndex); /* cacheIndex (2 bytes) */ fastpath_send_update_pdu(rdp->fastpath, FASTPATH_UPDATETYPE_CACHED, s); } void update_register_server_callbacks(rdpUpdate* update) { update->BeginPaint = update_begin_paint; update->EndPaint = update_end_paint; update->Synchronize = update_send_synchronize; update->DesktopResize = update_send_desktop_resize; update->RefreshRect = update_send_refresh_rect; update->SuppressOutput = update_send_suppress_output; update->SurfaceBits = update_send_surface_bits; update->SurfaceFrameMarker = update_send_surface_frame_marker; update->SurfaceCommand = update_send_surface_command; update->primary->ScrBlt = update_send_scrblt; update->pointer->PointerSystem = update_send_pointer_system; update->pointer->PointerColor = update_send_pointer_color; update->pointer->PointerNew = update_send_pointer_new; update->pointer->PointerCached = update_send_pointer_cached; } rdpUpdate* update_new(rdpRdp* rdp) { rdpUpdate* update; update = (rdpUpdate*) xzalloc(sizeof(rdpUpdate)); if (update != NULL) { OFFSCREEN_DELETE_LIST* deleteList; update->bitmap_update.count = 64; update->bitmap_update.rectangles = (BITMAP_DATA*) xzalloc(sizeof(BITMAP_DATA) * update->bitmap_update.count); update->pointer = xnew(rdpPointerUpdate); update->primary = xnew(rdpPrimaryUpdate); update->secondary = xnew(rdpSecondaryUpdate); update->altsec = xnew(rdpAltSecUpdate); update->window = xnew(rdpWindowUpdate); deleteList = &(update->altsec->create_offscreen_bitmap.deleteList); deleteList->sIndices = 64; deleteList->indices = xmalloc(deleteList->sIndices * 2); deleteList->cIndices = 0; update->SuppressOutput = update_send_suppress_output; } return update; } void update_free(rdpUpdate* update) { if (update != NULL) { OFFSCREEN_DELETE_LIST* deleteList; deleteList = &(update->altsec->create_offscreen_bitmap.deleteList); xfree(deleteList->indices); xfree(update->bitmap_update.rectangles); xfree(update->pointer); xfree(update->primary); xfree(update->secondary); xfree(update->altsec); xfree(update->window); xfree(update); } } FreeRDP-1.0.2/libfreerdp-core/update.h000066400000000000000000000041121207112532300174320ustar00rootroot00000000000000/** * FreeRDP: A Remote Desktop Protocol Client * Update Data PDUs * * Copyright 2011 Marc-Andre Moreau * * 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. */ #ifndef __UPDATE_H #define __UPDATE_H #include "rdp.h" #include "orders.h" #include #include #include #include #define UPDATE_TYPE_ORDERS 0x0000 #define UPDATE_TYPE_BITMAP 0x0001 #define UPDATE_TYPE_PALETTE 0x0002 #define UPDATE_TYPE_SYNCHRONIZE 0x0003 #define BITMAP_COMPRESSION 0x0001 #define NO_BITMAP_COMPRESSION_HDR 0x0400 rdpUpdate* update_new(rdpRdp* rdp); void update_free(rdpUpdate* update); void update_free_bitmap(BITMAP_UPDATE* bitmap_update); void update_reset_state(rdpUpdate* update); void update_read_bitmap(rdpUpdate* update, STREAM* s, BITMAP_UPDATE* bitmap_update); void update_read_palette(rdpUpdate* update, STREAM* s, PALETTE_UPDATE* palette_update); void update_recv_play_sound(rdpUpdate* update, STREAM* s); void update_recv_pointer(rdpUpdate* update, STREAM* s); void update_recv(rdpUpdate* update, STREAM* s); void update_read_pointer_position(STREAM* s, POINTER_POSITION_UPDATE* pointer_position); void update_read_pointer_system(STREAM* s, POINTER_SYSTEM_UPDATE* pointer_system); void update_read_pointer_color(STREAM* s, POINTER_COLOR_UPDATE* pointer_color); void update_read_pointer_new(STREAM* s, POINTER_NEW_UPDATE* pointer_new); void update_read_pointer_cached(STREAM* s, POINTER_CACHED_UPDATE* pointer_cached); void update_register_server_callbacks(rdpUpdate* update); #endif /* __UPDATE_H */ FreeRDP-1.0.2/libfreerdp-core/window.c000066400000000000000000000311161207112532300174560ustar00rootroot00000000000000/** * FreeRDP: A Remote Desktop Protocol Client * Windowing Alternate Secondary Orders * * Copyright 2011 Marc-Andre Moreau * Copyright 2011 Roman Barabanov * * 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. */ #include #include #include "window.h" void update_read_icon_info(STREAM* s, ICON_INFO* icon_info) { stream_read_uint16(s, icon_info->cacheEntry); /* cacheEntry (2 bytes) */ stream_read_uint8(s, icon_info->cacheId); /* cacheId (1 byte) */ stream_read_uint8(s, icon_info->bpp); /* bpp (1 byte) */ stream_read_uint16(s, icon_info->width); /* width (2 bytes) */ stream_read_uint16(s, icon_info->height); /* height (2 bytes) */ /* cbColorTable is only present when bpp is 1, 2 or 4 */ if (icon_info->bpp == 1 || icon_info->bpp == 2 || icon_info->bpp == 4) stream_read_uint16(s, icon_info->cbColorTable); /* cbColorTable (2 bytes) */ else icon_info->cbColorTable = 0; stream_read_uint16(s, icon_info->cbBitsMask); /* cbBitsMask (2 bytes) */ stream_read_uint16(s, icon_info->cbBitsColor); /* cbBitsColor (2 bytes) */ /* bitsMask */ if (icon_info->bitsMask == NULL) icon_info->bitsMask = (uint8*) xmalloc(icon_info->cbBitsMask); else icon_info->bitsMask = (uint8*) xrealloc(icon_info->bitsMask, icon_info->cbBitsMask); stream_read(s, icon_info->bitsMask, icon_info->cbBitsMask); /* colorTable */ if (icon_info->colorTable == NULL) icon_info->colorTable = (uint8*) xmalloc(icon_info->cbColorTable); else icon_info->colorTable = (uint8*) xrealloc(icon_info->colorTable, icon_info->cbColorTable); stream_read(s, icon_info->colorTable, icon_info->cbColorTable); /* bitsColor */ if (icon_info->bitsColor == NULL) icon_info->bitsColor = (uint8*) xmalloc(icon_info->cbBitsColor); else icon_info->bitsColor = (uint8*) xrealloc(icon_info->bitsColor, icon_info->cbBitsColor); stream_read(s, icon_info->bitsColor, icon_info->cbBitsColor); } void update_read_cached_icon_info(STREAM* s, CACHED_ICON_INFO* cached_icon_info) { stream_read_uint16(s, cached_icon_info->cacheEntry); /* cacheEntry (2 bytes) */ stream_read_uint8(s, cached_icon_info->cacheId); /* cacheId (1 byte) */ } void update_read_notify_icon_infotip(STREAM* s, NOTIFY_ICON_INFOTIP* notify_icon_infotip) { stream_read_uint32(s, notify_icon_infotip->timeout); /* timeout (4 bytes) */ stream_read_uint32(s, notify_icon_infotip->flags); /* infoFlags (4 bytes) */ rail_read_unicode_string(s, ¬ify_icon_infotip->text); /* infoTipText */ rail_read_unicode_string(s, ¬ify_icon_infotip->title); /* title */ } void update_read_window_state_order(STREAM* s, WINDOW_ORDER_INFO* orderInfo, WINDOW_STATE_ORDER* window_state) { int i; int size; if (orderInfo->fieldFlags & WINDOW_ORDER_FIELD_OWNER) stream_read_uint32(s, window_state->ownerWindowId); /* ownerWindowId (4 bytes) */ if (orderInfo->fieldFlags & WINDOW_ORDER_FIELD_STYLE) { stream_read_uint32(s, window_state->style); /* style (4 bytes) */ stream_read_uint32(s, window_state->extendedStyle); /* extendedStyle (4 bytes) */ } if (orderInfo->fieldFlags & WINDOW_ORDER_FIELD_SHOW) stream_read_uint8(s, window_state->showState); /* showState (1 byte) */ if (orderInfo->fieldFlags & WINDOW_ORDER_FIELD_TITLE) rail_read_unicode_string(s, &window_state->titleInfo); /* titleInfo */ if (orderInfo->fieldFlags & WINDOW_ORDER_FIELD_CLIENT_AREA_OFFSET) { stream_read_uint32(s, window_state->clientOffsetX); /* clientOffsetX (4 bytes) */ stream_read_uint32(s, window_state->clientOffsetY); /* clientOffsetY (4 bytes) */ } if (orderInfo->fieldFlags & WINDOW_ORDER_FIELD_CLIENT_AREA_SIZE) { stream_read_uint32(s, window_state->clientAreaWidth); /* clientAreaWidth (4 bytes) */ stream_read_uint32(s, window_state->clientAreaHeight); /* clientAreaHeight (4 bytes) */ } if (orderInfo->fieldFlags & WINDOW_ORDER_FIELD_RP_CONTENT) stream_read_uint8(s, window_state->RPContent); /* RPContent (1 byte) */ if (orderInfo->fieldFlags & WINDOW_ORDER_FIELD_ROOT_PARENT) stream_read_uint32(s, window_state->rootParentHandle);/* rootParentHandle (4 bytes) */ if (orderInfo->fieldFlags & WINDOW_ORDER_FIELD_WND_OFFSET) { stream_read_uint32(s, window_state->windowOffsetX); /* windowOffsetX (4 bytes) */ stream_read_uint32(s, window_state->windowOffsetY); /* windowOffsetY (4 bytes) */ } if (orderInfo->fieldFlags & WINDOW_ORDER_FIELD_WND_CLIENT_DELTA) { stream_read_uint32(s, window_state->windowClientDeltaX); /* windowClientDeltaX (4 bytes) */ stream_read_uint32(s, window_state->windowClientDeltaY); /* windowClientDeltaY (4 bytes) */ } if (orderInfo->fieldFlags & WINDOW_ORDER_FIELD_WND_SIZE) { stream_read_uint32(s, window_state->windowWidth); /* windowWidth (4 bytes) */ stream_read_uint32(s, window_state->windowHeight); /* windowHeight (4 bytes) */ } if (orderInfo->fieldFlags & WINDOW_ORDER_FIELD_WND_RECTS) { stream_read_uint16(s, window_state->numWindowRects); /* numWindowRects (2 bytes) */ size = sizeof(RECTANGLE_16) * window_state->numWindowRects; window_state->windowRects = (RECTANGLE_16*) xmalloc(size); /* windowRects */ for (i = 0; i < (int) window_state->numWindowRects; i++) { freerdp_read_rectangle_16(s, &window_state->windowRects[i]); } } if (orderInfo->fieldFlags & WINDOW_ORDER_FIELD_VIS_OFFSET) { stream_read_uint32(s, window_state->visibleOffsetX); /* visibleOffsetX (4 bytes) */ stream_read_uint32(s, window_state->visibleOffsetY); /* visibleOffsetY (4 bytes) */ } if (orderInfo->fieldFlags & WINDOW_ORDER_FIELD_VISIBILITY) { stream_read_uint16(s, window_state->numVisibilityRects); /* numVisibilityRects (2 bytes) */ size = sizeof(RECTANGLE_16) * window_state->numVisibilityRects; window_state->visibilityRects = (RECTANGLE_16*) xmalloc(size); /* visibilityRects */ for (i = 0; i < (int) window_state->numVisibilityRects; i++) { freerdp_read_rectangle_16(s, &window_state->visibilityRects[i]); } } } void update_read_window_icon_order(STREAM* s, WINDOW_ORDER_INFO* orderInfo, WINDOW_ICON_ORDER* window_icon) { window_icon->iconInfo = (ICON_INFO*) xzalloc(sizeof(ICON_INFO)); update_read_icon_info(s, window_icon->iconInfo); /* iconInfo (ICON_INFO) */ } void update_read_window_cached_icon_order(STREAM* s, WINDOW_ORDER_INFO* orderInfo, WINDOW_CACHED_ICON_ORDER* window_cached_icon) { update_read_cached_icon_info(s, &window_cached_icon->cachedIcon); /* cachedIcon (CACHED_ICON_INFO) */ } void update_read_window_delete_order(STREAM* s, WINDOW_ORDER_INFO* orderInfo) { /* window deletion event */ } void update_recv_window_info_order(rdpUpdate* update, STREAM* s, WINDOW_ORDER_INFO* orderInfo) { rdpContext* context = update->context; rdpWindowUpdate* window = update->window; stream_read_uint32(s, orderInfo->windowId); /* windowId (4 bytes) */ if (orderInfo->fieldFlags & WINDOW_ORDER_ICON) { DEBUG_WND("Window Icon Order"); update_read_window_icon_order(s, orderInfo, &window->window_icon); IFCALL(window->WindowIcon, context, orderInfo, &window->window_icon); } else if (orderInfo->fieldFlags & WINDOW_ORDER_CACHED_ICON) { DEBUG_WND("Window Cached Icon Order"); update_read_window_cached_icon_order(s, orderInfo, &window->window_cached_icon); IFCALL(window->WindowCachedIcon, context, orderInfo, &window->window_cached_icon); } else if (orderInfo->fieldFlags & WINDOW_ORDER_STATE_DELETED) { DEBUG_WND("Window Deleted Order"); update_read_window_delete_order(s, orderInfo); IFCALL(window->WindowDelete, context, orderInfo); } else { DEBUG_WND("Window State Order"); update_read_window_state_order(s, orderInfo, &window->window_state); if (orderInfo->fieldFlags & WINDOW_ORDER_STATE_NEW) IFCALL(window->WindowCreate, context, orderInfo, &window->window_state); else IFCALL(window->WindowUpdate, context, orderInfo, &window->window_state); } } void update_read_notification_icon_state_order(STREAM* s, WINDOW_ORDER_INFO* orderInfo, NOTIFY_ICON_STATE_ORDER* notify_icon_state) { if (orderInfo->fieldFlags & WINDOW_ORDER_FIELD_NOTIFY_VERSION) stream_read_uint32(s, notify_icon_state->version); /* version (4 bytes) */ if (orderInfo->fieldFlags & WINDOW_ORDER_FIELD_NOTIFY_TIP) rail_read_unicode_string(s, ¬ify_icon_state->toolTip); /* toolTip (UNICODE_STRING) */ if (orderInfo->fieldFlags & WINDOW_ORDER_FIELD_NOTIFY_INFO_TIP) update_read_notify_icon_infotip(s, ¬ify_icon_state->infoTip); /* infoTip (NOTIFY_ICON_INFOTIP) */ if (orderInfo->fieldFlags & WINDOW_ORDER_FIELD_NOTIFY_STATE) stream_read_uint32(s, notify_icon_state->state); /* state (4 bytes) */ if (orderInfo->fieldFlags & WINDOW_ORDER_ICON) update_read_icon_info(s, ¬ify_icon_state->icon); /* icon (ICON_INFO) */ if (orderInfo->fieldFlags & WINDOW_ORDER_CACHED_ICON) update_read_cached_icon_info(s, ¬ify_icon_state->cachedIcon); /* cachedIcon (CACHED_ICON_INFO) */ } void update_read_notification_icon_delete_order(STREAM* s, WINDOW_ORDER_INFO* orderInfo) { /* notification icon deletion event */ } void update_recv_notification_icon_info_order(rdpUpdate* update, STREAM* s, WINDOW_ORDER_INFO* orderInfo) { rdpContext* context = update->context; rdpWindowUpdate* window = update->window; stream_read_uint32(s, orderInfo->windowId); /* windowId (4 bytes) */ stream_read_uint32(s, orderInfo->notifyIconId); /* notifyIconId (4 bytes) */ if (orderInfo->fieldFlags & WINDOW_ORDER_STATE_DELETED) { DEBUG_WND("Delete Notification Icon Deleted Order"); update_read_notification_icon_delete_order(s, orderInfo); IFCALL(window->NotifyIconDelete, context, orderInfo); } else { DEBUG_WND("Notification Icon State Order"); update_read_notification_icon_state_order(s, orderInfo, &window->notify_icon_state); if (orderInfo->fieldFlags & WINDOW_ORDER_STATE_NEW) IFCALL(window->NotifyIconCreate, context, orderInfo, &window->notify_icon_state); else IFCALL(window->NotifyIconUpdate, context, orderInfo, &window->notify_icon_state); } } void update_read_desktop_actively_monitored_order(STREAM* s, WINDOW_ORDER_INFO* orderInfo, MONITORED_DESKTOP_ORDER* monitored_desktop) { int i; int size; if (orderInfo->fieldFlags & WINDOW_ORDER_FIELD_DESKTOP_ACTIVE_WND) stream_read_uint32(s, monitored_desktop->activeWindowId); /* activeWindowId (4 bytes) */ if (orderInfo->fieldFlags & WINDOW_ORDER_FIELD_DESKTOP_ZORDER) { stream_read_uint8(s, monitored_desktop->numWindowIds); /* numWindowIds (1 byte) */ size = sizeof(uint32) * monitored_desktop->numWindowIds; if (monitored_desktop->windowIds == NULL) monitored_desktop->windowIds = (uint32*) xmalloc(size); else monitored_desktop->windowIds = (uint32*) xrealloc(monitored_desktop->windowIds, size); /* windowIds */ for (i = 0; i < (int) monitored_desktop->numWindowIds; i++) { stream_read_uint32(s, monitored_desktop->windowIds[i]); } } } void update_read_desktop_non_monitored_order(STREAM* s, WINDOW_ORDER_INFO* orderInfo) { /* non-monitored desktop notification event */ } void update_recv_desktop_info_order(rdpUpdate* update, STREAM* s, WINDOW_ORDER_INFO* orderInfo) { rdpContext* context = update->context; rdpWindowUpdate* window = update->window; if (orderInfo->fieldFlags & WINDOW_ORDER_FIELD_DESKTOP_NONE) { DEBUG_WND("Non-Monitored Desktop Order"); update_read_desktop_non_monitored_order(s, orderInfo); IFCALL(window->NonMonitoredDesktop, context, orderInfo); } else { DEBUG_WND("Actively Monitored Desktop Order"); update_read_desktop_actively_monitored_order(s, orderInfo, &window->monitored_desktop); IFCALL(window->MonitoredDesktop, context, orderInfo, &window->monitored_desktop); } } void update_recv_altsec_window_order(rdpUpdate* update, STREAM* s) { uint16 orderSize; rdpWindowUpdate* window = update->window; stream_read_uint16(s, orderSize); /* orderSize (2 bytes) */ stream_read_uint32(s, window->orderInfo.fieldFlags); /* FieldsPresentFlags (4 bytes) */ if (window->orderInfo.fieldFlags & WINDOW_ORDER_TYPE_WINDOW) update_recv_window_info_order(update, s, &window->orderInfo); else if (window->orderInfo.fieldFlags & WINDOW_ORDER_TYPE_NOTIFY) update_recv_notification_icon_info_order(update, s, &window->orderInfo); else if (window->orderInfo.fieldFlags & WINDOW_ORDER_TYPE_DESKTOP) update_recv_desktop_info_order(update, s, &window->orderInfo); } FreeRDP-1.0.2/libfreerdp-core/window.h000066400000000000000000000021531207112532300174620ustar00rootroot00000000000000/** * FreeRDP: A Remote Desktop Protocol Client * Windowing Alternate Secondary Orders * * Copyright 2011 Marc-Andre Moreau * Copyright 2011 Roman Barabanov * * 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. */ #ifndef __WINDOW_H #define __WINDOW_H #include "update.h" #include void update_recv_altsec_window_order(rdpUpdate* update, STREAM* s); #ifdef WITH_DEBUG_WND #define DEBUG_WND(fmt, ...) DEBUG_CLASS(WND, fmt, ## __VA_ARGS__) #else #define DEBUG_WND(fmt, ...) DEBUG_NULL(fmt, ## __VA_ARGS__) #endif #endif /* __WINDOW_H */ FreeRDP-1.0.2/libfreerdp-gdi/000077500000000000000000000000001207112532300156145ustar00rootroot00000000000000FreeRDP-1.0.2/libfreerdp-gdi/16bpp.c000066400000000000000000000537261207112532300167250ustar00rootroot00000000000000/** * FreeRDP: A Remote Desktop Protocol Client * GDI 16bpp Internal Buffer Routines * * Copyright 2010-2011 Marc-Andre Moreau * * 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. */ #include #include #include #include #include #include #include #include #include #include #include #include #include uint16 gdi_get_color_16bpp(HGDI_DC hdc, GDI_COLOR color) { uint8 r, g, b; uint16 color16; GetBGR32(r, g, b, color); if (hdc->rgb555) { if (hdc->invert) { color16 = BGR15(r, g, b); } else { color16 = RGB15(r, g, b); } } else { if (hdc->invert) { color16 = BGR16(r, g, b); } else { color16 = RGB16(r, g, b); } } return color16; } int FillRect_16bpp(HGDI_DC hdc, HGDI_RECT rect, HGDI_BRUSH hbr) { int x, y; uint16 *dstp; int nXDest, nYDest; int nWidth, nHeight; uint16 color16; gdi_RectToCRgn(rect, &nXDest, &nYDest, &nWidth, &nHeight); if (gdi_ClipCoords(hdc, &nXDest, &nYDest, &nWidth, &nHeight, NULL, NULL) == 0) return 0; color16 = gdi_get_color_16bpp(hdc, hbr->color); for (y = 0; y < nHeight; y++) { dstp = (uint16*) gdi_get_bitmap_pointer(hdc, nXDest, nYDest + y); if (dstp != 0) { for (x = 0; x < nWidth; x++) { *dstp = color16; dstp++; } } } gdi_InvalidateRegion(hdc, nXDest, nYDest, nWidth, nHeight); return 0; } static int BitBlt_BLACKNESS_16bpp(HGDI_DC hdcDest, int nXDest, int nYDest, int nWidth, int nHeight) { int y; uint8* dstp; for (y = 0; y < nHeight; y++) { dstp = gdi_get_bitmap_pointer(hdcDest, nXDest, nYDest + y); if (dstp != 0) memset(dstp, 0, nWidth * hdcDest->bytesPerPixel); } return 0; } static int BitBlt_WHITENESS_16bpp(HGDI_DC hdcDest, int nXDest, int nYDest, int nWidth, int nHeight) { int y; uint8* dstp; for (y = 0; y < nHeight; y++) { dstp = gdi_get_bitmap_pointer(hdcDest, nXDest, nYDest + y); if (dstp != 0) memset(dstp, 0xFF, nWidth * hdcDest->bytesPerPixel); } return 0; } static int BitBlt_SRCCOPY_16bpp(HGDI_DC hdcDest, int nXDest, int nYDest, int nWidth, int nHeight, HGDI_DC hdcSrc, int nXSrc, int nYSrc) { int y; uint8* srcp; uint8* dstp; if ((hdcDest->selectedObject != hdcSrc->selectedObject) || gdi_CopyOverlap(nXDest, nYDest, nWidth, nHeight, nXSrc, nYSrc) == 0) { for (y = 0; y < nHeight; y++) { srcp = gdi_get_bitmap_pointer(hdcSrc, nXSrc, nYSrc + y); dstp = gdi_get_bitmap_pointer(hdcDest, nXDest, nYDest + y); if (srcp != 0 && dstp != 0) memcpy(dstp, srcp, nWidth * hdcDest->bytesPerPixel); } return 0; } if (nYSrc < nYDest) { /* copy down (bottom to top) */ for (y = nHeight - 1; y >= 0; y--) { srcp = gdi_get_bitmap_pointer(hdcSrc, nXSrc, nYSrc + y); dstp = gdi_get_bitmap_pointer(hdcDest, nXDest, nYDest + y); if (srcp != 0 && dstp != 0) memmove(dstp, srcp, nWidth * hdcDest->bytesPerPixel); } } else if (nYSrc > nYDest || nXSrc > nXDest) { /* copy up or left (top top bottom) */ for (y = 0; y < nHeight; y++) { srcp = gdi_get_bitmap_pointer(hdcSrc, nXSrc, nYSrc + y); dstp = gdi_get_bitmap_pointer(hdcDest, nXDest, nYDest + y); if (srcp != 0 && dstp != 0) memmove(dstp, srcp, nWidth * hdcDest->bytesPerPixel); } } else { /* copy straight right */ for (y = 0; y < nHeight; y++) { srcp = gdi_get_bitmap_pointer(hdcSrc, nXSrc, nYSrc + y); dstp = gdi_get_bitmap_pointer(hdcDest, nXDest, nYDest + y); if (srcp != 0 && dstp != 0) memmove(dstp, srcp, nWidth * hdcDest->bytesPerPixel); } } return 0; } static int BitBlt_NOTSRCCOPY_16bpp(HGDI_DC hdcDest, int nXDest, int nYDest, int nWidth, int nHeight, HGDI_DC hdcSrc, int nXSrc, int nYSrc) { int x, y; uint16* srcp; uint16* dstp; for (y = 0; y < nHeight; y++) { srcp = (uint16*) gdi_get_bitmap_pointer(hdcSrc, nXSrc, nYSrc + y); dstp = (uint16*) gdi_get_bitmap_pointer(hdcDest, nXDest, nYDest + y); if (dstp != 0) { for (x = 0; x < nWidth; x++) { *dstp = ~(*srcp); srcp++; dstp++; } } } return 0; } static int BitBlt_DSTINVERT_16bpp(HGDI_DC hdcDest, int nXDest, int nYDest, int nWidth, int nHeight) { int x, y; uint16* dstp; for (y = 0; y < nHeight; y++) { dstp = (uint16*) gdi_get_bitmap_pointer(hdcDest, nXDest, nYDest + y); if (dstp != 0) { for (x = 0; x < nWidth; x++) { *dstp = ~(*dstp); dstp++; } } } return 0; } static int BitBlt_SRCERASE_16bpp(HGDI_DC hdcDest, int nXDest, int nYDest, int nWidth, int nHeight, HGDI_DC hdcSrc, int nXSrc, int nYSrc) { int x, y; uint16* srcp; uint16* dstp; for (y = 0; y < nHeight; y++) { srcp = (uint16*) gdi_get_bitmap_pointer(hdcSrc, nXSrc, nYSrc + y); dstp = (uint16*) gdi_get_bitmap_pointer(hdcDest, nXDest, nYDest + y); if (dstp != 0) { for (x = 0; x < nWidth; x++) { *dstp = *srcp & ~(*dstp); srcp++; dstp++; } } } return 0; } static int BitBlt_NOTSRCERASE_16bpp(HGDI_DC hdcDest, int nXDest, int nYDest, int nWidth, int nHeight, HGDI_DC hdcSrc, int nXSrc, int nYSrc) { int x, y; uint16* srcp; uint16* dstp; for (y = 0; y < nHeight; y++) { srcp = (uint16*) gdi_get_bitmap_pointer(hdcSrc, nXSrc, nYSrc + y); dstp = (uint16*) gdi_get_bitmap_pointer(hdcDest, nXDest, nYDest + y); if (dstp != 0) { for (x = 0; x < nWidth; x++) { *dstp = ~(*srcp) & ~(*dstp); srcp++; dstp++; } } } return 0; } static int BitBlt_SRCINVERT_16bpp(HGDI_DC hdcDest, int nXDest, int nYDest, int nWidth, int nHeight, HGDI_DC hdcSrc, int nXSrc, int nYSrc) { int x, y; uint16* srcp; uint16* dstp; for (y = 0; y < nHeight; y++) { srcp = (uint16*) gdi_get_bitmap_pointer(hdcSrc, nXSrc, nYSrc + y); dstp = (uint16*) gdi_get_bitmap_pointer(hdcDest, nXDest, nYDest + y); if (dstp != 0) { for (x = 0; x < nWidth; x++) { *dstp ^= *srcp; srcp++; dstp++; } } } return 0; } static int BitBlt_SRCAND_16bpp(HGDI_DC hdcDest, int nXDest, int nYDest, int nWidth, int nHeight, HGDI_DC hdcSrc, int nXSrc, int nYSrc) { int x, y; uint16* srcp; uint16* dstp; for (y = 0; y < nHeight; y++) { srcp = (uint16*) gdi_get_bitmap_pointer(hdcSrc, nXSrc, nYSrc + y); dstp = (uint16*) gdi_get_bitmap_pointer(hdcDest, nXDest, nYDest + y); if (dstp != 0) { for (x = 0; x < nWidth; x++) { *dstp &= *srcp; srcp++; dstp++; } } } return 0; } static int BitBlt_SRCPAINT_16bpp(HGDI_DC hdcDest, int nXDest, int nYDest, int nWidth, int nHeight, HGDI_DC hdcSrc, int nXSrc, int nYSrc) { int x, y; uint16* srcp; uint16* dstp; for (y = 0; y < nHeight; y++) { srcp = (uint16*) gdi_get_bitmap_pointer(hdcSrc, nXSrc, nYSrc + y); dstp = (uint16*) gdi_get_bitmap_pointer(hdcDest, nXDest, nYDest + y); if (dstp != 0) { for (x = 0; x < nWidth; x++) { *dstp |= *srcp; srcp++; dstp++; } } } return 0; } static int BitBlt_DSPDxax_16bpp(HGDI_DC hdcDest, int nXDest, int nYDest, int nWidth, int nHeight, HGDI_DC hdcSrc, int nXSrc, int nYSrc) { int x, y; uint8* srcp; uint16* dstp; uint16 src16; uint16 color16; HGDI_BITMAP hSrcBmp; /* D = (S & P) | (~S & D) */ /* DSPDxax, used to draw glyphs */ color16 = gdi_get_color_16bpp(hdcDest, hdcDest->textColor); hSrcBmp = (HGDI_BITMAP) hdcSrc->selectedObject; if (hdcSrc->bytesPerPixel != 1) { printf("BitBlt_DSPDxax expects 1 bpp, unimplemented for %d\n", hdcSrc->bytesPerPixel); return 0; } for (y = 0; y < nHeight; y++) { srcp = (uint8*) gdi_get_bitmap_pointer(hdcSrc, nXSrc, nYSrc + y); dstp = (uint16*) gdi_get_bitmap_pointer(hdcDest, nXDest, nYDest + y); if (dstp != 0) { for (x = 0; x < nWidth; x++) { src16 = (*srcp << 8) | *srcp; *dstp = (src16 & color16) | (~src16 & *dstp); srcp++; dstp++; } } } return 0; } static int BitBlt_SPna_16bpp(HGDI_DC hdcDest, int nXDest, int nYDest, int nWidth, int nHeight, HGDI_DC hdcSrc, int nXSrc, int nYSrc) { int x, y; uint16* srcp; uint16* dstp; uint16* patp; for (y = 0; y < nHeight; y++) { srcp = (uint16*) gdi_get_bitmap_pointer(hdcSrc, nXSrc, nYSrc + y); dstp = (uint16*) gdi_get_bitmap_pointer(hdcDest, nXDest, nYDest + y); if (dstp != 0) { for (x = 0; x < nWidth; x++) { patp = (uint16*) gdi_get_brush_pointer(hdcDest, x, y); *dstp = *srcp & ~(*patp); srcp++; dstp++; } } } return 0; } static int BitBlt_DPa_16bpp(HGDI_DC hdcDest, int nXDest, int nYDest, int nWidth, int nHeight) { int x, y; uint16* dstp; uint16* patp; for (y = 0; y < nHeight; y++) { dstp = (uint16*) gdi_get_bitmap_pointer(hdcDest, nXDest, nYDest + y); if (dstp != 0) { for (x = 0; x < nWidth; x++) { patp = (uint16*) gdi_get_brush_pointer(hdcDest, x, y); *dstp = *dstp & *patp; dstp++; } } } return 0; } static int BitBlt_PDxn_16bpp(HGDI_DC hdcDest, int nXDest, int nYDest, int nWidth, int nHeight) { int x, y; uint16* dstp; uint16* patp; for (y = 0; y < nHeight; y++) { dstp = (uint16*) gdi_get_bitmap_pointer(hdcDest, nXDest, nYDest + y); if (dstp != 0) { for (x = 0; x < nWidth; x++) { patp = (uint16*) gdi_get_brush_pointer(hdcDest, x, y); *dstp = *dstp ^ ~(*patp); dstp++; } } } return 0; } static int BitBlt_DSna_16bpp(HGDI_DC hdcDest, int nXDest, int nYDest, int nWidth, int nHeight, HGDI_DC hdcSrc, int nXSrc, int nYSrc) { int x, y; uint16* srcp; uint16* dstp; for (y = 0; y < nHeight; y++) { srcp = (uint16*) gdi_get_bitmap_pointer(hdcSrc, nXSrc, nYSrc + y); dstp = (uint16*) gdi_get_bitmap_pointer(hdcDest, nXDest, nYDest + y); if (dstp != 0) { for (x = 0; x < nWidth; x++) { *dstp = ~(*srcp) & (*dstp); srcp++; dstp++; } } } return 0; } static int BitBlt_MERGECOPY_16bpp(HGDI_DC hdcDest, int nXDest, int nYDest, int nWidth, int nHeight, HGDI_DC hdcSrc, int nXSrc, int nYSrc) { int x, y; uint16* srcp; uint16* dstp; uint16* patp; for (y = 0; y < nHeight; y++) { srcp = (uint16*) gdi_get_bitmap_pointer(hdcSrc, nXSrc, nYSrc + y); dstp = (uint16*) gdi_get_bitmap_pointer(hdcDest, nXDest, nYDest + y); if (dstp != 0) { for (x = 0; x < nWidth; x++) { patp = (uint16*) gdi_get_brush_pointer(hdcDest, x, y); *dstp = *srcp & *patp; srcp++; dstp++; } } } return 0; } static int BitBlt_MERGEPAINT_16bpp(HGDI_DC hdcDest, int nXDest, int nYDest, int nWidth, int nHeight, HGDI_DC hdcSrc, int nXSrc, int nYSrc) { int x, y; uint16* srcp; uint16* dstp; for (y = 0; y < nHeight; y++) { srcp = (uint16*) gdi_get_bitmap_pointer(hdcSrc, nXSrc, nYSrc + y); dstp = (uint16*) gdi_get_bitmap_pointer(hdcDest, nXDest, nYDest + y); if (dstp != 0) { for (x = 0; x < nWidth; x++) { *dstp = ~(*srcp) | *dstp; srcp++; dstp++; } } } return 0; } static int BitBlt_PATCOPY_16bpp(HGDI_DC hdcDest, int nXDest, int nYDest, int nWidth, int nHeight) { int x, y; uint16* dstp; uint16* patp; uint16 color16; if (hdcDest->brush->style == GDI_BS_SOLID) { color16 = gdi_get_color_16bpp(hdcDest, hdcDest->brush->color); for (y = 0; y < nHeight; y++) { dstp = (uint16*) gdi_get_bitmap_pointer(hdcDest, nXDest, nYDest + y); if (dstp != 0) { for (x = 0; x < nWidth; x++) { *dstp = color16; dstp++; } } } } else { for (y = 0; y < nHeight; y++) { dstp = (uint16*) gdi_get_bitmap_pointer(hdcDest, nXDest, nYDest + y); if (dstp != 0) { for (x = 0; x < nWidth; x++) { patp = (uint16*) gdi_get_brush_pointer(hdcDest, x, y); *dstp = *patp; dstp++; } } } } return 0; } static int BitBlt_PATINVERT_16bpp(HGDI_DC hdcDest, int nXDest, int nYDest, int nWidth, int nHeight) { int x, y; uint16* dstp; uint16* patp; uint16 color16; if (hdcDest->brush->style == GDI_BS_SOLID) { color16 = gdi_get_color_16bpp(hdcDest, hdcDest->brush->color); for (y = 0; y < nHeight; y++) { dstp = (uint16*) gdi_get_bitmap_pointer(hdcDest, nXDest, nYDest + y); if (dstp != 0) { for (x = 0; x < nWidth; x++) { *dstp ^= color16; dstp++; } } } } else { for (y = 0; y < nHeight; y++) { dstp = (uint16*) gdi_get_bitmap_pointer(hdcDest, nXDest, nYDest + y); if (dstp != 0) { for (x = 0; x < nWidth; x++) { patp = (uint16*) gdi_get_brush_pointer(hdcDest, x, y); *dstp = *patp ^ *dstp; dstp++; } } } } return 0; } static int BitBlt_PATPAINT_16bpp(HGDI_DC hdcDest, int nXDest, int nYDest, int nWidth, int nHeight, HGDI_DC hdcSrc, int nXSrc, int nYSrc) { int x, y; uint16* srcp; uint16* dstp; uint16* patp; for (y = 0; y < nHeight; y++) { srcp = (uint16*) gdi_get_bitmap_pointer(hdcSrc, nXSrc, nYSrc + y); dstp = (uint16*) gdi_get_bitmap_pointer(hdcDest, nXDest, nYDest + y); if (dstp != 0) { for (x = 0; x < nWidth; x++) { patp = (uint16*) gdi_get_brush_pointer(hdcDest, x, y); *dstp = *dstp | (*patp | ~(*srcp)); srcp++; dstp++; } } } return 0; } int BitBlt_16bpp(HGDI_DC hdcDest, int nXDest, int nYDest, int nWidth, int nHeight, HGDI_DC hdcSrc, int nXSrc, int nYSrc, int rop) { if (hdcSrc != NULL) { if (gdi_ClipCoords(hdcDest, &nXDest, &nYDest, &nWidth, &nHeight, &nXSrc, &nYSrc) == 0) return 0; } else { if (gdi_ClipCoords(hdcDest, &nXDest, &nYDest, &nWidth, &nHeight, NULL, NULL) == 0) return 0; } gdi_InvalidateRegion(hdcDest, nXDest, nYDest, nWidth, nHeight); switch (rop) { case GDI_BLACKNESS: return BitBlt_BLACKNESS_16bpp(hdcDest, nXDest, nYDest, nWidth, nHeight); break; case GDI_WHITENESS: return BitBlt_WHITENESS_16bpp(hdcDest, nXDest, nYDest, nWidth, nHeight); break; case GDI_SRCCOPY: return BitBlt_SRCCOPY_16bpp(hdcDest, nXDest, nYDest, nWidth, nHeight, hdcSrc, nXSrc, nYSrc); break; case GDI_SPna: return BitBlt_SPna_16bpp(hdcDest, nXDest, nYDest, nWidth, nHeight, hdcSrc, nXSrc, nYSrc); break; case GDI_DSna: return BitBlt_DSna_16bpp(hdcDest, nXDest, nYDest, nWidth, nHeight, hdcSrc, nXSrc, nYSrc); break; case GDI_DSPDxax: return BitBlt_DSPDxax_16bpp(hdcDest, nXDest, nYDest, nWidth, nHeight, hdcSrc, nXSrc, nYSrc); break; case GDI_NOTSRCCOPY: return BitBlt_NOTSRCCOPY_16bpp(hdcDest, nXDest, nYDest, nWidth, nHeight, hdcSrc, nXSrc, nYSrc); break; case GDI_DSTINVERT: return BitBlt_DSTINVERT_16bpp(hdcDest, nXDest, nYDest, nWidth, nHeight); break; case GDI_SRCERASE: return BitBlt_SRCERASE_16bpp(hdcDest, nXDest, nYDest, nWidth, nHeight, hdcSrc, nXSrc, nYSrc); break; case GDI_NOTSRCERASE: return BitBlt_NOTSRCERASE_16bpp(hdcDest, nXDest, nYDest, nWidth, nHeight, hdcSrc, nXSrc, nYSrc); break; case GDI_SRCINVERT: return BitBlt_SRCINVERT_16bpp(hdcDest, nXDest, nYDest, nWidth, nHeight, hdcSrc, nXSrc, nYSrc); break; case GDI_SRCAND: return BitBlt_SRCAND_16bpp(hdcDest, nXDest, nYDest, nWidth, nHeight, hdcSrc, nXSrc, nYSrc); break; case GDI_SRCPAINT: return BitBlt_SRCPAINT_16bpp(hdcDest, nXDest, nYDest, nWidth, nHeight, hdcSrc, nXSrc, nYSrc); break; case GDI_MERGECOPY: return BitBlt_MERGECOPY_16bpp(hdcDest, nXDest, nYDest, nWidth, nHeight, hdcSrc, nXSrc, nYSrc); break; case GDI_MERGEPAINT: return BitBlt_MERGEPAINT_16bpp(hdcDest, nXDest, nYDest, nWidth, nHeight, hdcSrc, nXSrc, nYSrc); break; case GDI_PATCOPY: return BitBlt_PATCOPY_16bpp(hdcDest, nXDest, nYDest, nWidth, nHeight); break; case GDI_PATINVERT: return BitBlt_PATINVERT_16bpp(hdcDest, nXDest, nYDest, nWidth, nHeight); break; case GDI_PATPAINT: return BitBlt_PATPAINT_16bpp(hdcDest, nXDest, nYDest, nWidth, nHeight, hdcSrc, nXSrc, nYSrc); break; } printf("BitBlt: unknown rop: 0x%08X\n", rop); return 1; } int PatBlt_16bpp(HGDI_DC hdc, int nXLeft, int nYLeft, int nWidth, int nHeight, int rop) { if (gdi_ClipCoords(hdc, &nXLeft, &nYLeft, &nWidth, &nHeight, NULL, NULL) == 0) return 0; gdi_InvalidateRegion(hdc, nXLeft, nYLeft, nWidth, nHeight); switch (rop) { case GDI_PATCOPY: return BitBlt_PATCOPY_16bpp(hdc, nXLeft, nYLeft, nWidth, nHeight); break; case GDI_PATINVERT: return BitBlt_PATINVERT_16bpp(hdc, nXLeft, nYLeft, nWidth, nHeight); break; case GDI_DSTINVERT: return BitBlt_DSTINVERT_16bpp(hdc, nXLeft, nYLeft, nWidth, nHeight); break; case GDI_BLACKNESS: return BitBlt_BLACKNESS_16bpp(hdc, nXLeft, nYLeft, nWidth, nHeight); break; case GDI_WHITENESS: return BitBlt_WHITENESS_16bpp(hdc, nXLeft, nYLeft, nWidth, nHeight); break; case GDI_DPa: return BitBlt_DPa_16bpp(hdc, nXLeft, nYLeft, nWidth, nHeight); break; case GDI_PDxn: return BitBlt_PDxn_16bpp(hdc, nXLeft, nYLeft, nWidth, nHeight); break; default: break; } printf("PatBlt: unknown rop: 0x%08X\n", rop); return 1; } INLINE void SetPixel_BLACK_16bpp(uint16 *pixel, uint16 *pen) { /* D = 0 */ *pixel = 0; } INLINE void SetPixel_NOTMERGEPEN_16bpp(uint16 *pixel, uint16 *pen) { /* D = ~(D | P) */ *pixel = ~(*pixel | *pen); } INLINE void SetPixel_MASKNOTPEN_16bpp(uint16 *pixel, uint16 *pen) { /* D = D & ~P */ *pixel &= ~(*pen); } INLINE void SetPixel_NOTCOPYPEN_16bpp(uint16 *pixel, uint16 *pen) { /* D = ~P */ *pixel = ~(*pen); } INLINE void SetPixel_MASKPENNOT_16bpp(uint16 *pixel, uint16 *pen) { /* D = P & ~D */ *pixel = *pen & ~*pixel; } INLINE void SetPixel_NOT_16bpp(uint16 *pixel, uint16 *pen) { /* D = ~D */ *pixel = ~(*pixel); } INLINE void SetPixel_XORPEN_16bpp(uint16 *pixel, uint16 *pen) { /* D = D ^ P */ *pixel = *pixel ^ *pen; } INLINE void SetPixel_NOTMASKPEN_16bpp(uint16 *pixel, uint16 *pen) { /* D = ~(D & P) */ *pixel = ~(*pixel & *pen); } INLINE void SetPixel_MASKPEN_16bpp(uint16 *pixel, uint16 *pen) { /* D = D & P */ *pixel &= *pen; } INLINE void SetPixel_NOTXORPEN_16bpp(uint16 *pixel, uint16 *pen) { /* D = ~(D ^ P) */ *pixel = ~(*pixel ^ *pen); } INLINE void SetPixel_NOP_16bpp(uint16 *pixel, uint16 *pen) { /* D = D */ } INLINE void SetPixel_MERGENOTPEN_16bpp(uint16 *pixel, uint16 *pen) { /* D = D | ~P */ *pixel |= ~(*pen); } INLINE void SetPixel_COPYPEN_16bpp(uint16 *pixel, uint16 *pen) { /* D = P */ *pixel = *pen; } INLINE void SetPixel_MERGEPENNOT_16bpp(uint16 *pixel, uint16 *pen) { /* D = P | ~D */ *pixel = *pen | ~(*pixel); } INLINE void SetPixel_MERGEPEN_16bpp(uint16 *pixel, uint16 *pen) { /* D = P | D */ *pixel |= *pen; } INLINE void SetPixel_WHITE_16bpp(uint16 *pixel, uint16 *pen) { /* D = 1 */ *pixel = 0xFFFF; } #define PIXEL_TYPE uint16 #define GDI_GET_POINTER gdi_GetPointer_16bpp #define GDI_GET_PEN_COLOR gdi_GetPenColor_16bpp #define LINE_TO LineTo_BLACK_16bpp #define SET_PIXEL_ROP2 SetPixel_BLACK_16bpp #include "include/line.c" #undef LINE_TO #undef SET_PIXEL_ROP2 #define LINE_TO LineTo_NOTMERGEPEN_16bpp #define SET_PIXEL_ROP2 SetPixel_NOTMERGEPEN_16bpp #include "include/line.c" #undef LINE_TO #undef SET_PIXEL_ROP2 #define LINE_TO LineTo_MASKNOTPEN_16bpp #define SET_PIXEL_ROP2 SetPixel_MASKNOTPEN_16bpp #include "include/line.c" #undef LINE_TO #undef SET_PIXEL_ROP2 #define LINE_TO LineTo_NOTCOPYPEN_16bpp #define SET_PIXEL_ROP2 SetPixel_NOTCOPYPEN_16bpp #include "include/line.c" #undef LINE_TO #undef SET_PIXEL_ROP2 #define LINE_TO LineTo_MASKPENNOT_16bpp #define SET_PIXEL_ROP2 SetPixel_MASKPENNOT_16bpp #include "include/line.c" #undef LINE_TO #undef SET_PIXEL_ROP2 #define LINE_TO LineTo_NOT_16bpp #define SET_PIXEL_ROP2 SetPixel_NOT_16bpp #include "include/line.c" #undef LINE_TO #undef SET_PIXEL_ROP2 #define LINE_TO LineTo_XORPEN_16bpp #define SET_PIXEL_ROP2 SetPixel_XORPEN_16bpp #include "include/line.c" #undef LINE_TO #undef SET_PIXEL_ROP2 #define LINE_TO LineTo_NOTMASKPEN_16bpp #define SET_PIXEL_ROP2 SetPixel_NOTMASKPEN_16bpp #include "include/line.c" #undef LINE_TO #undef SET_PIXEL_ROP2 #define LINE_TO LineTo_MASKPEN_16bpp #define SET_PIXEL_ROP2 SetPixel_MASKPEN_16bpp #include "include/line.c" #undef LINE_TO #undef SET_PIXEL_ROP2 #define LINE_TO LineTo_NOTXORPEN_16bpp #define SET_PIXEL_ROP2 SetPixel_NOTXORPEN_16bpp #include "include/line.c" #undef LINE_TO #undef SET_PIXEL_ROP2 #define LINE_TO LineTo_NOP_16bpp #define SET_PIXEL_ROP2 SetPixel_NOP_16bpp #include "include/line.c" #undef LINE_TO #undef SET_PIXEL_ROP2 #define LINE_TO LineTo_MERGENOTPEN_16bpp #define SET_PIXEL_ROP2 SetPixel_MERGENOTPEN_16bpp #include "include/line.c" #undef LINE_TO #undef SET_PIXEL_ROP2 #define LINE_TO LineTo_COPYPEN_16bpp #define SET_PIXEL_ROP2 SetPixel_COPYPEN_16bpp #include "include/line.c" #undef LINE_TO #undef SET_PIXEL_ROP2 #define LINE_TO LineTo_MERGEPENNOT_16bpp #define SET_PIXEL_ROP2 SetPixel_MERGEPENNOT_16bpp #include "include/line.c" #undef LINE_TO #undef SET_PIXEL_ROP2 #define LINE_TO LineTo_MERGEPEN_16bpp #define SET_PIXEL_ROP2 SetPixel_MERGEPEN_16bpp #include "include/line.c" #undef LINE_TO #undef SET_PIXEL_ROP2 #define LINE_TO LineTo_WHITE_16bpp #define SET_PIXEL_ROP2 SetPixel_WHITE_16bpp #include "include/line.c" #undef LINE_TO #undef SET_PIXEL_ROP2 #undef PIXEL_TYPE #undef GDI_GET_POINTER #undef GDI_GET_PEN_COLOR pLineTo_16bpp LineTo_ROP2_16bpp[32] = { LineTo_BLACK_16bpp, LineTo_NOTMERGEPEN_16bpp, LineTo_MASKNOTPEN_16bpp, LineTo_NOTCOPYPEN_16bpp, LineTo_MASKPENNOT_16bpp, LineTo_NOT_16bpp, LineTo_XORPEN_16bpp, LineTo_NOTMASKPEN_16bpp, LineTo_MASKPEN_16bpp, LineTo_NOTXORPEN_16bpp, LineTo_NOP_16bpp, LineTo_MERGENOTPEN_16bpp, LineTo_COPYPEN_16bpp, LineTo_MERGEPENNOT_16bpp, LineTo_MERGEPEN_16bpp, LineTo_WHITE_16bpp }; int LineTo_16bpp(HGDI_DC hdc, int nXEnd, int nYEnd) { pLineTo_16bpp _LineTo; int rop2 = gdi_GetROP2(hdc) - 1; _LineTo = LineTo_ROP2_16bpp[rop2]; if (_LineTo != NULL) return _LineTo(hdc, nXEnd, nYEnd); else return 0; } FreeRDP-1.0.2/libfreerdp-gdi/32bpp.c000066400000000000000000000545661207112532300167260ustar00rootroot00000000000000/** * FreeRDP: A Remote Desktop Protocol Client * GDI 32bpp Internal Buffer Routines * * Copyright 2010-2011 Marc-Andre Moreau * * 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. */ #include #include #include #include #include #include #include #include #include #include #include #include #include uint32 gdi_get_color_32bpp(HGDI_DC hdc, GDI_COLOR color) { uint32 color32; uint8 a, r, g, b; a = 0xFF; GetBGR32(r, g, b, color); if (hdc->invert) { color32 = ABGR32(a, r, g, b); } else { color32 = ARGB32(a, r, g, b); } return color32; } int FillRect_32bpp(HGDI_DC hdc, HGDI_RECT rect, HGDI_BRUSH hbr) { int x, y; uint32 *dstp; uint32 color32; int nXDest, nYDest; int nWidth, nHeight; gdi_RectToCRgn(rect, &nXDest, &nYDest, &nWidth, &nHeight); if (gdi_ClipCoords(hdc, &nXDest, &nYDest, &nWidth, &nHeight, NULL, NULL) == 0) return 0; color32 = gdi_get_color_32bpp(hdc, hbr->color); for (y = 0; y < nHeight; y++) { dstp = (uint32*) gdi_get_bitmap_pointer(hdc, nXDest, nYDest + y); if (dstp != 0) { for (x = 0; x < nWidth; x++) { *dstp = color32; dstp++; } } } gdi_InvalidateRegion(hdc, nXDest, nYDest, nWidth, nHeight); return 0; } static int BitBlt_BLACKNESS_32bpp(HGDI_DC hdcDest, int nXDest, int nYDest, int nWidth, int nHeight) { if (hdcDest->alpha) { int x, y; uint8* dstp; for (y = 0; y < nHeight; y++) { dstp = gdi_get_bitmap_pointer(hdcDest, nXDest, nYDest + y); if (dstp != 0) { for (x = 0; x < nWidth; x++) { *dstp = 0; dstp++; *dstp = 0; dstp++; *dstp = 0; dstp++; *dstp = 0xFF; dstp++; } } } } else { int y; uint8* dstp; for (y = 0; y < nHeight; y++) { dstp = gdi_get_bitmap_pointer(hdcDest, nXDest, nYDest + y); if (dstp != 0) memset(dstp, 0, nWidth * hdcDest->bytesPerPixel); } } return 0; } static int BitBlt_WHITENESS_32bpp(HGDI_DC hdcDest, int nXDest, int nYDest, int nWidth, int nHeight) { int y; uint8* dstp; for (y = 0; y < nHeight; y++) { dstp = gdi_get_bitmap_pointer(hdcDest, nXDest, nYDest + y); if (dstp != 0) memset(dstp, 0xFF, nWidth * hdcDest->bytesPerPixel); } return 0; } static int BitBlt_SRCCOPY_32bpp(HGDI_DC hdcDest, int nXDest, int nYDest, int nWidth, int nHeight, HGDI_DC hdcSrc, int nXSrc, int nYSrc) { int y; uint8* srcp; uint8* dstp; if ((hdcDest->selectedObject != hdcSrc->selectedObject) || gdi_CopyOverlap(nXDest, nYDest, nWidth, nHeight, nXSrc, nYSrc) == 0) { for (y = 0; y < nHeight; y++) { srcp = gdi_get_bitmap_pointer(hdcSrc, nXSrc, nYSrc + y); dstp = gdi_get_bitmap_pointer(hdcDest, nXDest, nYDest + y); if (srcp != 0 && dstp != 0) memcpy(dstp, srcp, nWidth * hdcDest->bytesPerPixel); } return 0; } if (nYSrc < nYDest) { /* copy down (bottom to top) */ for (y = nHeight - 1; y >= 0; y--) { srcp = gdi_get_bitmap_pointer(hdcSrc, nXSrc, nYSrc + y); dstp = gdi_get_bitmap_pointer(hdcDest, nXDest, nYDest + y); if (srcp != 0 && dstp != 0) memmove(dstp, srcp, nWidth * hdcDest->bytesPerPixel); } } else if (nYSrc > nYDest || nXSrc > nXDest) { /* copy up or left (top top bottom) */ for (y = 0; y < nHeight; y++) { srcp = gdi_get_bitmap_pointer(hdcSrc, nXSrc, nYSrc + y); dstp = gdi_get_bitmap_pointer(hdcDest, nXDest, nYDest + y); if (srcp != 0 && dstp != 0) memmove(dstp, srcp, nWidth * hdcDest->bytesPerPixel); } } else { /* copy straight right */ for (y = 0; y < nHeight; y++) { srcp = gdi_get_bitmap_pointer(hdcSrc, nXSrc, nYSrc + y); dstp = gdi_get_bitmap_pointer(hdcDest, nXDest, nYDest + y); if (srcp != 0 && dstp != 0) memmove(dstp, srcp, nWidth * hdcDest->bytesPerPixel); } } return 0; } static int BitBlt_NOTSRCCOPY_32bpp(HGDI_DC hdcDest, int nXDest, int nYDest, int nWidth, int nHeight, HGDI_DC hdcSrc, int nXSrc, int nYSrc) { int x, y; uint32* srcp; uint32* dstp; for (y = 0; y < nHeight; y++) { srcp = (uint32*) gdi_get_bitmap_pointer(hdcSrc, nXSrc, nYSrc + y); dstp = (uint32*) gdi_get_bitmap_pointer(hdcDest, nXDest, nYDest + y); if (dstp != 0) { for (x = 0; x < nWidth; x++) { *dstp = ~(*srcp); srcp++; dstp++; } } } return 0; } static int BitBlt_DSTINVERT_32bpp(HGDI_DC hdcDest, int nXDest, int nYDest, int nWidth, int nHeight) { int x, y; uint32* dstp; for (y = 0; y < nHeight; y++) { dstp = (uint32*) gdi_get_bitmap_pointer(hdcDest, nXDest, nYDest + y); if (dstp != 0) { for (x = 0; x < nWidth; x++) { *dstp = ~(*dstp); dstp++; } } } return 0; } static int BitBlt_SRCERASE_32bpp(HGDI_DC hdcDest, int nXDest, int nYDest, int nWidth, int nHeight, HGDI_DC hdcSrc, int nXSrc, int nYSrc) { int x, y; uint32* srcp; uint32* dstp; for (y = 0; y < nHeight; y++) { srcp = (uint32*) gdi_get_bitmap_pointer(hdcSrc, nXSrc, nYSrc + y); dstp = (uint32*) gdi_get_bitmap_pointer(hdcDest, nXDest, nYDest + y); if (dstp != 0) { for (x = 0; x < nWidth; x++) { *dstp = *srcp & ~(*dstp); srcp++; dstp++; } } } return 0; } static int BitBlt_NOTSRCERASE_32bpp(HGDI_DC hdcDest, int nXDest, int nYDest, int nWidth, int nHeight, HGDI_DC hdcSrc, int nXSrc, int nYSrc) { int x, y; uint32* srcp; uint32* dstp; for (y = 0; y < nHeight; y++) { srcp = (uint32*) gdi_get_bitmap_pointer(hdcSrc, nXSrc, nYSrc + y); dstp = (uint32*) gdi_get_bitmap_pointer(hdcDest, nXDest, nYDest + y); if (dstp != 0) { for (x = 0; x < nWidth; x++) { *dstp = ~(*srcp) & ~(*dstp); srcp++; dstp++; } } } return 0; } static int BitBlt_SRCINVERT_32bpp(HGDI_DC hdcDest, int nXDest, int nYDest, int nWidth, int nHeight, HGDI_DC hdcSrc, int nXSrc, int nYSrc) { int x, y; uint32* srcp; uint32* dstp; for (y = 0; y < nHeight; y++) { srcp = (uint32*) gdi_get_bitmap_pointer(hdcSrc, nXSrc, nYSrc + y); dstp = (uint32*) gdi_get_bitmap_pointer(hdcDest, nXDest, nYDest + y); if (dstp != 0) { for (x = 0; x < nWidth; x++) { *dstp ^= *srcp; srcp++; dstp++; } } } return 0; } static int BitBlt_SRCAND_32bpp(HGDI_DC hdcDest, int nXDest, int nYDest, int nWidth, int nHeight, HGDI_DC hdcSrc, int nXSrc, int nYSrc) { int x, y; uint32* srcp; uint32* dstp; for (y = 0; y < nHeight; y++) { srcp = (uint32*) gdi_get_bitmap_pointer(hdcSrc, nXSrc, nYSrc + y); dstp = (uint32*) gdi_get_bitmap_pointer(hdcDest, nXDest, nYDest + y); if (dstp != 0) { for (x = 0; x < nWidth; x++) { *dstp &= *srcp; srcp++; dstp++; } } } return 0; } static int BitBlt_SRCPAINT_32bpp(HGDI_DC hdcDest, int nXDest, int nYDest, int nWidth, int nHeight, HGDI_DC hdcSrc, int nXSrc, int nYSrc) { int x, y; uint32* srcp; uint32* dstp; for (y = 0; y < nHeight; y++) { srcp = (uint32*) gdi_get_bitmap_pointer(hdcSrc, nXSrc, nYSrc + y); dstp = (uint32*) gdi_get_bitmap_pointer(hdcDest, nXDest, nYDest + y); if (dstp != 0) { for (x = 0; x < nWidth; x++) { *dstp |= *srcp; srcp++; dstp++; } } } return 0; } static int BitBlt_DSPDxax_32bpp(HGDI_DC hdcDest, int nXDest, int nYDest, int nWidth, int nHeight, HGDI_DC hdcSrc, int nXSrc, int nYSrc) { int x, y; uint8* srcp; uint8* dstp; uint8* patp; uint32 color32; HGDI_BITMAP hSrcBmp; /* D = (S & P) | (~S & D) */ /* DSPDxax, used to draw glyphs */ color32 = gdi_get_color_32bpp(hdcDest, hdcDest->textColor); hSrcBmp = (HGDI_BITMAP) hdcSrc->selectedObject; srcp = hSrcBmp->data; if (hdcSrc->bytesPerPixel != 1) { printf("BitBlt_DSPDxax expects 1 bpp, unimplemented for %d\n", hdcSrc->bytesPerPixel); return 0; } for (y = 0; y < nHeight; y++) { srcp = gdi_get_bitmap_pointer(hdcSrc, nXSrc, nYSrc + y); dstp = gdi_get_bitmap_pointer(hdcDest, nXDest, nYDest + y); if (dstp != 0) { for (x = 0; x < nWidth; x++) { patp = (uint8*) &color32; *dstp = (*srcp & *patp) | (~(*srcp) & *dstp); dstp++; patp++; *dstp = (*srcp & *patp) | (~(*srcp) & *dstp); dstp++; patp++; *dstp = (*srcp & *patp) | (~(*srcp) & *dstp); dstp += 2; srcp++; } } } return 0; } static int BitBlt_SPna_32bpp(HGDI_DC hdcDest, int nXDest, int nYDest, int nWidth, int nHeight, HGDI_DC hdcSrc, int nXSrc, int nYSrc) { int x, y; uint32* srcp; uint32* dstp; uint32* patp; for (y = 0; y < nHeight; y++) { srcp = (uint32*) gdi_get_bitmap_pointer(hdcSrc, nXSrc, nYSrc + y); dstp = (uint32*) gdi_get_bitmap_pointer(hdcDest, nXDest, nYDest + y); if (dstp != 0) { for (x = 0; x < nWidth; x++) { patp = (uint32*) gdi_get_brush_pointer(hdcDest, x, y); *dstp = *srcp & ~(*patp); srcp++; dstp++; } } } return 0; } static int BitBlt_DSna_32bpp(HGDI_DC hdcDest, int nXDest, int nYDest, int nWidth, int nHeight, HGDI_DC hdcSrc, int nXSrc, int nYSrc) { int x, y; uint32* srcp; uint32* dstp; for (y = 0; y < nHeight; y++) { srcp = (uint32*) gdi_get_bitmap_pointer(hdcSrc, nXSrc, nYSrc + y); dstp = (uint32*) gdi_get_bitmap_pointer(hdcDest, nXDest, nYDest + y); if (dstp != 0) { for (x = 0; x < nWidth; x++) { *dstp = ~(*srcp) & (*dstp); srcp++; dstp++; } } } return 0; } static int BitBlt_DPa_32bpp(HGDI_DC hdcDest, int nXDest, int nYDest, int nWidth, int nHeight) { int x, y; uint32* dstp; uint32* patp; for (y = 0; y < nHeight; y++) { dstp = (uint32*) gdi_get_bitmap_pointer(hdcDest, nXDest, nYDest + y); if (dstp != 0) { for (x = 0; x < nWidth; x++) { patp = (uint32*) gdi_get_brush_pointer(hdcDest, x, y); *dstp = *dstp & *patp; dstp++; } } } return 0; } static int BitBlt_PDxn_32bpp(HGDI_DC hdcDest, int nXDest, int nYDest, int nWidth, int nHeight) { int x, y; uint32* dstp; uint32* patp; for (y = 0; y < nHeight; y++) { dstp = (uint32*) gdi_get_bitmap_pointer(hdcDest, nXDest, nYDest + y); if (dstp != 0) { for (x = 0; x < nWidth; x++) { patp = (uint32*) gdi_get_brush_pointer(hdcDest, x, y); *dstp = *dstp ^ ~(*patp); dstp++; } } } return 0; } static int BitBlt_MERGECOPY_32bpp(HGDI_DC hdcDest, int nXDest, int nYDest, int nWidth, int nHeight, HGDI_DC hdcSrc, int nXSrc, int nYSrc) { int x, y; uint32* srcp; uint32* dstp; uint32* patp; for (y = 0; y < nHeight; y++) { srcp = (uint32*) gdi_get_bitmap_pointer(hdcSrc, nXSrc, nYSrc + y); dstp = (uint32*) gdi_get_bitmap_pointer(hdcDest, nXDest, nYDest + y); if (dstp != 0) { for (x = 0; x < nWidth; x++) { patp = (uint32*) gdi_get_brush_pointer(hdcDest, x, y); *dstp = *srcp & *patp; srcp++; dstp++; } } } return 0; } static int BitBlt_MERGEPAINT_32bpp(HGDI_DC hdcDest, int nXDest, int nYDest, int nWidth, int nHeight, HGDI_DC hdcSrc, int nXSrc, int nYSrc) { int x, y; uint32* srcp; uint32* dstp; for (y = 0; y < nHeight; y++) { srcp = (uint32*) gdi_get_bitmap_pointer(hdcSrc, nXSrc, nYSrc + y); dstp = (uint32*) gdi_get_bitmap_pointer(hdcDest, nXDest, nYDest + y); if (dstp != 0) { for (x = 0; x < nWidth; x++) { *dstp = ~(*srcp) | *dstp; srcp++; dstp++; } } } return 0; } static int BitBlt_PATCOPY_32bpp(HGDI_DC hdcDest, int nXDest, int nYDest, int nWidth, int nHeight) { int x, y; uint32* dstp; uint32* patp; uint32 color32; if (hdcDest->brush->style == GDI_BS_SOLID) { color32 = gdi_get_color_32bpp(hdcDest, hdcDest->brush->color); for (y = 0; y < nHeight; y++) { dstp = (uint32*) gdi_get_bitmap_pointer(hdcDest, nXDest, nYDest + y); if (dstp != 0) { for (x = 0; x < nWidth; x++) { *dstp = color32; dstp++; } } } } else { for (y = 0; y < nHeight; y++) { dstp = (uint32*) gdi_get_bitmap_pointer(hdcDest, nXDest, nYDest + y); if (dstp != 0) { for (x = 0; x < nWidth; x++) { patp = (uint32*) gdi_get_brush_pointer(hdcDest, x, y); *dstp = *patp; dstp++; } } } } return 0; } static int BitBlt_PATINVERT_32bpp(HGDI_DC hdcDest, int nXDest, int nYDest, int nWidth, int nHeight) { int x, y; uint32* dstp; uint32* patp; uint32 color32; if (hdcDest->brush->style == GDI_BS_SOLID) { color32 = gdi_get_color_32bpp(hdcDest, hdcDest->brush->color); for (y = 0; y < nHeight; y++) { dstp = (uint32*) gdi_get_bitmap_pointer(hdcDest, nXDest, nYDest + y); if (dstp != 0) { for (x = 0; x < nWidth; x++) { *dstp ^= color32; dstp++; } } } } else { for (y = 0; y < nHeight; y++) { dstp = (uint32*) gdi_get_bitmap_pointer(hdcDest, nXDest, nYDest + y); if (dstp != 0) { for (x = 0; x < nWidth; x++) { patp = (uint32*) gdi_get_brush_pointer(hdcDest, x, y); *dstp = *patp ^ *dstp; dstp++; } } } } return 0; } static int BitBlt_PATPAINT_32bpp(HGDI_DC hdcDest, int nXDest, int nYDest, int nWidth, int nHeight, HGDI_DC hdcSrc, int nXSrc, int nYSrc) { int x, y; uint32* srcp; uint32* dstp; uint32* patp; for (y = 0; y < nHeight; y++) { srcp = (uint32*) gdi_get_bitmap_pointer(hdcSrc, nXSrc, nYSrc + y); dstp = (uint32*) gdi_get_bitmap_pointer(hdcDest, nXDest, nYDest + y); if (dstp != 0) { for (x = 0; x < nWidth; x++) { patp = (uint32*) gdi_get_brush_pointer(hdcDest, x, y); *dstp = *dstp | (*patp | ~(*srcp)); srcp++; dstp++; } } } return 0; } int BitBlt_32bpp(HGDI_DC hdcDest, int nXDest, int nYDest, int nWidth, int nHeight, HGDI_DC hdcSrc, int nXSrc, int nYSrc, int rop) { if (hdcSrc != NULL) { if (gdi_ClipCoords(hdcDest, &nXDest, &nYDest, &nWidth, &nHeight, &nXSrc, &nYSrc) == 0) return 0; } else { if (gdi_ClipCoords(hdcDest, &nXDest, &nYDest, &nWidth, &nHeight, NULL, NULL) == 0) return 0; } gdi_InvalidateRegion(hdcDest, nXDest, nYDest, nWidth, nHeight); switch (rop) { case GDI_BLACKNESS: return BitBlt_BLACKNESS_32bpp(hdcDest, nXDest, nYDest, nWidth, nHeight); break; case GDI_WHITENESS: return BitBlt_WHITENESS_32bpp(hdcDest, nXDest, nYDest, nWidth, nHeight); break; case GDI_SRCCOPY: return BitBlt_SRCCOPY_32bpp(hdcDest, nXDest, nYDest, nWidth, nHeight, hdcSrc, nXSrc, nYSrc); break; case GDI_SPna: return BitBlt_SPna_32bpp(hdcDest, nXDest, nYDest, nWidth, nHeight, hdcSrc, nXSrc, nYSrc); break; case GDI_DSna: return BitBlt_DSna_32bpp(hdcDest, nXDest, nYDest, nWidth, nHeight, hdcSrc, nXSrc, nYSrc); break; case GDI_DSPDxax: return BitBlt_DSPDxax_32bpp(hdcDest, nXDest, nYDest, nWidth, nHeight, hdcSrc, nXSrc, nYSrc); break; case GDI_NOTSRCCOPY: return BitBlt_NOTSRCCOPY_32bpp(hdcDest, nXDest, nYDest, nWidth, nHeight, hdcSrc, nXSrc, nYSrc); break; case GDI_DSTINVERT: return BitBlt_DSTINVERT_32bpp(hdcDest, nXDest, nYDest, nWidth, nHeight); break; case GDI_SRCERASE: return BitBlt_SRCERASE_32bpp(hdcDest, nXDest, nYDest, nWidth, nHeight, hdcSrc, nXSrc, nYSrc); break; case GDI_NOTSRCERASE: return BitBlt_NOTSRCERASE_32bpp(hdcDest, nXDest, nYDest, nWidth, nHeight, hdcSrc, nXSrc, nYSrc); break; case GDI_SRCINVERT: return BitBlt_SRCINVERT_32bpp(hdcDest, nXDest, nYDest, nWidth, nHeight, hdcSrc, nXSrc, nYSrc); break; case GDI_SRCAND: return BitBlt_SRCAND_32bpp(hdcDest, nXDest, nYDest, nWidth, nHeight, hdcSrc, nXSrc, nYSrc); break; case GDI_SRCPAINT: return BitBlt_SRCPAINT_32bpp(hdcDest, nXDest, nYDest, nWidth, nHeight, hdcSrc, nXSrc, nYSrc); break; case GDI_MERGECOPY: return BitBlt_MERGECOPY_32bpp(hdcDest, nXDest, nYDest, nWidth, nHeight, hdcSrc, nXSrc, nYSrc); break; case GDI_MERGEPAINT: return BitBlt_MERGEPAINT_32bpp(hdcDest, nXDest, nYDest, nWidth, nHeight, hdcSrc, nXSrc, nYSrc); break; case GDI_PATCOPY: return BitBlt_PATCOPY_32bpp(hdcDest, nXDest, nYDest, nWidth, nHeight); break; case GDI_PATINVERT: return BitBlt_PATINVERT_32bpp(hdcDest, nXDest, nYDest, nWidth, nHeight); break; case GDI_PATPAINT: return BitBlt_PATPAINT_32bpp(hdcDest, nXDest, nYDest, nWidth, nHeight, hdcSrc, nXSrc, nYSrc); break; } printf("BitBlt: unknown rop: 0x%08X\n", rop); return 1; } int PatBlt_32bpp(HGDI_DC hdc, int nXLeft, int nYLeft, int nWidth, int nHeight, int rop) { if (gdi_ClipCoords(hdc, &nXLeft, &nYLeft, &nWidth, &nHeight, NULL, NULL) == 0) return 0; gdi_InvalidateRegion(hdc, nXLeft, nYLeft, nWidth, nHeight); switch (rop) { case GDI_PATCOPY: return BitBlt_PATCOPY_32bpp(hdc, nXLeft, nYLeft, nWidth, nHeight); break; case GDI_PATINVERT: return BitBlt_PATINVERT_32bpp(hdc, nXLeft, nYLeft, nWidth, nHeight); break; case GDI_DSTINVERT: return BitBlt_DSTINVERT_32bpp(hdc, nXLeft, nYLeft, nWidth, nHeight); break; case GDI_BLACKNESS: return BitBlt_BLACKNESS_32bpp(hdc, nXLeft, nYLeft, nWidth, nHeight); break; case GDI_WHITENESS: return BitBlt_WHITENESS_32bpp(hdc, nXLeft, nYLeft, nWidth, nHeight); break; case GDI_DPa: return BitBlt_DPa_32bpp(hdc, nXLeft, nYLeft, nWidth, nHeight); break; case GDI_PDxn: return BitBlt_PDxn_32bpp(hdc, nXLeft, nYLeft, nWidth, nHeight); break; default: break; } printf("PatBlt: unknown rop: 0x%08X\n", rop); return 1; } INLINE void SetPixel_BLACK_32bpp(uint32* pixel, uint32* pen) { /* D = 0 */ *pixel = 0; } INLINE void SetPixel_NOTMERGEPEN_32bpp(uint32* pixel, uint32* pen) { /* D = ~(D | P) */ *pixel = ~(*pixel | *pen); } INLINE void SetPixel_MASKNOTPEN_32bpp(uint32* pixel, uint32* pen) { /* D = D & ~P */ *pixel &= ~(*pen); } INLINE void SetPixel_NOTCOPYPEN_32bpp(uint32* pixel, uint32* pen) { /* D = ~P */ *pixel = ~(*pen); } INLINE void SetPixel_MASKPENNOT_32bpp(uint32* pixel, uint32* pen) { /* D = P & ~D */ *pixel = *pen & ~*pixel; } INLINE void SetPixel_NOT_32bpp(uint32* pixel, uint32* pen) { /* D = ~D */ *pixel = ~(*pixel); } INLINE void SetPixel_XORPEN_32bpp(uint32* pixel, uint32* pen) { /* D = D ^ P */ *pixel = *pixel ^ *pen; } INLINE void SetPixel_NOTMASKPEN_32bpp(uint32* pixel, uint32* pen) { /* D = ~(D & P) */ *pixel = ~(*pixel & *pen); } INLINE void SetPixel_MASKPEN_32bpp(uint32* pixel, uint32* pen) { /* D = D & P */ *pixel &= *pen; } INLINE void SetPixel_NOTXORPEN_32bpp(uint32* pixel, uint32* pen) { /* D = ~(D ^ P) */ *pixel = ~(*pixel ^ *pen); } INLINE void SetPixel_NOP_32bpp(uint32* pixel, uint32* pen) { /* D = D */ } INLINE void SetPixel_MERGENOTPEN_32bpp(uint32* pixel, uint32* pen) { /* D = D | ~P */ *pixel |= ~(*pen); } INLINE void SetPixel_COPYPEN_32bpp(uint32* pixel, uint32* pen) { /* D = P */ *pixel = *pen; } INLINE void SetPixel_MERGEPENNOT_32bpp(uint32* pixel, uint32* pen) { /* D = P | ~D */ *pixel = *pen | ~(*pixel); } INLINE void SetPixel_MERGEPEN_32bpp(uint32* pixel, uint32* pen) { /* D = P | D */ *pixel |= *pen; } INLINE void SetPixel_WHITE_32bpp(uint32* pixel, uint32* pen) { /* D = 1 */ *pixel = 0xFFFFFF; } #define PIXEL_TYPE uint32 #define GDI_GET_POINTER gdi_GetPointer_32bpp #define GDI_GET_PEN_COLOR gdi_GetPenColor_32bpp #define LINE_TO LineTo_BLACK_32bpp #define SET_PIXEL_ROP2 SetPixel_BLACK_32bpp #include "include/line.c" #undef LINE_TO #undef SET_PIXEL_ROP2 #define LINE_TO LineTo_NOTMERGEPEN_32bpp #define SET_PIXEL_ROP2 SetPixel_NOTMERGEPEN_32bpp #include "include/line.c" #undef LINE_TO #undef SET_PIXEL_ROP2 #define LINE_TO LineTo_MASKNOTPEN_32bpp #define SET_PIXEL_ROP2 SetPixel_MASKNOTPEN_32bpp #include "include/line.c" #undef LINE_TO #undef SET_PIXEL_ROP2 #define LINE_TO LineTo_NOTCOPYPEN_32bpp #define SET_PIXEL_ROP2 SetPixel_NOTCOPYPEN_32bpp #include "include/line.c" #undef LINE_TO #undef SET_PIXEL_ROP2 #define LINE_TO LineTo_MASKPENNOT_32bpp #define SET_PIXEL_ROP2 SetPixel_MASKPENNOT_32bpp #include "include/line.c" #undef LINE_TO #undef SET_PIXEL_ROP2 #define LINE_TO LineTo_NOT_32bpp #define SET_PIXEL_ROP2 SetPixel_NOT_32bpp #include "include/line.c" #undef LINE_TO #undef SET_PIXEL_ROP2 #define LINE_TO LineTo_XORPEN_32bpp #define SET_PIXEL_ROP2 SetPixel_XORPEN_32bpp #include "include/line.c" #undef LINE_TO #undef SET_PIXEL_ROP2 #define LINE_TO LineTo_NOTMASKPEN_32bpp #define SET_PIXEL_ROP2 SetPixel_NOTMASKPEN_32bpp #include "include/line.c" #undef LINE_TO #undef SET_PIXEL_ROP2 #define LINE_TO LineTo_MASKPEN_32bpp #define SET_PIXEL_ROP2 SetPixel_MASKPEN_32bpp #include "include/line.c" #undef LINE_TO #undef SET_PIXEL_ROP2 #define LINE_TO LineTo_NOTXORPEN_32bpp #define SET_PIXEL_ROP2 SetPixel_NOTXORPEN_32bpp #include "include/line.c" #undef LINE_TO #undef SET_PIXEL_ROP2 #define LINE_TO LineTo_NOP_32bpp #define SET_PIXEL_ROP2 SetPixel_NOP_32bpp #include "include/line.c" #undef LINE_TO #undef SET_PIXEL_ROP2 #define LINE_TO LineTo_MERGENOTPEN_32bpp #define SET_PIXEL_ROP2 SetPixel_MERGENOTPEN_32bpp #include "include/line.c" #undef LINE_TO #undef SET_PIXEL_ROP2 #define LINE_TO LineTo_COPYPEN_32bpp #define SET_PIXEL_ROP2 SetPixel_COPYPEN_32bpp #include "include/line.c" #undef LINE_TO #undef SET_PIXEL_ROP2 #define LINE_TO LineTo_MERGEPENNOT_32bpp #define SET_PIXEL_ROP2 SetPixel_MERGEPENNOT_32bpp #include "include/line.c" #undef LINE_TO #undef SET_PIXEL_ROP2 #define LINE_TO LineTo_MERGEPEN_32bpp #define SET_PIXEL_ROP2 SetPixel_MERGEPEN_32bpp #include "include/line.c" #undef LINE_TO #undef SET_PIXEL_ROP2 #define LINE_TO LineTo_WHITE_32bpp #define SET_PIXEL_ROP2 SetPixel_WHITE_32bpp #include "include/line.c" #undef LINE_TO #undef SET_PIXEL_ROP2 #undef PIXEL_TYPE #undef GDI_GET_POINTER #undef GDI_GET_PEN_COLOR pLineTo_32bpp LineTo_ROP2_32bpp[32] = { LineTo_BLACK_32bpp, LineTo_NOTMERGEPEN_32bpp, LineTo_MASKNOTPEN_32bpp, LineTo_NOTCOPYPEN_32bpp, LineTo_MASKPENNOT_32bpp, LineTo_NOT_32bpp, LineTo_XORPEN_32bpp, LineTo_NOTMASKPEN_32bpp, LineTo_MASKPEN_32bpp, LineTo_NOTXORPEN_32bpp, LineTo_NOP_32bpp, LineTo_MERGENOTPEN_32bpp, LineTo_COPYPEN_32bpp, LineTo_MERGEPENNOT_32bpp, LineTo_MERGEPEN_32bpp, LineTo_WHITE_32bpp }; int LineTo_32bpp(HGDI_DC hdc, int nXEnd, int nYEnd) { pLineTo_32bpp _LineTo; int rop2 = gdi_GetROP2(hdc) - 1; _LineTo = LineTo_ROP2_32bpp[rop2]; if (_LineTo != NULL) return _LineTo(hdc, nXEnd, nYEnd); else return 0; } FreeRDP-1.0.2/libfreerdp-gdi/8bpp.c000066400000000000000000000476231207112532300166450ustar00rootroot00000000000000/** * FreeRDP: A Remote Desktop Protocol Client * GDI 8bpp Internal Buffer Routines * * Copyright 2010-2011 Marc-Andre Moreau * * 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. */ #include #include #include #include #include #include #include #include #include #include #include #include #include int FillRect_8bpp(HGDI_DC hdc, HGDI_RECT rect, HGDI_BRUSH hbr) { /* TODO: Implement 8bpp FillRect() */ return 0; } static int BitBlt_BLACKNESS_8bpp(HGDI_DC hdcDest, int nXDest, int nYDest, int nWidth, int nHeight) { int y; uint8* dstp; for (y = 0; y < nHeight; y++) { dstp = gdi_get_bitmap_pointer(hdcDest, nXDest, nYDest + y); if (dstp != 0) memset(dstp, 0, nWidth * hdcDest->bytesPerPixel); } return 0; } static int BitBlt_WHITENESS_8bpp(HGDI_DC hdcDest, int nXDest, int nYDest, int nWidth, int nHeight) { int y; uint8* dstp; for (y = 0; y < nHeight; y++) { dstp = gdi_get_bitmap_pointer(hdcDest, nXDest, nYDest + y); if (dstp != 0) memset(dstp, 0xFF, nWidth * hdcDest->bytesPerPixel); } return 0; } static int BitBlt_SRCCOPY_8bpp(HGDI_DC hdcDest, int nXDest, int nYDest, int nWidth, int nHeight, HGDI_DC hdcSrc, int nXSrc, int nYSrc) { int y; uint8* srcp; uint8* dstp; if ((hdcDest->selectedObject != hdcSrc->selectedObject) || gdi_CopyOverlap(nXDest, nYDest, nWidth, nHeight, nXSrc, nYSrc) == 0) { for (y = 0; y < nHeight; y++) { srcp = gdi_get_bitmap_pointer(hdcSrc, nXSrc, nYSrc + y); dstp = gdi_get_bitmap_pointer(hdcDest, nXDest, nYDest + y); if (srcp != 0 && dstp != 0) memcpy(dstp, srcp, nWidth * hdcDest->bytesPerPixel); } return 0; } if (nYSrc < nYDest) { /* copy down (bottom to top) */ for (y = nHeight - 1; y >= 0; y--) { srcp = gdi_get_bitmap_pointer(hdcSrc, nXSrc, nYSrc + y); dstp = gdi_get_bitmap_pointer(hdcDest, nXDest, nYDest + y); if (srcp != 0 && dstp != 0) memmove(dstp, srcp, nWidth * hdcDest->bytesPerPixel); } } else if (nYSrc > nYDest || nXSrc > nXDest) { /* copy up or left (top top bottom) */ for (y = 0; y < nHeight; y++) { srcp = gdi_get_bitmap_pointer(hdcSrc, nXSrc, nYSrc + y); dstp = gdi_get_bitmap_pointer(hdcDest, nXDest, nYDest + y); if (srcp != 0 && dstp != 0) memmove(dstp, srcp, nWidth * hdcDest->bytesPerPixel); } } else { /* copy straight right */ for (y = 0; y < nHeight; y++) { srcp = gdi_get_bitmap_pointer(hdcSrc, nXSrc, nYSrc + y); dstp = gdi_get_bitmap_pointer(hdcDest, nXDest, nYDest + y); if (srcp != 0 && dstp != 0) memmove(dstp, srcp, nWidth * hdcDest->bytesPerPixel); } } return 0; } static int BitBlt_NOTSRCCOPY_8bpp(HGDI_DC hdcDest, int nXDest, int nYDest, int nWidth, int nHeight, HGDI_DC hdcSrc, int nXSrc, int nYSrc) { int x, y; uint8* srcp; uint8* dstp; for (y = 0; y < nHeight; y++) { srcp = gdi_get_bitmap_pointer(hdcSrc, nXSrc, nYSrc + y); dstp = gdi_get_bitmap_pointer(hdcDest, nXDest, nYDest + y); if (dstp != 0) { for (x = 0; x < nWidth; x++) { *dstp = ~(*srcp); srcp++; dstp++; } } } return 0; } static int BitBlt_DSTINVERT_8bpp(HGDI_DC hdcDest, int nXDest, int nYDest, int nWidth, int nHeight) { int x, y; uint8* dstp; for (y = 0; y < nHeight; y++) { dstp = gdi_get_bitmap_pointer(hdcDest, nXDest, nYDest + y); if (dstp != 0) { for (x = 0; x < nWidth; x++) { *dstp = ~(*dstp); dstp++; } } } return 0; } static int BitBlt_SRCERASE_8bpp(HGDI_DC hdcDest, int nXDest, int nYDest, int nWidth, int nHeight, HGDI_DC hdcSrc, int nXSrc, int nYSrc) { int x, y; uint8* srcp; uint8* dstp; for (y = 0; y < nHeight; y++) { srcp = gdi_get_bitmap_pointer(hdcSrc, nXSrc, nYSrc + y); dstp = gdi_get_bitmap_pointer(hdcDest, nXDest, nYDest + y); if (dstp != 0) { for (x = 0; x < nWidth; x++) { *dstp = *srcp & ~(*dstp); srcp++; dstp++; } } } return 0; } static int BitBlt_NOTSRCERASE_8bpp(HGDI_DC hdcDest, int nXDest, int nYDest, int nWidth, int nHeight, HGDI_DC hdcSrc, int nXSrc, int nYSrc) { int x, y; uint8* srcp; uint8* dstp; for (y = 0; y < nHeight; y++) { srcp = gdi_get_bitmap_pointer(hdcSrc, nXSrc, nYSrc + y); dstp = gdi_get_bitmap_pointer(hdcDest, nXDest, nYDest + y); if (dstp != 0) { for (x = 0; x < nWidth; x++) { *dstp = ~(*srcp) & ~(*dstp); srcp++; dstp++; } } } return 0; } static int BitBlt_SRCINVERT_8bpp(HGDI_DC hdcDest, int nXDest, int nYDest, int nWidth, int nHeight, HGDI_DC hdcSrc, int nXSrc, int nYSrc) { int x, y; uint8* srcp; uint8* dstp; for (y = 0; y < nHeight; y++) { srcp = gdi_get_bitmap_pointer(hdcSrc, nXSrc, nYSrc + y); dstp = gdi_get_bitmap_pointer(hdcDest, nXDest, nYDest + y); if (dstp != 0) { for (x = 0; x < nWidth; x++) { *dstp ^= *srcp; srcp++; dstp++; } } } return 0; } static int BitBlt_SRCAND_8bpp(HGDI_DC hdcDest, int nXDest, int nYDest, int nWidth, int nHeight, HGDI_DC hdcSrc, int nXSrc, int nYSrc) { int x, y; uint8* srcp; uint8* dstp; for (y = 0; y < nHeight; y++) { srcp = gdi_get_bitmap_pointer(hdcSrc, nXSrc, nYSrc + y); dstp = gdi_get_bitmap_pointer(hdcDest, nXDest, nYDest + y); if (dstp != 0) { for (x = 0; x < nWidth; x++) { *dstp &= *srcp; srcp++; dstp++; } } } return 0; } static int BitBlt_SRCPAINT_8bpp(HGDI_DC hdcDest, int nXDest, int nYDest, int nWidth, int nHeight, HGDI_DC hdcSrc, int nXSrc, int nYSrc) { int x, y; uint8* srcp; uint8* dstp; for (y = 0; y < nHeight; y++) { srcp = gdi_get_bitmap_pointer(hdcSrc, nXSrc, nYSrc + y); dstp = gdi_get_bitmap_pointer(hdcDest, nXDest, nYDest + y); if (dstp != 0) { for (x = 0; x < nWidth; x++) { *dstp |= *srcp; srcp++; dstp++; } } } return 0; } static int BitBlt_DSPDxax_8bpp(HGDI_DC hdcDest, int nXDest, int nYDest, int nWidth, int nHeight, HGDI_DC hdcSrc, int nXSrc, int nYSrc) { /* TODO: Implement 8bpp DSPDxax BitBlt */ return 0; } static int BitBlt_SPna_8bpp(HGDI_DC hdcDest, int nXDest, int nYDest, int nWidth, int nHeight, HGDI_DC hdcSrc, int nXSrc, int nYSrc) { int x, y; uint8* srcp; uint8* dstp; uint8* patp; for (y = 0; y < nHeight; y++) { srcp = gdi_get_bitmap_pointer(hdcSrc, nXSrc, nYSrc + y); dstp = gdi_get_bitmap_pointer(hdcDest, nXDest, nYDest + y); if (dstp != 0) { for (x = 0; x < nWidth; x++) { patp = gdi_get_brush_pointer(hdcDest, x, y); *dstp = *srcp & ~(*patp); patp++; srcp++; dstp++; } } } return 0; } static int BitBlt_DPa_8bpp(HGDI_DC hdcDest, int nXDest, int nYDest, int nWidth, int nHeight) { int x, y; uint8* dstp; uint8* patp; for (y = 0; y < nHeight; y++) { dstp = gdi_get_bitmap_pointer(hdcDest, nXDest, nYDest + y); if (dstp != 0) { for (x = 0; x < nWidth; x++) { patp = gdi_get_brush_pointer(hdcDest, x, y); *dstp = *dstp & *patp; dstp++; } } } return 0; } static int BitBlt_PDxn_8bpp(HGDI_DC hdcDest, int nXDest, int nYDest, int nWidth, int nHeight) { int x, y; uint8* dstp; uint8* patp; for (y = 0; y < nHeight; y++) { dstp = gdi_get_bitmap_pointer(hdcDest, nXDest, nYDest + y); if (dstp != 0) { for (x = 0; x < nWidth; x++) { patp = gdi_get_brush_pointer(hdcDest, x, y); *dstp = *dstp ^ ~(*patp); patp++; dstp++; } } } return 0; } static int BitBlt_DSna_8bpp(HGDI_DC hdcDest, int nXDest, int nYDest, int nWidth, int nHeight, HGDI_DC hdcSrc, int nXSrc, int nYSrc) { int x, y; uint8* srcp; uint8* dstp; for (y = 0; y < nHeight; y++) { srcp = gdi_get_bitmap_pointer(hdcSrc, nXSrc, nYSrc + y); dstp = gdi_get_bitmap_pointer(hdcDest, nXDest, nYDest + y); if (dstp != 0) { for (x = 0; x < nWidth; x++) { *dstp = ~(*srcp) & (*dstp); srcp++; dstp++; } } } return 0; } static int BitBlt_MERGECOPY_8bpp(HGDI_DC hdcDest, int nXDest, int nYDest, int nWidth, int nHeight, HGDI_DC hdcSrc, int nXSrc, int nYSrc) { int x, y; uint8* srcp; uint8* dstp; uint8* patp; for (y = 0; y < nHeight; y++) { srcp = gdi_get_bitmap_pointer(hdcSrc, nXSrc, nYSrc + y); dstp = gdi_get_bitmap_pointer(hdcDest, nXDest, nYDest + y); if (dstp != 0) { for (x = 0; x < nWidth; x++) { patp = gdi_get_brush_pointer(hdcDest, x, y); *dstp = *srcp & *patp; patp++; srcp++; dstp++; } } } return 0; } static int BitBlt_MERGEPAINT_8bpp(HGDI_DC hdcDest, int nXDest, int nYDest, int nWidth, int nHeight, HGDI_DC hdcSrc, int nXSrc, int nYSrc) { int x, y; uint8* srcp; uint8* dstp; for (y = 0; y < nHeight; y++) { srcp = gdi_get_bitmap_pointer(hdcSrc, nXSrc, nYSrc + y); dstp = gdi_get_bitmap_pointer(hdcDest, nXDest, nYDest + y); if (dstp != 0) { for (x = 0; x < nWidth; x++) { *dstp = ~(*srcp) | *dstp; srcp++; dstp++; } } } return 0; } static int BitBlt_PATCOPY_8bpp(HGDI_DC hdcDest, int nXDest, int nYDest, int nWidth, int nHeight) { int x, y; uint8* dstp; uint8* patp; uint8 palIndex; if(hdcDest->brush->style == GDI_BS_SOLID) { palIndex = ((hdcDest->brush->color >> 16) & 0xFF); for (y = 0; y < nHeight; y++) { dstp = gdi_get_bitmap_pointer(hdcDest, nXDest, nYDest + y); if (dstp != 0) { for (x = 0; x < nWidth; x++) { *dstp = palIndex; dstp++; } } } } else { for (y = 0; y < nHeight; y++) { dstp = gdi_get_bitmap_pointer(hdcDest, nXDest, nYDest + y); if (dstp != 0) { for (x = 0; x < nWidth; x++) { patp = gdi_get_brush_pointer(hdcDest, x, y); *dstp = *patp; patp++; dstp++; } } } } return 0; } static int BitBlt_PATINVERT_8bpp(HGDI_DC hdcDest, int nXDest, int nYDest, int nWidth, int nHeight) { int x, y; uint8* dstp; uint8* patp; uint8 palIndex; if(hdcDest->brush->style == GDI_BS_SOLID) { palIndex = ((hdcDest->brush->color >> 16) & 0xFF); for (y = 0; y < nHeight; y++) { dstp = gdi_get_bitmap_pointer(hdcDest, nXDest, nYDest + y); if (dstp != 0) { for (x = 0; x < nWidth; x++) { *dstp ^= palIndex; dstp++; } } } } else { for (y = 0; y < nHeight; y++) { dstp = gdi_get_bitmap_pointer(hdcDest, nXDest, nYDest + y); if (dstp != 0) { for (x = 0; x < nWidth; x++) { patp = gdi_get_brush_pointer(hdcDest, x, y); *dstp = *patp ^ *dstp; patp++; dstp++; } } } } return 0; } static int BitBlt_PATPAINT_8bpp(HGDI_DC hdcDest, int nXDest, int nYDest, int nWidth, int nHeight, HGDI_DC hdcSrc, int nXSrc, int nYSrc) { int x, y; uint8* srcp; uint8* dstp; uint8* patp; for (y = 0; y < nHeight; y++) { srcp = gdi_get_bitmap_pointer(hdcSrc, nXSrc, nYSrc + y); dstp = gdi_get_bitmap_pointer(hdcDest, nXDest, nYDest + y); if (dstp != 0) { for (x = 0; x < nWidth; x++) { patp = gdi_get_brush_pointer(hdcDest, x, y); *dstp = *dstp | (*patp | ~(*srcp)); patp++; srcp++; dstp++; } } } return 0; } int BitBlt_8bpp(HGDI_DC hdcDest, int nXDest, int nYDest, int nWidth, int nHeight, HGDI_DC hdcSrc, int nXSrc, int nYSrc, int rop) { if (hdcSrc != NULL) { if (gdi_ClipCoords(hdcDest, &nXDest, &nYDest, &nWidth, &nHeight, &nXSrc, &nYSrc) == 0) return 0; } else { if (gdi_ClipCoords(hdcDest, &nXDest, &nYDest, &nWidth, &nHeight, NULL, NULL) == 0) return 0; } gdi_InvalidateRegion(hdcDest, nXDest, nYDest, nWidth, nHeight); switch (rop) { case GDI_BLACKNESS: return BitBlt_BLACKNESS_8bpp(hdcDest, nXDest, nYDest, nWidth, nHeight); break; case GDI_WHITENESS: return BitBlt_WHITENESS_8bpp(hdcDest, nXDest, nYDest, nWidth, nHeight); break; case GDI_SRCCOPY: return BitBlt_SRCCOPY_8bpp(hdcDest, nXDest, nYDest, nWidth, nHeight, hdcSrc, nXSrc, nYSrc); break; case GDI_SPna: return BitBlt_SPna_8bpp(hdcDest, nXDest, nYDest, nWidth, nHeight, hdcSrc, nXSrc, nYSrc); break; case GDI_DSna: return BitBlt_DSna_8bpp(hdcDest, nXDest, nYDest, nWidth, nHeight, hdcSrc, nXSrc, nYSrc); break; case GDI_DSPDxax: return BitBlt_DSPDxax_8bpp(hdcDest, nXDest, nYDest, nWidth, nHeight, hdcSrc, nXSrc, nYSrc); break; case GDI_NOTSRCCOPY: return BitBlt_NOTSRCCOPY_8bpp(hdcDest, nXDest, nYDest, nWidth, nHeight, hdcSrc, nXSrc, nYSrc); break; case GDI_DSTINVERT: return BitBlt_DSTINVERT_8bpp(hdcDest, nXDest, nYDest, nWidth, nHeight); break; case GDI_SRCERASE: return BitBlt_SRCERASE_8bpp(hdcDest, nXDest, nYDest, nWidth, nHeight, hdcSrc, nXSrc, nYSrc); break; case GDI_NOTSRCERASE: return BitBlt_NOTSRCERASE_8bpp(hdcDest, nXDest, nYDest, nWidth, nHeight, hdcSrc, nXSrc, nYSrc); break; case GDI_SRCINVERT: return BitBlt_SRCINVERT_8bpp(hdcDest, nXDest, nYDest, nWidth, nHeight, hdcSrc, nXSrc, nYSrc); break; case GDI_SRCAND: return BitBlt_SRCAND_8bpp(hdcDest, nXDest, nYDest, nWidth, nHeight, hdcSrc, nXSrc, nYSrc); break; case GDI_SRCPAINT: return BitBlt_SRCPAINT_8bpp(hdcDest, nXDest, nYDest, nWidth, nHeight, hdcSrc, nXSrc, nYSrc); break; case GDI_MERGECOPY: return BitBlt_MERGECOPY_8bpp(hdcDest, nXDest, nYDest, nWidth, nHeight, hdcSrc, nXSrc, nYSrc); break; case GDI_MERGEPAINT: return BitBlt_MERGEPAINT_8bpp(hdcDest, nXDest, nYDest, nWidth, nHeight, hdcSrc, nXSrc, nYSrc); break; case GDI_PATCOPY: return BitBlt_PATCOPY_8bpp(hdcDest, nXDest, nYDest, nWidth, nHeight); break; case GDI_PATINVERT: return BitBlt_PATINVERT_8bpp(hdcDest, nXDest, nYDest, nWidth, nHeight); break; case GDI_PATPAINT: return BitBlt_PATPAINT_8bpp(hdcDest, nXDest, nYDest, nWidth, nHeight, hdcSrc, nXSrc, nYSrc); break; } printf("BitBlt: unknown rop: 0x%08X\n", rop); return 1; } int PatBlt_8bpp(HGDI_DC hdc, int nXLeft, int nYLeft, int nWidth, int nHeight, int rop) { if (gdi_ClipCoords(hdc, &nXLeft, &nYLeft, &nWidth, &nHeight, NULL, NULL) == 0) return 0; gdi_InvalidateRegion(hdc, nXLeft, nYLeft, nWidth, nHeight); switch (rop) { case GDI_PATCOPY: return BitBlt_PATCOPY_8bpp(hdc, nXLeft, nYLeft, nWidth, nHeight); break; case GDI_PATINVERT: return BitBlt_PATINVERT_8bpp(hdc, nXLeft, nYLeft, nWidth, nHeight); break; case GDI_DSTINVERT: return BitBlt_DSTINVERT_8bpp(hdc, nXLeft, nYLeft, nWidth, nHeight); break; case GDI_BLACKNESS: return BitBlt_BLACKNESS_8bpp(hdc, nXLeft, nYLeft, nWidth, nHeight); break; case GDI_WHITENESS: return BitBlt_WHITENESS_8bpp(hdc, nXLeft, nYLeft, nWidth, nHeight); break; case GDI_DPa: return BitBlt_DPa_8bpp(hdc, nXLeft, nYLeft, nWidth, nHeight); break; case GDI_PDxn: return BitBlt_PDxn_8bpp(hdc, nXLeft, nYLeft, nWidth, nHeight); break; default: break; } printf("PatBlt: unknown rop: 0x%08X\n", rop); return 1; } INLINE void SetPixel_BLACK_8bpp(uint8* pixel, uint8* pen) { /* D = 0 */ *pixel = 0; } INLINE void SetPixel_NOTMERGEPEN_8bpp(uint8* pixel, uint8* pen) { /* D = ~(D | P) */ *pixel = ~(*pixel | *pen); } INLINE void SetPixel_MASKNOTPEN_8bpp(uint8* pixel, uint8* pen) { /* D = D & ~P */ *pixel &= ~(*pen); } INLINE void SetPixel_NOTCOPYPEN_8bpp(uint8* pixel, uint8* pen) { /* D = ~P */ *pixel = ~(*pen); } INLINE void SetPixel_MASKPENNOT_8bpp(uint8* pixel, uint8* pen) { /* D = P & ~D */ *pixel = *pen & ~*pixel; } INLINE void SetPixel_NOT_8bpp(uint8* pixel, uint8* pen) { /* D = ~D */ *pixel = ~(*pixel); } INLINE void SetPixel_XORPEN_8bpp(uint8* pixel, uint8* pen) { /* D = D ^ P */ *pixel = *pixel ^ *pen; } INLINE void SetPixel_NOTMASKPEN_8bpp(uint8* pixel, uint8* pen) { /* D = ~(D & P) */ *pixel = ~(*pixel & *pen); } INLINE void SetPixel_MASKPEN_8bpp(uint8* pixel, uint8* pen) { /* D = D & P */ *pixel &= *pen; } INLINE void SetPixel_NOTXORPEN_8bpp(uint8* pixel, uint8* pen) { /* D = ~(D ^ P) */ *pixel = ~(*pixel ^ *pen); } INLINE void SetPixel_NOP_8bpp(uint8* pixel, uint8* pen) { /* D = D */ } INLINE void SetPixel_MERGENOTPEN_8bpp(uint8* pixel, uint8* pen) { /* D = D | ~P */ *pixel |= ~(*pen); } INLINE void SetPixel_COPYPEN_8bpp(uint8* pixel, uint8* pen) { /* D = P */ *pixel = *pen; } INLINE void SetPixel_MERGEPENNOT_8bpp(uint8* pixel, uint8* pen) { /* D = P | ~D */ *pixel = *pen | ~(*pixel); } INLINE void SetPixel_MERGEPEN_8bpp(uint8* pixel, uint8* pen) { /* D = P | D */ *pixel |= *pen; } INLINE void SetPixel_WHITE_8bpp(uint8* pixel, uint8* pen) { /* D = 1 */ *pixel = 0xFF; } #define PIXEL_TYPE uint8 #define GDI_GET_POINTER gdi_GetPointer_8bpp #define GDI_GET_PEN_COLOR gdi_GetPenColor_8bpp #define LINE_TO LineTo_BLACK_8bpp #define SET_PIXEL_ROP2 SetPixel_BLACK_8bpp #include "include/line.c" #undef LINE_TO #undef SET_PIXEL_ROP2 #define LINE_TO LineTo_NOTMERGEPEN_8bpp #define SET_PIXEL_ROP2 SetPixel_NOTMERGEPEN_8bpp #include "include/line.c" #undef LINE_TO #undef SET_PIXEL_ROP2 #define LINE_TO LineTo_MASKNOTPEN_8bpp #define SET_PIXEL_ROP2 SetPixel_MASKNOTPEN_8bpp #include "include/line.c" #undef LINE_TO #undef SET_PIXEL_ROP2 #define LINE_TO LineTo_NOTCOPYPEN_8bpp #define SET_PIXEL_ROP2 SetPixel_NOTCOPYPEN_8bpp #include "include/line.c" #undef LINE_TO #undef SET_PIXEL_ROP2 #define LINE_TO LineTo_MASKPENNOT_8bpp #define SET_PIXEL_ROP2 SetPixel_MASKPENNOT_8bpp #include "include/line.c" #undef LINE_TO #undef SET_PIXEL_ROP2 #define LINE_TO LineTo_NOT_8bpp #define SET_PIXEL_ROP2 SetPixel_NOT_8bpp #include "include/line.c" #undef LINE_TO #undef SET_PIXEL_ROP2 #define LINE_TO LineTo_XORPEN_8bpp #define SET_PIXEL_ROP2 SetPixel_XORPEN_8bpp #include "include/line.c" #undef LINE_TO #undef SET_PIXEL_ROP2 #define LINE_TO LineTo_NOTMASKPEN_8bpp #define SET_PIXEL_ROP2 SetPixel_NOTMASKPEN_8bpp #include "include/line.c" #undef LINE_TO #undef SET_PIXEL_ROP2 #define LINE_TO LineTo_MASKPEN_8bpp #define SET_PIXEL_ROP2 SetPixel_MASKPEN_8bpp #include "include/line.c" #undef LINE_TO #undef SET_PIXEL_ROP2 #define LINE_TO LineTo_NOTXORPEN_8bpp #define SET_PIXEL_ROP2 SetPixel_NOTXORPEN_8bpp #include "include/line.c" #undef LINE_TO #undef SET_PIXEL_ROP2 #define LINE_TO LineTo_NOP_8bpp #define SET_PIXEL_ROP2 SetPixel_NOP_8bpp #include "include/line.c" #undef LINE_TO #undef SET_PIXEL_ROP2 #define LINE_TO LineTo_MERGENOTPEN_8bpp #define SET_PIXEL_ROP2 SetPixel_MERGENOTPEN_8bpp #include "include/line.c" #undef LINE_TO #undef SET_PIXEL_ROP2 #define LINE_TO LineTo_COPYPEN_8bpp #define SET_PIXEL_ROP2 SetPixel_COPYPEN_8bpp #include "include/line.c" #undef LINE_TO #undef SET_PIXEL_ROP2 #define LINE_TO LineTo_MERGEPENNOT_8bpp #define SET_PIXEL_ROP2 SetPixel_MERGEPENNOT_8bpp #include "include/line.c" #undef LINE_TO #undef SET_PIXEL_ROP2 #define LINE_TO LineTo_MERGEPEN_8bpp #define SET_PIXEL_ROP2 SetPixel_MERGEPEN_8bpp #include "include/line.c" #undef LINE_TO #undef SET_PIXEL_ROP2 #define LINE_TO LineTo_WHITE_8bpp #define SET_PIXEL_ROP2 SetPixel_WHITE_8bpp #include "include/line.c" #undef LINE_TO #undef SET_PIXEL_ROP2 #undef PIXEL_TYPE #undef GDI_GET_POINTER #undef GDI_GET_PEN_COLOR pLineTo_8bpp LineTo_ROP2_8bpp[32] = { LineTo_BLACK_8bpp, LineTo_NOTMERGEPEN_8bpp, LineTo_MASKNOTPEN_8bpp, LineTo_NOTCOPYPEN_8bpp, LineTo_MASKPENNOT_8bpp, LineTo_NOT_8bpp, LineTo_XORPEN_8bpp, LineTo_NOTMASKPEN_8bpp, LineTo_MASKPEN_8bpp, LineTo_NOTXORPEN_8bpp, LineTo_NOP_8bpp, LineTo_MERGENOTPEN_8bpp, LineTo_COPYPEN_8bpp, LineTo_MERGEPENNOT_8bpp, LineTo_MERGEPEN_8bpp, LineTo_WHITE_8bpp }; int LineTo_8bpp(HGDI_DC hdc, int nXEnd, int nYEnd) { pLineTo_8bpp _LineTo; int rop2 = gdi_GetROP2(hdc) - 1; _LineTo = LineTo_ROP2_8bpp[rop2]; if (_LineTo != NULL) return _LineTo(hdc, nXEnd, nYEnd); else return 0; } FreeRDP-1.0.2/libfreerdp-gdi/CMakeLists.txt000066400000000000000000000025141207112532300203560ustar00rootroot00000000000000# FreeRDP: A Remote Desktop Protocol Client # libfreerdp-gdi cmake build script # # Copyright 2011 O.S. Systems Software Ltda. # Copyright 2011 Otavio Salvador # Copyright 2011 Marc-Andre Moreau # # 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(FREERDP_GDI_SRCS 8bpp.c 16bpp.c 32bpp.c bitmap.c brush.c clipping.c dc.c drawing.c line.c palette.c pen.c region.c shape.c graphics.c graphics.h gdi.c gdi.h) add_library(freerdp-gdi ${FREERDP_GDI_SRCS}) target_link_libraries(freerdp-gdi freerdp-core) target_link_libraries(freerdp-gdi freerdp-cache) target_link_libraries(freerdp-gdi freerdp-codec) set_target_properties(freerdp-gdi PROPERTIES VERSION ${FREERDP_VERSION_FULL} SOVERSION ${FREERDP_VERSION} PREFIX "lib") install(TARGETS freerdp-gdi DESTINATION ${CMAKE_INSTALL_LIBDIR}) FreeRDP-1.0.2/libfreerdp-gdi/bitmap.c000066400000000000000000000123641207112532300172420ustar00rootroot00000000000000/** * FreeRDP: A Remote Desktop Protocol Client * GDI Bitmap Functions * * Copyright 2010-2011 Marc-Andre Moreau * * 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. */ #include #include #include #include #include #include #include #include #include #include #include p_BitBlt BitBlt_[5] = { NULL, BitBlt_8bpp, BitBlt_16bpp, NULL, BitBlt_32bpp }; /** * Get pixel at the given coordinates.\n * @msdn{dd144909} * @param hdc device context * @param nXPos pixel x position * @param nYPos pixel y position * @return pixel color */ INLINE GDI_COLOR gdi_GetPixel(HGDI_DC hdc, int nXPos, int nYPos) { HGDI_BITMAP hBmp = (HGDI_BITMAP) hdc->selectedObject; GDI_COLOR* colorp = (GDI_COLOR*)&(hBmp->data[(nYPos * hBmp->width * hdc->bytesPerPixel) + nXPos * hdc->bytesPerPixel]); return (GDI_COLOR) *colorp; } INLINE uint8 gdi_GetPixel_8bpp(HGDI_BITMAP hBmp, int X, int Y) { return *((uint8*)&(hBmp->data[(Y * hBmp->width) + X])); } INLINE uint16 gdi_GetPixel_16bpp(HGDI_BITMAP hBmp, int X, int Y) { return *((uint16*)&(hBmp->data[(Y * hBmp->width * 2) + X * 2])); } INLINE uint32 gdi_GetPixel_32bpp(HGDI_BITMAP hBmp, int X, int Y) { return *((uint32*)&(hBmp->data[(Y * hBmp->width * 4) + X * 4])); } INLINE uint8* gdi_GetPointer_8bpp(HGDI_BITMAP hBmp, int X, int Y) { return ((uint8*)&(hBmp->data[(Y * hBmp->width) + X])); } INLINE uint16* gdi_GetPointer_16bpp(HGDI_BITMAP hBmp, int X, int Y) { return ((uint16*)&(hBmp->data[(Y * hBmp->width * 2) + X * 2])); } INLINE uint32* gdi_GetPointer_32bpp(HGDI_BITMAP hBmp, int X, int Y) { return ((uint32*)&(hBmp->data[(Y * hBmp->width * 4) + X * 4])); } /** * Set pixel at the given coordinates.\n * @msdn{dd145078} * @param hdc device context * @param X pixel x position * @param Y pixel y position * @param crColor new pixel color * @return */ INLINE GDI_COLOR gdi_SetPixel(HGDI_DC hdc, int X, int Y, GDI_COLOR crColor) { HGDI_BITMAP hBmp = (HGDI_BITMAP) hdc->selectedObject; *((GDI_COLOR*)&(hBmp->data[(Y * hBmp->width * hdc->bytesPerPixel) + X * hdc->bytesPerPixel])) = crColor; return 0; } INLINE void gdi_SetPixel_8bpp(HGDI_BITMAP hBmp, int X, int Y, uint8 pixel) { *((uint8*)&(hBmp->data[(Y * hBmp->width) + X])) = pixel; } INLINE void gdi_SetPixel_16bpp(HGDI_BITMAP hBmp, int X, int Y, uint16 pixel) { *((uint16*)&(hBmp->data[(Y * hBmp->width * 2) + X * 2])) = pixel; } INLINE void gdi_SetPixel_32bpp(HGDI_BITMAP hBmp, int X, int Y, uint32 pixel) { *((uint32*)&(hBmp->data[(Y * hBmp->width * 4) + X * 4])) = pixel; } /** * Create a new bitmap with the given width, height, color format and pixel buffer.\n * @msdn{dd183485} * @param nWidth width * @param nHeight height * @param cBitsPerPixel bits per pixel * @param data pixel buffer * @return new bitmap */ HGDI_BITMAP gdi_CreateBitmap(int nWidth, int nHeight, int cBitsPerPixel, uint8* data) { HGDI_BITMAP hBitmap = (HGDI_BITMAP) malloc(sizeof(GDI_BITMAP)); hBitmap->objectType = GDIOBJECT_BITMAP; hBitmap->bitsPerPixel = cBitsPerPixel; hBitmap->bytesPerPixel = (cBitsPerPixel + 1) / 8; hBitmap->scanline = nWidth * hBitmap->bytesPerPixel; hBitmap->width = nWidth; hBitmap->height = nHeight; hBitmap->data = data; return hBitmap; } /** * Create a new bitmap of the given width and height compatible with the current device context.\n * @msdn{dd183488} * @param hdc device context * @param nWidth width * @param nHeight height * @return new bitmap */ HGDI_BITMAP gdi_CreateCompatibleBitmap(HGDI_DC hdc, int nWidth, int nHeight) { HGDI_BITMAP hBitmap = (HGDI_BITMAP) malloc(sizeof(GDI_BITMAP)); hBitmap->objectType = GDIOBJECT_BITMAP; hBitmap->bytesPerPixel = hdc->bytesPerPixel; hBitmap->bitsPerPixel = hdc->bitsPerPixel; hBitmap->width = nWidth; hBitmap->height = nHeight; hBitmap->data = malloc(nWidth * nHeight * hBitmap->bytesPerPixel); hBitmap->scanline = nWidth * hBitmap->bytesPerPixel; return hBitmap; } /** * Perform a bit blit operation on the given pixel buffers.\n * @msdn{dd183370} * @param hdcDest destination device context * @param nXDest destination x1 * @param nYDest destination y1 * @param nWidth width * @param nHeight height * @param hdcSrc source device context * @param nXSrc source x1 * @param nYSrc source y1 * @param rop raster operation code * @return 1 if successful, 0 otherwise */ int gdi_BitBlt(HGDI_DC hdcDest, int nXDest, int nYDest, int nWidth, int nHeight, HGDI_DC hdcSrc, int nXSrc, int nYSrc, int rop) { p_BitBlt _BitBlt = BitBlt_[IBPP(hdcDest->bitsPerPixel)]; if (_BitBlt != NULL) return _BitBlt(hdcDest, nXDest, nYDest, nWidth, nHeight, hdcSrc, nXSrc, nYSrc, rop); else return 0; } FreeRDP-1.0.2/libfreerdp-gdi/brush.c000066400000000000000000000044311207112532300171050ustar00rootroot00000000000000/** * FreeRDP: A Remote Desktop Protocol Client * GDI Brush Functions * * Copyright 2010-2011 Marc-Andre Moreau * * 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. */ /* GDI Brush Functions: http://msdn.microsoft.com/en-us/library/dd183395/ */ #include #include #include #include #include #include #include #include #include p_PatBlt PatBlt_[5] = { NULL, PatBlt_8bpp, PatBlt_16bpp, NULL, PatBlt_32bpp }; /** * Create a new solid brush.\n * @msdn{dd183518} * @param crColor brush color * @return new brush */ HGDI_BRUSH gdi_CreateSolidBrush(GDI_COLOR crColor) { HGDI_BRUSH hBrush = (HGDI_BRUSH) malloc(sizeof(GDI_BRUSH)); hBrush->objectType = GDIOBJECT_BRUSH; hBrush->style = GDI_BS_SOLID; hBrush->color = crColor; return hBrush; } /** * Create a new pattern brush.\n * @msdn{dd183508} * @param hbmp pattern bitmap * @return new brush */ HGDI_BRUSH gdi_CreatePatternBrush(HGDI_BITMAP hbmp) { HGDI_BRUSH hBrush = (HGDI_BRUSH) malloc(sizeof(GDI_BRUSH)); hBrush->objectType = GDIOBJECT_BRUSH; hBrush->style = GDI_BS_PATTERN; hBrush->pattern = hbmp; return hBrush; } /** * Perform a pattern blit operation on the given pixel buffer.\n * @msdn{dd162778} * @param hdc device context * @param nXLeft x1 * @param nYLeft y1 * @param nWidth width * @param nHeight height * @param rop raster operation code * @return 1 if successful, 0 otherwise */ int gdi_PatBlt(HGDI_DC hdc, int nXLeft, int nYLeft, int nWidth, int nHeight, int rop) { p_PatBlt _PatBlt = PatBlt_[IBPP(hdc->bitsPerPixel)]; if (_PatBlt != NULL) return _PatBlt(hdc, nXLeft, nYLeft, nWidth, nHeight, rop); else return 0; } FreeRDP-1.0.2/libfreerdp-gdi/clipping.c000066400000000000000000000064631207112532300175760ustar00rootroot00000000000000/** * FreeRDP: A Remote Desktop Protocol Client * GDI Clipping Functions * * Copyright 2010-2011 Marc-Andre Moreau * * 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. */ #include #include #include #include #include #include #include int gdi_SetClipRgn(HGDI_DC hdc, int nXLeft, int nYLeft, int nWidth, int nHeight) { return gdi_SetRgn(hdc->clip, nXLeft, nYLeft, nWidth, nHeight); } /** * Get the current clipping region.\n * @msdn{dd144866} * @param hdc device context * @return clipping region */ HGDI_RGN gdi_GetClipRgn(HGDI_DC hdc) { return hdc->clip; } /** * Set the current clipping region to null. * @param hdc device context * @return */ int gdi_SetNullClipRgn(HGDI_DC hdc) { gdi_SetClipRgn(hdc, 0, 0, 0, 0); hdc->clip->null = 1; return 0; } /** * Clip coordinates according to clipping region * @param hdc device context * @param x x1 * @param y y1 * @param w width * @param h height * @param srcx source x1 * @param srcy source y1 * @return 1 if there is something to draw, 0 otherwise */ int gdi_ClipCoords(HGDI_DC hdc, int *x, int *y, int *w, int *h, int *srcx, int *srcy) { GDI_RECT bmp; GDI_RECT clip; GDI_RECT coords; HGDI_BITMAP hBmp; int dx = 0; int dy = 0; int draw = 1; if (hdc == NULL) return 0; hBmp = (HGDI_BITMAP) hdc->selectedObject; if (hBmp != NULL) { if (hdc->clip->null) { gdi_CRgnToRect(0, 0, hBmp->width, hBmp->height, &clip); } else { gdi_RgnToRect(hdc->clip, &clip); gdi_CRgnToRect(0, 0, hBmp->width, hBmp->height, &bmp); if (clip.left < bmp.left) clip.left = bmp.left; if (clip.right > bmp.right) clip.right = bmp.right; if (clip.top < bmp.top) clip.top = bmp.top; if (clip.bottom > bmp.bottom) clip.bottom = bmp.bottom; } } else { gdi_RgnToRect(hdc->clip, &clip); } gdi_CRgnToRect(*x, *y, *w, *h, &coords); if (coords.right >= clip.left && coords.left <= clip.right && coords.bottom >= clip.top && coords.top <= clip.bottom) { /* coordinates overlap with clipping region */ if (coords.left < clip.left) { dx = (clip.left - coords.left) + 1; coords.left = clip.left; } if (coords.right > clip.right) coords.right = clip.right; if (coords.top < clip.top) { dy = (clip.top - coords.top) + 1; coords.top = clip.top; } if (coords.bottom > clip.bottom) coords.bottom = clip.bottom; } else { /* coordinates do not overlap with clipping region */ coords.left = 0; coords.right = 0; coords.top = 0; coords.bottom = 0; draw = 0; } if (srcx != NULL) { if (dx > 0) { *srcx += dx - 1; } } if (srcy != NULL) { if (dy > 0) { *srcy += dy - 1; } } gdi_RectToCRgn(&coords, x, y, w, h); return draw; } FreeRDP-1.0.2/libfreerdp-gdi/dc.c000066400000000000000000000117611207112532300163540ustar00rootroot00000000000000/** * FreeRDP: A Remote Desktop Protocol Client * GDI Device Context Functions * * Copyright 2010-2011 Marc-Andre Moreau * * 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. */ /* Device Context Functions: http://msdn.microsoft.com/en-us/library/dd183554 */ #include #include #include #include #include #include #include #include /** * Get the current device context (a new one is created each time).\n * @msdn{dd144871} * @return current device context */ HGDI_DC gdi_GetDC() { HGDI_DC hDC = (HGDI_DC) malloc(sizeof(GDI_DC)); hDC->bytesPerPixel = 4; hDC->bitsPerPixel = 32; hDC->drawMode = GDI_R2_BLACK; hDC->clip = gdi_CreateRectRgn(0, 0, 0, 0); hDC->clip->null = 1; hDC->hwnd = NULL; return hDC; } /** * Create a device context.\n * @msdn{dd144871} * @return new device context */ HGDI_DC gdi_CreateDC(HCLRCONV clrconv, int bpp) { HGDI_DC hDC = (HGDI_DC) malloc(sizeof(GDI_DC)); hDC->drawMode = GDI_R2_BLACK; hDC->clip = gdi_CreateRectRgn(0, 0, 0, 0); hDC->clip->null = 1; hDC->hwnd = NULL; hDC->bitsPerPixel = bpp; hDC->bytesPerPixel = bpp / 8; hDC->alpha = clrconv->alpha; hDC->invert = clrconv->invert; hDC->rgb555 = clrconv->rgb555; hDC->hwnd = (HGDI_WND) malloc(sizeof(GDI_WND)); hDC->hwnd->invalid = gdi_CreateRectRgn(0, 0, 0, 0); hDC->hwnd->invalid->null = 1; hDC->hwnd->count = 32; hDC->hwnd->cinvalid = (HGDI_RGN) malloc(sizeof(GDI_RGN) * hDC->hwnd->count); hDC->hwnd->ninvalid = 0; return hDC; } /** * Create a new device context compatible with the given device context.\n * @msdn{dd183489} * @param hdc device context * @return new compatible device context */ HGDI_DC gdi_CreateCompatibleDC(HGDI_DC hdc) { HGDI_DC hDC = (HGDI_DC) malloc(sizeof(GDI_DC)); hDC->bytesPerPixel = hdc->bytesPerPixel; hDC->bitsPerPixel = hdc->bitsPerPixel; hDC->drawMode = hdc->drawMode; hDC->clip = gdi_CreateRectRgn(0, 0, 0, 0); hDC->clip->null = 1; hDC->hwnd = NULL; hDC->alpha = hdc->alpha; hDC->invert = hdc->invert; hDC->rgb555 = hdc->rgb555; return hDC; } /** * Select a GDI object in the current device context.\n * @msdn{dd162957} * @param hdc device context * @param hgdiobject new selected GDI object * @return previous selected GDI object */ HGDIOBJECT gdi_SelectObject(HGDI_DC hdc, HGDIOBJECT hgdiobject) { HGDIOBJECT previousSelectedObject = hdc->selectedObject; if (hgdiobject == NULL) return NULL; if (hgdiobject->objectType == GDIOBJECT_BITMAP) { hdc->selectedObject = hgdiobject; } else if (hgdiobject->objectType == GDIOBJECT_PEN) { previousSelectedObject = (HGDIOBJECT) hdc->pen; hdc->pen = (HGDI_PEN) hgdiobject; } else if (hgdiobject->objectType == GDIOBJECT_BRUSH) { previousSelectedObject = (HGDIOBJECT) hdc->brush; hdc->brush = (HGDI_BRUSH) hgdiobject; } else if (hgdiobject->objectType == GDIOBJECT_REGION) { hdc->selectedObject = hgdiobject; } else if (hgdiobject->objectType == GDIOBJECT_RECT) { hdc->selectedObject = hgdiobject; } else { /* Unknown GDI Object Type */ return 0; } return previousSelectedObject; } /** * Delete a GDI object.\n * @msdn{dd183539} * @param hgdiobject GDI object * @return 1 if successful, 0 otherwise */ int gdi_DeleteObject(HGDIOBJECT hgdiobject) { if (hgdiobject == NULL) return 0; if (hgdiobject->objectType == GDIOBJECT_BITMAP) { HGDI_BITMAP hBitmap = (HGDI_BITMAP) hgdiobject; if (hBitmap->data != NULL) free(hBitmap->data); free(hBitmap); } else if (hgdiobject->objectType == GDIOBJECT_PEN) { HGDI_PEN hPen = (HGDI_PEN) hgdiobject; free(hPen); } else if (hgdiobject->objectType == GDIOBJECT_BRUSH) { HGDI_BRUSH hBrush = (HGDI_BRUSH) hgdiobject; if(hBrush->style == GDI_BS_PATTERN) { if (hBrush->pattern != NULL) gdi_DeleteObject((HGDIOBJECT) hBrush->pattern); } free(hBrush); } else if (hgdiobject->objectType == GDIOBJECT_REGION) { free(hgdiobject); } else if (hgdiobject->objectType == GDIOBJECT_RECT) { free(hgdiobject); } else { /* Unknown GDI Object Type */ free(hgdiobject); return 0; } return 1; } /** * Delete device context.\n * @msdn{dd183533} * @param hdc device context * @return 1 if successful, 0 otherwise */ int gdi_DeleteDC(HGDI_DC hdc) { if (hdc->hwnd) { if (hdc->hwnd->cinvalid != NULL) free(hdc->hwnd->cinvalid); if (hdc->hwnd->invalid != NULL) free(hdc->hwnd->invalid); free(hdc->hwnd); } free(hdc->clip); free(hdc); return 1; } FreeRDP-1.0.2/libfreerdp-gdi/drawing.c000066400000000000000000000053321207112532300174160ustar00rootroot00000000000000/** * FreeRDP: A Remote Desktop Protocol Client * GDI Drawing Functions * * Copyright 2010-2011 Marc-Andre Moreau * * 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. */ /* GDI Drawing Functions: http://msdn.microsoft.com/en-us/library/dd162760/ */ #include #include #include #include #include #include /** * Set current foreground draw mode.\n * @msdn{dd144922} * @param hdc device context * @return draw mode */ int gdi_GetROP2(HGDI_DC hdc) { return hdc->drawMode; } /** * Set current foreground draw mode.\n * @msdn{dd145088} * @param hdc device context * @param fnDrawMode draw mode * @return previous draw mode */ int gdi_SetROP2(HGDI_DC hdc, int fnDrawMode) { int prevDrawMode = hdc->drawMode; if (fnDrawMode > 0 && fnDrawMode <= 16) hdc->drawMode = fnDrawMode; return prevDrawMode; } /** * Get the current background color.\n * @msdn{dd144852} * @param hdc device context * @return background color */ GDI_COLOR gdi_GetBkColor(HGDI_DC hdc) { return hdc->bkColor; } /** * Set the current background color.\n * @msdn{dd162964} * @param hdc device color * @param crColor new background color * @return previous background color */ GDI_COLOR gdi_SetBkColor(HGDI_DC hdc, GDI_COLOR crColor) { GDI_COLOR previousBkColor = hdc->bkColor; hdc->bkColor = crColor; return previousBkColor; } /** * Get the current background mode.\n * @msdn{dd144853} * @param hdc device context * @return background mode */ int gdi_GetBkMode(HGDI_DC hdc) { return hdc->bkMode; } /** * Set the current background mode.\n * @msdn{dd162965} * @param hdc device context * @param iBkMode background mode * @return */ int gdi_SetBkMode(HGDI_DC hdc, int iBkMode) { if (iBkMode == GDI_OPAQUE || iBkMode == GDI_TRANSPARENT) hdc->bkMode = iBkMode; else hdc->bkMode = GDI_OPAQUE; return 0; } /** * Set the current text color.\n * @msdn{dd145093} * @param hdc device context * @param crColor new text color * @return previous text color */ GDI_COLOR gdi_SetTextColor(HGDI_DC hdc, GDI_COLOR crColor) { GDI_COLOR previousTextColor = hdc->textColor; hdc->textColor = crColor; return previousTextColor; } FreeRDP-1.0.2/libfreerdp-gdi/gdi.c000066400000000000000000000633111207112532300165270ustar00rootroot00000000000000/** * FreeRDP: A Remote Desktop Protocol Client * GDI Library * * Copyright 2010-2011 Marc-Andre Moreau * * 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. */ #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include "gdi.h" /* Ternary Raster Operation Table */ static const uint32 rop3_code_table[] = { 0x00000042, /* 0 */ 0x00010289, /* DPSoon */ 0x00020C89, /* DPSona */ 0x000300AA, /* PSon */ 0x00040C88, /* SDPona */ 0x000500A9, /* DPon */ 0x00060865, /* PDSxnon */ 0x000702C5, /* PDSaon */ 0x00080F08, /* SDPnaa */ 0x00090245, /* PDSxon */ 0x000A0329, /* DPna */ 0x000B0B2A, /* PSDnaon */ 0x000C0324, /* SPna */ 0x000D0B25, /* PDSnaon */ 0x000E08A5, /* PDSonon */ 0x000F0001, /* Pn */ 0x00100C85, /* PDSona */ 0x001100A6, /* DSon */ 0x00120868, /* SDPxnon */ 0x001302C8, /* SDPaon */ 0x00140869, /* DPSxnon */ 0x001502C9, /* DPSaon */ 0x00165CCA, /* PSDPSanaxx */ 0x00171D54, /* SSPxDSxaxn */ 0x00180D59, /* SPxPDxa */ 0x00191CC8, /* SDPSanaxn */ 0x001A06C5, /* PDSPaox */ 0x001B0768, /* SDPSxaxn */ 0x001C06CA, /* PSDPaox */ 0x001D0766, /* DSPDxaxn */ 0x001E01A5, /* PDSox */ 0x001F0385, /* PDSoan */ 0x00200F09, /* DPSnaa */ 0x00210248, /* SDPxon */ 0x00220326, /* DSna */ 0x00230B24, /* SPDnaon */ 0x00240D55, /* SPxDSxa */ 0x00251CC5, /* PDSPanaxn */ 0x002606C8, /* SDPSaox */ 0x00271868, /* SDPSxnox */ 0x00280369, /* DPSxa */ 0x002916CA, /* PSDPSaoxxn */ 0x002A0CC9, /* DPSana */ 0x002B1D58, /* SSPxPDxaxn */ 0x002C0784, /* SPDSoax */ 0x002D060A, /* PSDnox */ 0x002E064A, /* PSDPxox */ 0x002F0E2A, /* PSDnoan */ 0x0030032A, /* PSna */ 0x00310B28, /* SDPnaon */ 0x00320688, /* SDPSoox */ 0x00330008, /* Sn */ 0x003406C4, /* SPDSaox */ 0x00351864, /* SPDSxnox */ 0x003601A8, /* SDPox */ 0x00370388, /* SDPoan */ 0x0038078A, /* PSDPoax */ 0x00390604, /* SPDnox */ 0x003A0644, /* SPDSxox */ 0x003B0E24, /* SPDnoan */ 0x003C004A, /* PSx */ 0x003D18A4, /* SPDSonox */ 0x003E1B24, /* SPDSnaox */ 0x003F00EA, /* PSan */ 0x00400F0A, /* PSDnaa */ 0x00410249, /* DPSxon */ 0x00420D5D, /* SDxPDxa */ 0x00431CC4, /* SPDSanaxn */ 0x00440328, /* SDna */ 0x00450B29, /* DPSnaon */ 0x004606C6, /* DSPDaox */ 0x0047076A, /* PSDPxaxn */ 0x00480368, /* SDPxa */ 0x004916C5, /* PDSPDaoxxn */ 0x004A0789, /* DPSDoax */ 0x004B0605, /* PDSnox */ 0x004C0CC8, /* SDPana */ 0x004D1954, /* SSPxDSxoxn */ 0x004E0645, /* PDSPxox */ 0x004F0E25, /* PDSnoan */ 0x00500325, /* PDna */ 0x00510B26, /* DSPnaon */ 0x005206C9, /* DPSDaox */ 0x00530764, /* SPDSxaxn */ 0x005408A9, /* DPSonon */ 0x00550009, /* Dn */ 0x005601A9, /* DPSox */ 0x00570389, /* DPSoan */ 0x00580785, /* PDSPoax */ 0x00590609, /* DPSnox */ 0x005A0049, /* DPx */ 0x005B18A9, /* DPSDonox */ 0x005C0649, /* DPSDxox */ 0x005D0E29, /* DPSnoan */ 0x005E1B29, /* DPSDnaox */ 0x005F00E9, /* DPan */ 0x00600365, /* PDSxa */ 0x006116C6, /* DSPDSaoxxn */ 0x00620786, /* DSPDoax */ 0x00630608, /* SDPnox */ 0x00640788, /* SDPSoax */ 0x00650606, /* DSPnox */ 0x00660046, /* DSx */ 0x006718A8, /* SDPSonox */ 0x006858A6, /* DSPDSonoxxn */ 0x00690145, /* PDSxxn */ 0x006A01E9, /* DPSax */ 0x006B178A, /* PSDPSoaxxn */ 0x006C01E8, /* SDPax */ 0x006D1785, /* PDSPDoaxxn */ 0x006E1E28, /* SDPSnoax */ 0x006F0C65, /* PDSxnan */ 0x00700CC5, /* PDSana */ 0x00711D5C, /* SSDxPDxaxn */ 0x00720648, /* SDPSxox */ 0x00730E28, /* SDPnoan */ 0x00740646, /* DSPDxox */ 0x00750E26, /* DSPnoan */ 0x00761B28, /* SDPSnaox */ 0x007700E6, /* DSan */ 0x007801E5, /* PDSax */ 0x00791786, /* DSPDSoaxxn */ 0x007A1E29, /* DPSDnoax */ 0x007B0C68, /* SDPxnan */ 0x007C1E24, /* SPDSnoax */ 0x007D0C69, /* DPSxnan */ 0x007E0955, /* SPxDSxo */ 0x007F03C9, /* DPSaan */ 0x008003E9, /* DPSaa */ 0x00810975, /* SPxDSxon */ 0x00820C49, /* DPSxna */ 0x00831E04, /* SPDSnoaxn */ 0x00840C48, /* SDPxna */ 0x00851E05, /* PDSPnoaxn */ 0x008617A6, /* DSPDSoaxx */ 0x008701C5, /* PDSaxn */ 0x008800C6, /* DSa */ 0x00891B08, /* SDPSnaoxn */ 0x008A0E06, /* DSPnoa */ 0x008B0666, /* DSPDxoxn */ 0x008C0E08, /* SDPnoa */ 0x008D0668, /* SDPSxoxn */ 0x008E1D7C, /* SSDxPDxax */ 0x008F0CE5, /* PDSanan */ 0x00900C45, /* PDSxna */ 0x00911E08, /* SDPSnoaxn */ 0x009217A9, /* DPSDPoaxx */ 0x009301C4, /* SPDaxn */ 0x009417AA, /* PSDPSoaxx */ 0x009501C9, /* DPSaxn */ 0x00960169, /* DPSxx */ 0x0097588A, /* PSDPSonoxx */ 0x00981888, /* SDPSonoxn */ 0x00990066, /* DSxn */ 0x009A0709, /* DPSnax */ 0x009B07A8, /* SDPSoaxn */ 0x009C0704, /* SPDnax */ 0x009D07A6, /* DSPDoaxn */ 0x009E16E6, /* DSPDSaoxx */ 0x009F0345, /* PDSxan */ 0x00A000C9, /* DPa */ 0x00A11B05, /* PDSPnaoxn */ 0x00A20E09, /* DPSnoa */ 0x00A30669, /* DPSDxoxn */ 0x00A41885, /* PDSPonoxn */ 0x00A50065, /* PDxn */ 0x00A60706, /* DSPnax */ 0x00A707A5, /* PDSPoaxn */ 0x00A803A9, /* DPSoa */ 0x00A90189, /* DPSoxn */ 0x00AA0029, /* D */ 0x00AB0889, /* DPSono */ 0x00AC0744, /* SPDSxax */ 0x00AD06E9, /* DPSDaoxn */ 0x00AE0B06, /* DSPnao */ 0x00AF0229, /* DPno */ 0x00B00E05, /* PDSnoa */ 0x00B10665, /* PDSPxoxn */ 0x00B21974, /* SSPxDSxox */ 0x00B30CE8, /* SDPanan */ 0x00B4070A, /* PSDnax */ 0x00B507A9, /* DPSDoaxn */ 0x00B616E9, /* DPSDPaoxx */ 0x00B70348, /* SDPxan */ 0x00B8074A, /* PSDPxax */ 0x00B906E6, /* DSPDaoxn */ 0x00BA0B09, /* DPSnao */ 0x00BB0226, /* DSno */ 0x00BC1CE4, /* SPDSanax */ 0x00BD0D7D, /* SDxPDxan */ 0x00BE0269, /* DPSxo */ 0x00BF08C9, /* DPSano */ 0x00C000CA, /* PSa */ 0x00C11B04, /* SPDSnaoxn */ 0x00C21884, /* SPDSonoxn */ 0x00C3006A, /* PSxn */ 0x00C40E04, /* SPDnoa */ 0x00C50664, /* SPDSxoxn */ 0x00C60708, /* SDPnax */ 0x00C707AA, /* PSDPoaxn */ 0x00C803A8, /* SDPoa */ 0x00C90184, /* SPDoxn */ 0x00CA0749, /* DPSDxax */ 0x00CB06E4, /* SPDSaoxn */ 0x00CC0020, /* S */ 0x00CD0888, /* SDPono */ 0x00CE0B08, /* SDPnao */ 0x00CF0224, /* SPno */ 0x00D00E0A, /* PSDnoa */ 0x00D1066A, /* PSDPxoxn */ 0x00D20705, /* PDSnax */ 0x00D307A4, /* SPDSoaxn */ 0x00D41D78, /* SSPxPDxax */ 0x00D50CE9, /* DPSanan */ 0x00D616EA, /* PSDPSaoxx */ 0x00D70349, /* DPSxan */ 0x00D80745, /* PDSPxax */ 0x00D906E8, /* SDPSaoxn */ 0x00DA1CE9, /* DPSDanax */ 0x00DB0D75, /* SPxDSxan */ 0x00DC0B04, /* SPDnao */ 0x00DD0228, /* SDno */ 0x00DE0268, /* SDPxo */ 0x00DF08C8, /* SDPano */ 0x00E003A5, /* PDSoa */ 0x00E10185, /* PDSoxn */ 0x00E20746, /* DSPDxax */ 0x00E306EA, /* PSDPaoxn */ 0x00E40748, /* SDPSxax */ 0x00E506E5, /* PDSPaoxn */ 0x00E61CE8, /* SDPSanax */ 0x00E70D79, /* SPxPDxan */ 0x00E81D74, /* SSPxDSxax */ 0x00E95CE6, /* DSPDSanaxxn */ 0x00EA02E9, /* DPSao */ 0x00EB0849, /* DPSxno */ 0x00EC02E8, /* SDPao */ 0x00ED0848, /* SDPxno */ 0x00EE0086, /* DSo */ 0x00EF0A08, /* SDPnoo */ 0x00F00021, /* P */ 0x00F10885, /* PDSono */ 0x00F20B05, /* PDSnao */ 0x00F3022A, /* PSno */ 0x00F40B0A, /* PSDnao */ 0x00F50225, /* PDno */ 0x00F60265, /* PDSxo */ 0x00F708C5, /* PDSano */ 0x00F802E5, /* PDSao */ 0x00F90845, /* PDSxno */ 0x00FA0089, /* DPo */ 0x00FB0A09, /* DPSnoo */ 0x00FC008A, /* PSo */ 0x00FD0A0A, /* PSDnoo */ 0x00FE02A9, /* DPSoo */ 0x00FF0062 /* 1 */ }; /* GDI Helper Functions */ INLINE uint32 gdi_rop3_code(uint8 code) { return rop3_code_table[code]; } INLINE uint8* gdi_get_bitmap_pointer(HGDI_DC hdcBmp, int x, int y) { uint8* p; HGDI_BITMAP hBmp = (HGDI_BITMAP) hdcBmp->selectedObject; if (x >= 0 && x < hBmp->width && y >= 0 && y < hBmp->height) { p = hBmp->data + (y * hBmp->width * hdcBmp->bytesPerPixel) + (x * hdcBmp->bytesPerPixel); return p; } else { printf("gdi_get_bitmap_pointer: requesting invalid pointer: (%d,%d) in %dx%d\n", x, y, hBmp->width, hBmp->height); return 0; } } INLINE uint8* gdi_get_brush_pointer(HGDI_DC hdcBrush, int x, int y) { uint8 * p; if (hdcBrush->brush != NULL) { if (hdcBrush->brush->style == GDI_BS_PATTERN) { HGDI_BITMAP hBmpBrush = hdcBrush->brush->pattern; if (x >= 0 && y >= 0) { x = x % hBmpBrush->width; y = y % hBmpBrush->height; p = hBmpBrush->data + (y * hBmpBrush->scanline) + (x * hBmpBrush->bytesPerPixel); return p; } } } p = (uint8*) &(hdcBrush->textColor); return p; } INLINE int gdi_is_mono_pixel_set(uint8* data, int x, int y, int width) { int byte; int shift; width = (width + 7) / 8; byte = (y * width) + (x / 8); shift = x % 8; return (data[byte] & (0x80 >> shift)) != 0; } gdiBitmap* gdi_glyph_new(rdpGdi* gdi, GLYPH_DATA* glyph) { uint8* extra; gdiBitmap* gdi_bmp; gdi_bmp = (gdiBitmap*) malloc(sizeof(gdiBitmap)); gdi_bmp->hdc = gdi_GetDC(); gdi_bmp->hdc->bytesPerPixel = 1; gdi_bmp->hdc->bitsPerPixel = 1; extra = freerdp_glyph_convert(glyph->cx, glyph->cy, glyph->aj); gdi_bmp->bitmap = gdi_CreateBitmap(glyph->cx, glyph->cy, 1, extra); gdi_bmp->bitmap->bytesPerPixel = 1; gdi_bmp->bitmap->bitsPerPixel = 1; gdi_SelectObject(gdi_bmp->hdc, (HGDIOBJECT) gdi_bmp->bitmap); gdi_bmp->org_bitmap = NULL; return gdi_bmp; } void gdi_glyph_free(gdiBitmap *gdi_bmp) { if (gdi_bmp != 0) { gdi_SelectObject(gdi_bmp->hdc, (HGDIOBJECT) gdi_bmp->org_bitmap); gdi_DeleteObject((HGDIOBJECT) gdi_bmp->bitmap); gdi_DeleteDC(gdi_bmp->hdc); free(gdi_bmp); } } gdiBitmap* gdi_bitmap_new_ex(rdpGdi* gdi, int width, int height, int bpp, uint8* data) { gdiBitmap* bitmap; bitmap = (gdiBitmap*) malloc(sizeof(gdiBitmap)); bitmap->hdc = gdi_CreateCompatibleDC(gdi->hdc); DEBUG_GDI("gdi_bitmap_new: width:%d height:%d bpp:%d", width, height, bpp); if (data == NULL) bitmap->bitmap = gdi_CreateCompatibleBitmap(gdi->hdc, width, height); else bitmap->bitmap = gdi_create_bitmap(gdi, width, height, bpp, data); gdi_SelectObject(bitmap->hdc, (HGDIOBJECT) bitmap->bitmap); bitmap->org_bitmap = NULL; return bitmap; } void gdi_bitmap_free_ex(gdiBitmap* bitmap) { if (bitmap != NULL) { gdi_SelectObject(bitmap->hdc, (HGDIOBJECT) bitmap->org_bitmap); gdi_DeleteObject((HGDIOBJECT) bitmap->bitmap); gdi_DeleteDC(bitmap->hdc); free(bitmap); } } void gdi_palette_update(rdpContext* context, PALETTE_UPDATE* palette) { rdpGdi* gdi = context->gdi; gdi->clrconv->palette->count = palette->number; gdi->clrconv->palette->entries = palette->entries; } void gdi_set_bounds(rdpContext* context, rdpBounds* bounds) { rdpGdi* gdi = context->gdi; if (bounds != NULL) { gdi_SetClipRgn(gdi->drawing->hdc, bounds->left, bounds->top, bounds->right - bounds->left + 1, bounds->bottom - bounds->top + 1); } else { gdi_SetNullClipRgn(gdi->drawing->hdc); } } void gdi_dstblt(rdpContext* context, DSTBLT_ORDER* dstblt) { rdpGdi* gdi = context->gdi; gdi_BitBlt(gdi->drawing->hdc, dstblt->nLeftRect, dstblt->nTopRect, dstblt->nWidth, dstblt->nHeight, NULL, 0, 0, gdi_rop3_code(dstblt->bRop)); } void gdi_patblt(rdpContext* context, PATBLT_ORDER* patblt) { uint8* data; rdpBrush* brush; HGDI_BRUSH originalBrush; rdpGdi* gdi = context->gdi; brush = &patblt->brush; if (brush->style == GDI_BS_SOLID) { uint32 color; originalBrush = gdi->drawing->hdc->brush; color = freerdp_color_convert_rgb(patblt->foreColor, gdi->srcBpp, 32, gdi->clrconv); gdi->drawing->hdc->brush = gdi_CreateSolidBrush(color); gdi_PatBlt(gdi->drawing->hdc, patblt->nLeftRect, patblt->nTopRect, patblt->nWidth, patblt->nHeight, gdi_rop3_code(patblt->bRop)); gdi_DeleteObject((HGDIOBJECT) gdi->drawing->hdc->brush); gdi->drawing->hdc->brush = originalBrush; } else if (brush->style == GDI_BS_PATTERN) { HGDI_BITMAP hBmp; if (brush->bpp > 1) { data = freerdp_image_convert(brush->data, NULL, 8, 8, gdi->srcBpp, gdi->dstBpp, gdi->clrconv); } else { data = freerdp_mono_image_convert(brush->data, 8, 8, gdi->srcBpp, gdi->dstBpp, patblt->backColor, patblt->foreColor, gdi->clrconv); } hBmp = gdi_CreateBitmap(8, 8, gdi->drawing->hdc->bitsPerPixel, data); originalBrush = gdi->drawing->hdc->brush; gdi->drawing->hdc->brush = gdi_CreatePatternBrush(hBmp); gdi_PatBlt(gdi->drawing->hdc, patblt->nLeftRect, patblt->nTopRect, patblt->nWidth, patblt->nHeight, gdi_rop3_code(patblt->bRop)); gdi_DeleteObject((HGDIOBJECT) gdi->drawing->hdc->brush); gdi->drawing->hdc->brush = originalBrush; } else { printf("unimplemented brush style:%d\n", brush->style); } } void gdi_scrblt(rdpContext* context, SCRBLT_ORDER* scrblt) { rdpGdi* gdi = context->gdi; gdi_BitBlt(gdi->drawing->hdc, scrblt->nLeftRect, scrblt->nTopRect, scrblt->nWidth, scrblt->nHeight, gdi->primary->hdc, scrblt->nXSrc, scrblt->nYSrc, gdi_rop3_code(scrblt->bRop)); } void gdi_opaque_rect(rdpContext* context, OPAQUE_RECT_ORDER* opaque_rect) { GDI_RECT rect; HGDI_BRUSH hBrush; uint32 brush_color; rdpGdi *gdi = context->gdi; gdi_CRgnToRect(opaque_rect->nLeftRect, opaque_rect->nTopRect, opaque_rect->nWidth, opaque_rect->nHeight, &rect); brush_color = freerdp_color_convert_var_bgr(opaque_rect->color, gdi->srcBpp, 32, gdi->clrconv); hBrush = gdi_CreateSolidBrush(brush_color); gdi_FillRect(gdi->drawing->hdc, &rect, hBrush); gdi_DeleteObject((HGDIOBJECT) hBrush); } void gdi_multi_opaque_rect(rdpContext* context, MULTI_OPAQUE_RECT_ORDER* multi_opaque_rect) { int i; GDI_RECT rect; HGDI_BRUSH hBrush; uint32 brush_color; DELTA_RECT* rectangle; rdpGdi *gdi = context->gdi; for (i = 1; i < (int) multi_opaque_rect->numRectangles + 1; i++) { rectangle = &multi_opaque_rect->rectangles[i]; gdi_CRgnToRect(rectangle->left, rectangle->top, rectangle->width, rectangle->height, &rect); brush_color = freerdp_color_convert_var_bgr(multi_opaque_rect->color, gdi->srcBpp, 32, gdi->clrconv); hBrush = gdi_CreateSolidBrush(brush_color); gdi_FillRect(gdi->drawing->hdc, &rect, hBrush); gdi_DeleteObject((HGDIOBJECT) hBrush); } } void gdi_line_to(rdpContext* context, LINE_TO_ORDER* line_to) { uint32 color; HGDI_PEN hPen; rdpGdi *gdi = context->gdi; color = freerdp_color_convert_rgb(line_to->penColor, gdi->srcBpp, 32, gdi->clrconv); hPen = gdi_CreatePen(line_to->penStyle, line_to->penWidth, (GDI_COLOR) color); gdi_SelectObject(gdi->drawing->hdc, (HGDIOBJECT) hPen); gdi_SetROP2(gdi->drawing->hdc, line_to->bRop2); gdi_MoveToEx(gdi->drawing->hdc, line_to->nXStart, line_to->nYStart, NULL); gdi_LineTo(gdi->drawing->hdc, line_to->nXEnd, line_to->nYEnd); gdi_DeleteObject((HGDIOBJECT) hPen); } void gdi_polyline(rdpContext* context, POLYLINE_ORDER* polyline) { int i; uint32 color; HGDI_PEN hPen; DELTA_POINT* points; rdpGdi* gdi = context->gdi; sint32 x; sint32 y; color = freerdp_color_convert_rgb(polyline->penColor, gdi->srcBpp, 32, gdi->clrconv); hPen = gdi_CreatePen(GDI_PS_SOLID, 1, (GDI_COLOR) color); gdi_SelectObject(gdi->drawing->hdc, (HGDIOBJECT) hPen); gdi_SetROP2(gdi->drawing->hdc, polyline->bRop2); x = polyline->xStart; y = polyline->yStart; gdi_MoveToEx(gdi->drawing->hdc, x, y, NULL); points = polyline->points; for (i = 0; i < (int) polyline->numPoints; i++) { x += points[i].x; y += points[i].y; gdi_LineTo(gdi->drawing->hdc, x, y); gdi_MoveToEx(gdi->drawing->hdc, x, y, NULL); } gdi_DeleteObject((HGDIOBJECT) hPen); } void gdi_memblt(rdpContext* context, MEMBLT_ORDER* memblt) { gdiBitmap* bitmap; rdpGdi* gdi = context->gdi; bitmap = (gdiBitmap*) memblt->bitmap; gdi_BitBlt(gdi->drawing->hdc, memblt->nLeftRect, memblt->nTopRect, memblt->nWidth, memblt->nHeight, bitmap->hdc, memblt->nXSrc, memblt->nYSrc, gdi_rop3_code(memblt->bRop)); } void gdi_mem3blt(rdpContext* context, MEM3BLT_ORDER* mem3blt) { printf("Mem3Blt\n"); } void gdi_polygon_sc(rdpContext* context, POLYGON_SC_ORDER* polygon_sc) { printf("PolygonSC\n"); } void gdi_polygon_cb(rdpContext* context, POLYGON_CB_ORDER* polygon_cb) { printf("PolygonCB\n"); } void gdi_ellipse_sc(rdpContext* context, ELLIPSE_SC_ORDER* ellipse_sc) { printf("EllipseSC\n"); } void gdi_ellipse_cb(rdpContext* context, ELLIPSE_CB_ORDER* ellipse_cb) { printf("EllipseCB\n"); } int tilenum = 0; void gdi_surface_bits(rdpContext* context, SURFACE_BITS_COMMAND* surface_bits_command) { int i, j; int tx, ty; char* tile_bitmap; RFX_MESSAGE* message; rdpGdi* gdi = context->gdi; RFX_CONTEXT* rfx_context = (RFX_CONTEXT*) gdi->rfx_context; NSC_CONTEXT* nsc_context = (NSC_CONTEXT*) gdi->nsc_context; DEBUG_GDI("destLeft %d destTop %d destRight %d destBottom %d " "bpp %d codecID %d width %d height %d length %d", surface_bits_command->destLeft, surface_bits_command->destTop, surface_bits_command->destRight, surface_bits_command->destBottom, surface_bits_command->bpp, surface_bits_command->codecID, surface_bits_command->width, surface_bits_command->height, surface_bits_command->bitmapDataLength); tile_bitmap = (char*) xzalloc(32); if (surface_bits_command->codecID == CODEC_ID_REMOTEFX) { message = rfx_process_message(rfx_context, surface_bits_command->bitmapData, surface_bits_command->bitmapDataLength); DEBUG_GDI("num_rects %d num_tiles %d", message->num_rects, message->num_tiles); /* blit each tile */ for (i = 0; i < message->num_tiles; i++) { tx = message->tiles[i]->x + surface_bits_command->destLeft; ty = message->tiles[i]->y + surface_bits_command->destTop; freerdp_image_convert(message->tiles[i]->data, gdi->tile->bitmap->data, 64, 64, 32, 32, gdi->clrconv); #ifdef DUMP_REMOTEFX_TILES sprintf(tile_bitmap, "/tmp/rfx/tile_%d.bmp", tilenum++); freerdp_bitmap_write(tile_bitmap, gdi->tile->bitmap->data, 64, 64, 32); #endif for (j = 0; j < message->num_rects; j++) { gdi_SetClipRgn(gdi->primary->hdc, surface_bits_command->destLeft + message->rects[j].x, surface_bits_command->destTop + message->rects[j].y, message->rects[j].width, message->rects[j].height); gdi_BitBlt(gdi->primary->hdc, tx, ty, 64, 64, gdi->tile->hdc, 0, 0, GDI_SRCCOPY); } } gdi_SetNullClipRgn(gdi->primary->hdc); rfx_message_free(rfx_context, message); } else if (surface_bits_command->codecID == CODEC_ID_NSCODEC) { nsc_context->width = surface_bits_command->width; nsc_context->height = surface_bits_command->height; nsc_process_message(nsc_context, surface_bits_command->bitmapData, surface_bits_command->bitmapDataLength); gdi->image->bitmap->width = surface_bits_command->width; gdi->image->bitmap->height = surface_bits_command->height; gdi->image->bitmap->bitsPerPixel = surface_bits_command->bpp; gdi->image->bitmap->bytesPerPixel = gdi->image->bitmap->bitsPerPixel / 8; gdi->image->bitmap->data = (uint8*) xrealloc(gdi->image->bitmap->data, gdi->image->bitmap->width * gdi->image->bitmap->height * 4); freerdp_image_flip(nsc_context->bmpdata, gdi->image->bitmap->data, gdi->image->bitmap->width, gdi->image->bitmap->height, 32); gdi_BitBlt(gdi->primary->hdc, surface_bits_command->destLeft, surface_bits_command->destTop, surface_bits_command->width, surface_bits_command->height, gdi->image->hdc, 0, 0, GDI_SRCCOPY); nsc_context_destroy(nsc_context); } else if (surface_bits_command->codecID == CODEC_ID_NONE) { gdi->image->bitmap->width = surface_bits_command->width; gdi->image->bitmap->height = surface_bits_command->height; gdi->image->bitmap->bitsPerPixel = surface_bits_command->bpp; gdi->image->bitmap->bytesPerPixel = gdi->image->bitmap->bitsPerPixel / 8; gdi->image->bitmap->data = (uint8*) xrealloc(gdi->image->bitmap->data, gdi->image->bitmap->width * gdi->image->bitmap->height * 4); if ((surface_bits_command->bpp != 32) || (gdi->clrconv->alpha == true)) { uint8* temp_image; freerdp_image_convert(surface_bits_command->bitmapData, gdi->image->bitmap->data, gdi->image->bitmap->width, gdi->image->bitmap->height, gdi->image->bitmap->bitsPerPixel, 32, gdi->clrconv); surface_bits_command->bpp = 32; surface_bits_command->bitmapData = gdi->image->bitmap->data; temp_image = (uint8*) xmalloc(gdi->image->bitmap->width * gdi->image->bitmap->height * 4); freerdp_image_flip(gdi->image->bitmap->data, temp_image, gdi->image->bitmap->width, gdi->image->bitmap->height, 32); xfree(gdi->image->bitmap->data); gdi->image->bitmap->data = temp_image; } else { freerdp_image_flip(surface_bits_command->bitmapData, gdi->image->bitmap->data, gdi->image->bitmap->width, gdi->image->bitmap->height, 32); } gdi_BitBlt(gdi->primary->hdc, surface_bits_command->destLeft, surface_bits_command->destTop, surface_bits_command->width, surface_bits_command->height, gdi->image->hdc, 0, 0, GDI_SRCCOPY); } else { printf("Unsupported codecID %d\n", surface_bits_command->codecID); } if (tile_bitmap != NULL) xfree(tile_bitmap); } /** * Register GDI callbacks with libfreerdp-core. * @param inst current instance * @return */ void gdi_register_update_callbacks(rdpUpdate* update) { rdpPrimaryUpdate* primary = update->primary; update->Palette = gdi_palette_update; update->SetBounds = gdi_set_bounds; primary->DstBlt = gdi_dstblt; primary->PatBlt = gdi_patblt; primary->ScrBlt = gdi_scrblt; primary->OpaqueRect = gdi_opaque_rect; primary->DrawNineGrid = NULL; primary->MultiDstBlt = NULL; primary->MultiPatBlt = NULL; primary->MultiScrBlt = NULL; primary->MultiOpaqueRect = gdi_multi_opaque_rect; primary->MultiDrawNineGrid = NULL; primary->LineTo = gdi_line_to; primary->Polyline = gdi_polyline; primary->MemBlt = gdi_memblt; primary->Mem3Blt = gdi_mem3blt; primary->SaveBitmap = NULL; primary->GlyphIndex = NULL; primary->FastIndex = NULL; primary->FastGlyph = NULL; primary->PolygonSC = gdi_polygon_sc; primary->PolygonCB = gdi_polygon_cb; primary->EllipseSC = gdi_ellipse_sc; primary->EllipseCB = gdi_ellipse_cb; update->SurfaceBits = gdi_surface_bits; } void gdi_init_primary(rdpGdi* gdi) { gdi->primary = gdi_bitmap_new_ex(gdi, gdi->width, gdi->height, gdi->dstBpp, gdi->primary_buffer); gdi->primary_buffer = gdi->primary->bitmap->data; if (gdi->drawing == NULL) gdi->drawing = gdi->primary; gdi->primary->hdc->hwnd = (HGDI_WND) malloc(sizeof(GDI_WND)); gdi->primary->hdc->hwnd->invalid = gdi_CreateRectRgn(0, 0, 0, 0); gdi->primary->hdc->hwnd->invalid->null = 1; gdi->primary->hdc->hwnd->count = 32; gdi->primary->hdc->hwnd->cinvalid = (HGDI_RGN) malloc(sizeof(GDI_RGN) * gdi->primary->hdc->hwnd->count); gdi->primary->hdc->hwnd->ninvalid = 0; } void gdi_resize(rdpGdi* gdi, int width, int height) { if (gdi && gdi->primary) { if (gdi->width != width || gdi->height != height) { if (gdi->drawing == gdi->primary) gdi->drawing = NULL; gdi->width = width; gdi->height = height; gdi_bitmap_free_ex(gdi->primary); gdi_init_primary(gdi); } } } /** * Initialize GDI * @param inst current instance * @return */ int gdi_init(freerdp* instance, uint32 flags, uint8* buffer) { rdpGdi* gdi; rdpCache* cache; gdi = (rdpGdi*) malloc(sizeof(rdpGdi)); memset(gdi, 0, sizeof(rdpGdi)); instance->context->gdi = gdi; cache = instance->context->cache; gdi->width = instance->settings->width; gdi->height = instance->settings->height; gdi->srcBpp = instance->settings->color_depth; gdi->primary_buffer = buffer; /* default internal buffer format */ gdi->dstBpp = 32; gdi->bytesPerPixel = 4; if (gdi->srcBpp > 16) { if (flags & CLRBUF_32BPP) { gdi->dstBpp = 32; gdi->bytesPerPixel = 4; } else if (flags & CLRBUF_24BPP) { gdi->dstBpp = 24; gdi->bytesPerPixel = 3; } else if (flags & CLRBUF_16BPP) { gdi->dstBpp = 16; gdi->bytesPerPixel = 2; } } else { if (flags & CLRBUF_16BPP) { gdi->dstBpp = 16; gdi->bytesPerPixel = 2; } else if (flags & CLRBUF_32BPP) { gdi->dstBpp = 32; gdi->bytesPerPixel = 4; } } gdi->hdc = gdi_GetDC(); gdi->hdc->bitsPerPixel = gdi->dstBpp; gdi->hdc->bytesPerPixel = gdi->bytesPerPixel; gdi->clrconv = (HCLRCONV) malloc(sizeof(CLRCONV)); gdi->clrconv->alpha = (flags & CLRCONV_ALPHA) ? 1 : 0; gdi->clrconv->invert = (flags & CLRCONV_INVERT) ? 1 : 0; gdi->clrconv->rgb555 = (flags & CLRCONV_RGB555) ? 1 : 0; gdi->clrconv->palette = (rdpPalette*) malloc(sizeof(rdpPalette)); gdi->hdc->alpha = gdi->clrconv->alpha; gdi->hdc->invert = gdi->clrconv->invert; gdi->hdc->rgb555 = gdi->clrconv->rgb555; gdi_init_primary(gdi); gdi->tile = gdi_bitmap_new_ex(gdi, 64, 64, 32, NULL); gdi->image = gdi_bitmap_new_ex(gdi, 64, 64, 32, NULL); if (cache == NULL) { cache = cache_new(instance->settings); instance->context->cache = cache; } gdi_register_update_callbacks(instance->update); brush_cache_register_callbacks(instance->update); glyph_cache_register_callbacks(instance->update); bitmap_cache_register_callbacks(instance->update); offscreen_cache_register_callbacks(instance->update); palette_cache_register_callbacks(instance->update); gdi_register_graphics(instance->context->graphics); gdi->rfx_context = rfx_context_new(); gdi->nsc_context = nsc_context_new(); return 0; } void gdi_free(freerdp* instance) { rdpGdi* gdi = instance->context->gdi; if (gdi) { gdi_bitmap_free_ex(gdi->primary); gdi_bitmap_free_ex(gdi->tile); gdi_bitmap_free_ex(gdi->image); gdi_DeleteDC(gdi->hdc); rfx_context_free((RFX_CONTEXT*)gdi->rfx_context); free(gdi->clrconv); free(gdi); } instance->context->gdi = (rdpGdi*) NULL; } FreeRDP-1.0.2/libfreerdp-gdi/gdi.h000066400000000000000000000016331207112532300165330ustar00rootroot00000000000000/** * FreeRDP: A Remote Desktop Protocol Client * GDI Library * * Copyright 2010-2011 Marc-Andre Moreau * * 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. */ #ifndef __GDI_CORE_H #define __GDI_CORE_H #include "graphics.h" gdiBitmap* gdi_bitmap_new_ex(rdpGdi* gdi, int width, int height, int bpp, uint8* data); void gdi_bitmap_free_ex(gdiBitmap* gdi_bmp); #endif /* __GDI_CORE_H */ FreeRDP-1.0.2/libfreerdp-gdi/graphics.c000066400000000000000000000142261207112532300175650ustar00rootroot00000000000000/** * FreeRDP: A Remote Desktop Protocol Client * Graphical Objects * * Copyright 2011 Marc-Andre Moreau * * 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. */ #include #include #include #include #include #include #include #include #include #include #include #include #include "graphics.h" /* Bitmap Class */ HGDI_BITMAP gdi_create_bitmap(rdpGdi* gdi, int width, int height, int bpp, uint8* data) { uint8* bmpData; HGDI_BITMAP bitmap; bmpData = freerdp_image_convert(data, NULL, width, height, gdi->srcBpp, bpp, gdi->clrconv); bitmap = gdi_CreateBitmap(width, height, gdi->dstBpp, bmpData); return bitmap; } void gdi_Bitmap_New(rdpContext* context, rdpBitmap* bitmap) { gdiBitmap* gdi_bitmap; rdpGdi* gdi = context->gdi; gdi_bitmap = (gdiBitmap*) bitmap; gdi_bitmap->hdc = gdi_CreateCompatibleDC(gdi->hdc); if (bitmap->data == NULL) gdi_bitmap->bitmap = gdi_CreateCompatibleBitmap(gdi->hdc, bitmap->width, bitmap->height); else gdi_bitmap->bitmap = gdi_create_bitmap(gdi, bitmap->width, bitmap->height, gdi->dstBpp, bitmap->data); gdi_SelectObject(gdi_bitmap->hdc, (HGDIOBJECT) gdi_bitmap->bitmap); gdi_bitmap->org_bitmap = NULL; } void gdi_Bitmap_Free(rdpContext* context, rdpBitmap* bitmap) { gdiBitmap* gdi_bitmap = (gdiBitmap*) bitmap; if (gdi_bitmap != NULL) { gdi_SelectObject(gdi_bitmap->hdc, (HGDIOBJECT) gdi_bitmap->org_bitmap); gdi_DeleteObject((HGDIOBJECT) gdi_bitmap->bitmap); gdi_DeleteDC(gdi_bitmap->hdc); } } void gdi_Bitmap_Paint(rdpContext* context, rdpBitmap* bitmap) { int width, height; gdiBitmap* gdi_bitmap = (gdiBitmap*) bitmap; width = bitmap->right - bitmap->left + 1; height = bitmap->bottom - bitmap->top + 1; gdi_BitBlt(context->gdi->primary->hdc, bitmap->left, bitmap->top, width, height, gdi_bitmap->hdc, 0, 0, GDI_SRCCOPY); } void gdi_Bitmap_Decompress(rdpContext* context, rdpBitmap* bitmap, uint8* data, int width, int height, int bpp, int length, boolean compressed) { uint16 size; size = width * height * (bpp + 7) / 8; if (bitmap->data == NULL) bitmap->data = (uint8*) xmalloc(size); else bitmap->data = (uint8*) xrealloc(bitmap->data, size); if (compressed) { boolean status; status = bitmap_decompress(data, bitmap->data, width, height, length, bpp, bpp); if (status != true) { printf("Bitmap Decompression Failed\n"); } } else { freerdp_image_flip(data, bitmap->data, width, height, bpp); } bitmap->width = width; bitmap->height = height; bitmap->compressed = false; bitmap->length = size; bitmap->bpp = bpp; } void gdi_Bitmap_SetSurface(rdpContext* context, rdpBitmap* bitmap, boolean primary) { rdpGdi* gdi = context->gdi; if (primary) gdi->drawing = gdi->primary; else gdi->drawing = (gdiBitmap*) bitmap; } /* Glyph Class */ void gdi_Glyph_New(rdpContext* context, rdpGlyph* glyph) { uint8* data; gdiGlyph* gdi_glyph; gdi_glyph = (gdiGlyph*) glyph; gdi_glyph->hdc = gdi_GetDC(); gdi_glyph->hdc->bytesPerPixel = 1; gdi_glyph->hdc->bitsPerPixel = 1; data = freerdp_glyph_convert(glyph->cx, glyph->cy, glyph->aj); gdi_glyph->bitmap = gdi_CreateBitmap(glyph->cx, glyph->cy, 1, data); gdi_glyph->bitmap->bytesPerPixel = 1; gdi_glyph->bitmap->bitsPerPixel = 1; gdi_SelectObject(gdi_glyph->hdc, (HGDIOBJECT) gdi_glyph->bitmap); gdi_glyph->org_bitmap = NULL; } void gdi_Glyph_Free(rdpContext* context, rdpGlyph* glyph) { gdiGlyph* gdi_glyph; gdi_glyph = (gdiGlyph*) glyph; if (gdi_glyph != 0) { gdi_SelectObject(gdi_glyph->hdc, (HGDIOBJECT) gdi_glyph->org_bitmap); gdi_DeleteObject((HGDIOBJECT) gdi_glyph->bitmap); gdi_DeleteDC(gdi_glyph->hdc); } } void gdi_Glyph_Draw(rdpContext* context, rdpGlyph* glyph, int x, int y) { gdiGlyph* gdi_glyph; rdpGdi* gdi = context->gdi; gdi_glyph = (gdiGlyph*) glyph; gdi_BitBlt(gdi->drawing->hdc, x, y, gdi_glyph->bitmap->width, gdi_glyph->bitmap->height, gdi_glyph->hdc, 0, 0, GDI_DSPDxax); } void gdi_Glyph_BeginDraw(rdpContext* context, int x, int y, int width, int height, uint32 bgcolor, uint32 fgcolor) { GDI_RECT rect; HGDI_BRUSH brush; rdpGdi* gdi = context->gdi; bgcolor = freerdp_color_convert_var_bgr(bgcolor, gdi->srcBpp, 32, gdi->clrconv); fgcolor = freerdp_color_convert_var_bgr(fgcolor, gdi->srcBpp, 32, gdi->clrconv); gdi_CRgnToRect(x, y, width, height, &rect); brush = gdi_CreateSolidBrush(fgcolor); gdi_FillRect(gdi->drawing->hdc, &rect, brush); gdi->textColor = gdi_SetTextColor(gdi->drawing->hdc, bgcolor); } void gdi_Glyph_EndDraw(rdpContext* context, int x, int y, int width, int height, uint32 bgcolor, uint32 fgcolor) { rdpGdi* gdi = context->gdi; bgcolor = freerdp_color_convert_var_bgr(bgcolor, gdi->srcBpp, 32, gdi->clrconv); gdi->textColor = gdi_SetTextColor(gdi->drawing->hdc, bgcolor); } /* Graphics Module */ void gdi_register_graphics(rdpGraphics* graphics) { rdpBitmap* bitmap; rdpGlyph* glyph; bitmap = xnew(rdpBitmap); bitmap->size = sizeof(gdiBitmap); bitmap->New = gdi_Bitmap_New; bitmap->Free = gdi_Bitmap_Free; bitmap->Paint = gdi_Bitmap_Paint; bitmap->Decompress = gdi_Bitmap_Decompress; bitmap->SetSurface = gdi_Bitmap_SetSurface; graphics_register_bitmap(graphics, bitmap); xfree(bitmap); glyph = xnew(rdpGlyph); glyph->size = sizeof(gdiGlyph); glyph->New = gdi_Glyph_New; glyph->Free = gdi_Glyph_Free; glyph->Draw = gdi_Glyph_Draw; glyph->BeginDraw = gdi_Glyph_BeginDraw; glyph->EndDraw = gdi_Glyph_EndDraw; graphics_register_glyph(graphics, glyph); xfree(glyph); } FreeRDP-1.0.2/libfreerdp-gdi/graphics.h000066400000000000000000000023461207112532300175720ustar00rootroot00000000000000/** * FreeRDP: A Remote Desktop Protocol Client * Graphical Objects * * Copyright 2011 Marc-Andre Moreau * * 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. */ #ifndef __GDI_GRAPHICS_H #define __GDI_GRAPHICS_H #include #include HGDI_BITMAP gdi_create_bitmap(rdpGdi* gdi, int width, int height, int bpp, uint8* data); void gdi_Bitmap_New(rdpContext* context, rdpBitmap* bitmap); void gdi_Bitmap_Free(rdpContext* context, rdpBitmap* bitmap); void gdi_Bitmap_Decompress(rdpContext* context, rdpBitmap* bitmap, uint8* data, int width, int height, int bpp, int length, boolean compressed); void gdi_register_graphics(rdpGraphics* graphics); #endif /* __GDI_GRAPHICS_H */ FreeRDP-1.0.2/libfreerdp-gdi/include/000077500000000000000000000000001207112532300172375ustar00rootroot00000000000000FreeRDP-1.0.2/libfreerdp-gdi/include/line.c000066400000000000000000000037001207112532300203320ustar00rootroot00000000000000/** * FreeRDP: A Remote Desktop Protocol Client * GDI LineTo * * Copyright 2010-2011 Marc-Andre Moreau * * 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. */ /* do not include this file directly! */ int LINE_TO(HGDI_DC hdc, int nXEnd, int nYEnd) { int x, y; int x1, y1; int x2, y2; int e, e2; int dx, dy; int sx, sy; int bx1, by1; int bx2, by2; PIXEL_TYPE pen; PIXEL_TYPE* pixel; HGDI_BITMAP bmp; x1 = hdc->pen->posX; y1 = hdc->pen->posY; x2 = nXEnd; y2 = nYEnd; dx = (x1 > x2) ? x1 - x2 : x2 - x1; dy = (y1 > y2) ? y1 - y2 : y2 - y1; sx = (x1 < x2) ? 1 : -1; sy = (y1 < y2) ? 1 : -1; e = dx - dy; x = x1; y = y1; bmp = (HGDI_BITMAP) hdc->selectedObject; if (hdc->clip->null) { bx1 = (x1 < x2) ? x1 : x2; by1 = (y1 < y2) ? y1 : y2; bx2 = (x1 > x2) ? x1 : x2; by2 = (y1 > y2) ? y1 : y2; } else { bx1 = hdc->clip->x; by1 = hdc->clip->y; bx2 = bx1 + hdc->clip->w - 1; by2 = by1 + hdc->clip->h - 1; } pen = GDI_GET_PEN_COLOR(hdc->pen); while (1) { if (!(x == x2 && y == y2)) { if ((x >= bx1 && x <= bx2) && (y >= by1 && y <= by2)) { pixel = GDI_GET_POINTER(bmp, x, y); SET_PIXEL_ROP2(pixel, &pen); } } else { break; } e2 = 2 * e; if (e2 > -dy) { e -= dy; x += sx; } if (e2 < dx) { e += dx; y += sy; } } return 1; } /* #undef LINE_TO #undef PIXEL_TYPE #undef SET_PIXEL_ROP2 #undef GDI_GET_POINTER #undef GDI_GET_PEN_COLOR */ FreeRDP-1.0.2/libfreerdp-gdi/line.c000066400000000000000000000062121207112532300167100ustar00rootroot00000000000000/** * FreeRDP: A Remote Desktop Protocol Client * GDI Line Functions * * Copyright 2010-2011 Marc-Andre Moreau * * 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. */ #include #include #include #include #include #include #include #include #include p_LineTo LineTo_[5] = { NULL, LineTo_8bpp, LineTo_16bpp, NULL, LineTo_32bpp }; /** * Draw a line from the current position to the given position.\n * @msdn{dd145029} * @param hdc device context * @param nXEnd ending x position * @param nYEnd ending y position * @return 1 if successful, 0 otherwise */ int gdi_LineTo(HGDI_DC hdc, int nXEnd, int nYEnd) { p_LineTo _LineTo = LineTo_[IBPP(hdc->bitsPerPixel)]; if (_LineTo != NULL) return _LineTo(hdc, nXEnd, nYEnd); else return 0; } /** * Draw one or more straight lines * @param hdc device context * @param lppt array of points * @param cCount number of points * @return */ int gdi_PolylineTo(HGDI_DC hdc, GDI_POINT *lppt, int cCount) { int i; for (i = 0; i < cCount; i++) { gdi_LineTo(hdc, lppt[i].x, lppt[i].y); gdi_MoveToEx(hdc, lppt[i].x, lppt[i].y, NULL); } return 1; } /** * Draw one or more straight lines * @param hdc device context * @param lppt array of points * @param cPoints number of points * @return */ int gdi_Polyline(HGDI_DC hdc, GDI_POINT *lppt, int cPoints) { if (cPoints > 0) { int i; GDI_POINT pt; gdi_MoveToEx(hdc, lppt[0].x, lppt[0].y, &pt); for (i = 0; i < cPoints; i++) { gdi_LineTo(hdc, lppt[i].x, lppt[i].y); gdi_MoveToEx(hdc, lppt[i].x, lppt[i].y, NULL); } gdi_MoveToEx(hdc, pt.x, pt.y, NULL); } return 1; } /** * Draw multiple series of connected line segments * @param hdc device context * @param lppt array of points * @param lpdwPolyPoints array of numbers of points per series * @param cCount count of entries in lpdwPolyPoints * @return */ int gdi_PolyPolyline(HGDI_DC hdc, GDI_POINT *lppt, int *lpdwPolyPoints, int cCount) { int cPoints; int i, j = 0; for (i = 0; i < cCount; i++) { cPoints = lpdwPolyPoints[i]; gdi_Polyline(hdc, &lppt[j], cPoints); j += cPoints; } return 1; } /** * Move pen from the current device context to a new position. * @param hdc device context * @param X x position * @param Y y position * @return 1 if successful, 0 otherwise */ int gdi_MoveToEx(HGDI_DC hdc, int X, int Y, HGDI_POINT lpPoint) { if (lpPoint != NULL) { lpPoint->x = hdc->pen->posX; lpPoint->y = hdc->pen->posY; } hdc->pen->posX = X; hdc->pen->posY = Y; return 1; } FreeRDP-1.0.2/libfreerdp-gdi/palette.c000066400000000000000000000053151207112532300174220ustar00rootroot00000000000000/** * FreeRDP: A Remote Desktop Protocol Client * GDI Palette Functions * * Copyright 2010-2011 Marc-Andre Moreau * * 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. */ /* GDI Palette Functions: http://msdn.microsoft.com/en-us/library/dd183454/ */ #include #include #include #include #include #include static HGDI_PALETTE hSystemPalette = NULL; static const GDI_PALETTEENTRY default_system_palette[20] = { /* First 10 entries */ { 0x00, 0x00, 0x00 }, { 0x80, 0x00, 0x00 }, { 0x00, 0x80, 0x00 }, { 0x80, 0x80, 0x00 }, { 0x00, 0x00, 0x80 }, { 0x80, 0x00, 0x80 }, { 0x00, 0x80, 0x80 }, { 0xC0, 0xC0, 0xC0 }, { 0xC0, 0xDC, 0xC0 }, { 0xA6, 0xCA, 0xF0 }, /* Last 10 entries */ { 0xFF, 0xFB, 0xF0 }, { 0xA0, 0xA0, 0xA4 }, { 0x80, 0x80, 0x80 }, { 0xFF, 0x00, 0x00 }, { 0x00, 0xFF, 0x00 }, { 0xFF, 0xFF, 0x00 }, { 0x00, 0x00, 0xFF }, { 0xFF, 0x00, 0xFF }, { 0x00, 0xFF, 0xFF }, { 0xFF, 0xFF, 0xFF } }; /** * Create a new palette.\n * @msdn{dd183507} * @param original palette * @return new palette */ HGDI_PALETTE gdi_CreatePalette(HGDI_PALETTE palette) { HGDI_PALETTE hPalette = (HGDI_PALETTE) malloc(sizeof(GDI_PALETTE)); hPalette->count = palette->count; hPalette->entries = (GDI_PALETTEENTRY*) malloc(sizeof(GDI_PALETTEENTRY) * hPalette->count); memcpy(hPalette->entries, palette->entries, sizeof(GDI_PALETTEENTRY) * hPalette->count); return hPalette; } /** * Create system palette\n * @return system palette */ HGDI_PALETTE CreateSystemPalette() { HGDI_PALETTE palette = (HGDI_PALETTE) malloc(sizeof(GDI_PALETTE)); palette->count = 256; palette->entries = (GDI_PALETTEENTRY*) malloc(sizeof(GDI_PALETTEENTRY) * 256); memset(palette->entries, 0, sizeof(GDI_PALETTEENTRY) * 256); memcpy(&palette->entries[0], &default_system_palette[0], 10 * sizeof(GDI_PALETTEENTRY)); memcpy(&palette->entries[256 - 10], &default_system_palette[10], 10 * sizeof(GDI_PALETTEENTRY)); return palette; } /** * Get system palette\n * @return system palette */ HGDI_PALETTE gdi_GetSystemPalette() { if (hSystemPalette == NULL) hSystemPalette = CreateSystemPalette(); return hSystemPalette; } FreeRDP-1.0.2/libfreerdp-gdi/pen.c000066400000000000000000000032611207112532300165440ustar00rootroot00000000000000/** * FreeRDP: A Remote Desktop Protocol Client * GDI Pen Functions * * Copyright 2010-2011 Marc-Andre Moreau * * 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. */ /* GDI Pen Functions: http://msdn.microsoft.com/en-us/library/dd162790 */ #include #include #include #include #include #include #include /** * Create a new pen.\n * @msdn{dd183509} * @param fnPenStyle pen style * @param nWidth pen width * @param crColor pen color * @return new pen */ HGDI_PEN gdi_CreatePen(int fnPenStyle, int nWidth, int crColor) { HGDI_PEN hPen = (HGDI_PEN) malloc(sizeof(GDI_PEN)); hPen->objectType = GDIOBJECT_PEN; hPen->style = fnPenStyle; hPen->color = crColor; hPen->width = nWidth; return hPen; } INLINE uint8 gdi_GetPenColor_8bpp(HGDI_PEN pen) { /* TODO: implement conversion using palette */ return 0xFF; } INLINE uint16 gdi_GetPenColor_16bpp(HGDI_PEN pen) { uint16 p; int r, g, b; GetRGB32(r, g, b, pen->color); RGB_888_565(r, g, b); p = RGB16(r, g, b); return p; } INLINE uint32 gdi_GetPenColor_32bpp(HGDI_PEN pen) { return pen->color; } FreeRDP-1.0.2/libfreerdp-gdi/region.c000066400000000000000000000211741207112532300172500ustar00rootroot00000000000000/** * FreeRDP: A Remote Desktop Protocol Client * GDI Region Functions * * Copyright 2010-2011 Marc-Andre Moreau * * 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. */ #include #include #include #include #include #include #include /** * Create a region from rectangular coordinates.\n * @msdn{dd183514} * @param nLeftRect x1 * @param nTopRect y1 * @param nRightRect x2 * @param nBottomRect y2 * @return new region */ HGDI_RGN gdi_CreateRectRgn(int nLeftRect, int nTopRect, int nRightRect, int nBottomRect) { HGDI_RGN hRgn = (HGDI_RGN) malloc(sizeof(GDI_RGN)); hRgn->objectType = GDIOBJECT_REGION; hRgn->x = nLeftRect; hRgn->y = nTopRect; hRgn->w = nRightRect - nLeftRect + 1; hRgn->h = nBottomRect - nTopRect + 1; hRgn->null = 0; return hRgn; } /** * Create a new rectangle. * @param xLeft x1 * @param yTop y1 * @param xRight x2 * @param yBottom y2 * @return new rectangle */ HGDI_RECT gdi_CreateRect(int xLeft, int yTop, int xRight, int yBottom) { HGDI_RECT hRect = (HGDI_RECT) malloc(sizeof(GDI_RECT)); hRect->objectType = GDIOBJECT_RECT; hRect->left = xLeft; hRect->top = yTop; hRect->right = xRight; hRect->bottom = yBottom; return hRect; } /** * Convert a rectangle to a region. * @param rect source rectangle * @param rgn destination region */ INLINE void gdi_RectToRgn(HGDI_RECT rect, HGDI_RGN rgn) { rgn->x = rect->left; rgn->y = rect->top; rgn->w = rect->right - rect->left + 1; rgn->h = rect->bottom - rect->top + 1; } /** * Convert rectangular coordinates to a region. * @param left x1 * @param top y1 * @param right x2 * @param bottom y2 * @param rgn destination region */ INLINE void gdi_CRectToRgn(int left, int top, int right, int bottom, HGDI_RGN rgn) { rgn->x = left; rgn->y = top; rgn->w = right - left + 1; rgn->h = bottom - top + 1; } /** * Convert a rectangle to region coordinates. * @param rect source rectangle * @param x x1 * @param y y1 * @param w width * @param h height */ INLINE void gdi_RectToCRgn(HGDI_RECT rect, int *x, int *y, int *w, int *h) { *x = rect->left; *y = rect->top; *w = rect->right - rect->left + 1; *h = rect->bottom - rect->top + 1; } /** * Convert rectangular coordinates to region coordinates. * @param left x1 * @param top y1 * @param right x2 * @param bottom y2 * @param x x1 * @param y y1 * @param w width * @param h height */ INLINE void gdi_CRectToCRgn(int left, int top, int right, int bottom, int *x, int *y, int *w, int *h) { *x = left; *y = top; *w = right - left + 1; *h = bottom - top + 1; } /** * Convert a region to a rectangle. * @param rgn source region * @param rect destination rectangle */ INLINE void gdi_RgnToRect(HGDI_RGN rgn, HGDI_RECT rect) { rect->left = rgn->x; rect->top = rgn->y; rect->right = rgn->x + rgn->w - 1; rect->bottom = rgn->y + rgn->h - 1; } /** * Convert region coordinates to a rectangle. * @param x x1 * @param y y1 * @param w width * @param h height * @param rect destination rectangle */ INLINE void gdi_CRgnToRect(int x, int y, int w, int h, HGDI_RECT rect) { rect->left = x; rect->top = y; rect->right = x + w - 1; rect->bottom = y + h - 1; } /** * Convert a region to rectangular coordinates. * @param rgn source region * @param left x1 * @param top y1 * @param right x2 * @param bottom y2 */ INLINE void gdi_RgnToCRect(HGDI_RGN rgn, int *left, int *top, int *right, int *bottom) { *left = rgn->x; *top = rgn->y; *right = rgn->x + rgn->w - 1; *bottom = rgn->y + rgn->h - 1; } /** * Convert region coordinates to rectangular coordinates. * @param x x1 * @param y y1 * @param w width * @param h height * @param left x1 * @param top y1 * @param right x2 * @param bottom y2 */ INLINE void gdi_CRgnToCRect(int x, int y, int w, int h, int *left, int *top, int *right, int *bottom) { *left = x; *top = y; *right = x + w - 1; *bottom = y + h - 1; } /** * Check if copying would involve overlapping regions * @param x x1 * @param y y1 * @param width width * @param height height * @param srcx source x1 * @param srcy source y1 * @return 1 if there is an overlap, 0 otherwise */ INLINE int gdi_CopyOverlap(int x, int y, int width, int height, int srcx, int srcy) { GDI_RECT dst; GDI_RECT src; gdi_CRgnToRect(x, y, width, height, &dst); gdi_CRgnToRect(srcx, srcy, width, height, &src); return (dst.right > src.left && dst.left < src.right && dst.bottom > src.top && dst.top < src.bottom) ? 1 : 0; } /** * Set the coordinates of a given rectangle.\n * @msdn{dd145085} * @param rc rectangle * @param xLeft x1 * @param yTop y1 * @param xRight x2 * @param yBottom y2 * @return 1 if successful, 0 otherwise */ INLINE int gdi_SetRect(HGDI_RECT rc, int xLeft, int yTop, int xRight, int yBottom) { rc->left = xLeft; rc->top = yTop; rc->right = xRight; rc->bottom = yBottom; return 1; } /** * Set the coordinates of a given region. * @param hRgn region * @param nXLeft x1 * @param nYLeft y1 * @param nWidth width * @param nHeight height * @return */ INLINE int gdi_SetRgn(HGDI_RGN hRgn, int nXLeft, int nYLeft, int nWidth, int nHeight) { hRgn->x = nXLeft; hRgn->y = nYLeft; hRgn->w = nWidth; hRgn->h = nHeight; hRgn->null = 0; return 0; } /** * Convert rectangular coordinates to a region * @param hRgn destination region * @param nLeftRect x1 * @param nTopRect y1 * @param nRightRect x2 * @param nBottomRect y2 * @return */ INLINE int gdi_SetRectRgn(HGDI_RGN hRgn, int nLeftRect, int nTopRect, int nRightRect, int nBottomRect) { gdi_CRectToRgn(nLeftRect, nTopRect, nRightRect, nBottomRect, hRgn); hRgn->null = 0; return 0; } /** * Compare two regions for equality.\n * @msdn{dd162700} * @param hSrcRgn1 first region * @param hSrcRgn2 second region * @return 1 if both regions are equal, 0 otherwise */ INLINE int gdi_EqualRgn(HGDI_RGN hSrcRgn1, HGDI_RGN hSrcRgn2) { if ((hSrcRgn1->x == hSrcRgn2->x) && (hSrcRgn1->y == hSrcRgn2->y) && (hSrcRgn1->w == hSrcRgn2->w) && (hSrcRgn1->h == hSrcRgn2->h)) { return 1; } return 0; } /** * Copy coordinates from a rectangle to another rectangle * @param dst destination rectangle * @param src source rectangle * @return 1 if successful, 0 otherwise */ INLINE int gdi_CopyRect(HGDI_RECT dst, HGDI_RECT src) { dst->left = src->left; dst->top = src->top; dst->right = src->right; dst->bottom = src->bottom; return 1; } /** * Check if a point is inside a rectangle.\n * @msdn{dd162882} * @param rc rectangle * @param x point x position * @param y point y position * @return 1 if the point is inside, 0 otherwise */ INLINE int gdi_PtInRect(HGDI_RECT rc, int x, int y) { /* * points on the left and top sides are considered in, * while points on the right and bottom sides are considered out */ if (x >= rc->left && x <= rc->right) { if (y >= rc->top && y <= rc->bottom) { return 1; } } return 0; } /** * Invalidate a given region, such that it is redrawn on the next region update.\n * @msdn{dd145003} * @param hdc device context * @param x x1 * @param y y1 * @param w width * @param h height * @return */ INLINE int gdi_InvalidateRegion(HGDI_DC hdc, int x, int y, int w, int h) { GDI_RECT inv; GDI_RECT rgn; HGDI_RGN invalid; HGDI_RGN cinvalid; if (hdc->hwnd == NULL) return 0; if (hdc->hwnd->invalid == NULL) return 0; cinvalid = hdc->hwnd->cinvalid; if (hdc->hwnd->ninvalid + 1 > hdc->hwnd->count) { hdc->hwnd->count *= 2; cinvalid = (HGDI_RGN) realloc(cinvalid, sizeof(GDI_RGN) * (hdc->hwnd->count)); } gdi_SetRgn(&cinvalid[hdc->hwnd->ninvalid++], x, y, w, h); hdc->hwnd->cinvalid = cinvalid; invalid = hdc->hwnd->invalid; if (invalid->null) { invalid->x = x; invalid->y = y; invalid->w = w; invalid->h = h; invalid->null = 0; return 0; } gdi_CRgnToRect(x, y, w, h, &rgn); gdi_RgnToRect(invalid, &inv); if (rgn.left < 0) rgn.left = 0; if (rgn.top < 0) rgn.top = 0; if (rgn.left < inv.left) inv.left = rgn.left; if (rgn.top < inv.top) inv.top = rgn.top; if (rgn.right > inv.right) inv.right = rgn.right; if (rgn.bottom > inv.bottom) inv.bottom = rgn.bottom; gdi_RectToRgn(&inv, invalid); return 0; } FreeRDP-1.0.2/libfreerdp-gdi/shape.c000066400000000000000000000106431207112532300170640ustar00rootroot00000000000000/** * FreeRDP: A Remote Desktop Protocol Client * GDI Shape Functions * * Copyright 2010-2011 Marc-Andre Moreau * * 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. */ #include #include #include #include #include #include #include #include #include #include p_FillRect FillRect_[5] = { NULL, FillRect_8bpp, FillRect_16bpp, NULL, FillRect_32bpp }; static void Ellipse_Bresenham(HGDI_DC hdc, int x1, int y1, int x2, int y2) { int i; long e, e2; long dx, dy; int a, b, c; HGDI_BITMAP bmp; uint8 pixel8; uint16 pixel16; uint32 pixel32; int bpp = hdc->bitsPerPixel; a = (x1 < x2) ? x2 - x1 : x1 - x2; b = (y1 < y2) ? y2 - y1 : y1 - y2; c = b & 1; dx = 4 * (1 - a) * b * b; dy = 4 * (c + 1) * a * a; e = dx + dy + c * a * a; if (x1 > x2) { x1 = x2; x2 += a; } if (y1 > y2) y1 = y2; y1 += (b + 1) / 2; y2 = y1 - c; a *= 8 * a; c = 8 * b * b; pixel8 = 0; pixel16 = 0; pixel32 = 0; bmp = (HGDI_BITMAP) hdc->selectedObject; do { if (bpp == 32) { gdi_SetPixel_32bpp(bmp, x2, y1, pixel32); gdi_SetPixel_32bpp(bmp, x1, y1, pixel32); gdi_SetPixel_32bpp(bmp, x1, y2, pixel32); gdi_SetPixel_32bpp(bmp, x2, y2, pixel32); } else if (bpp == 16) { gdi_SetPixel_16bpp(bmp, x2, y1, pixel16); gdi_SetPixel_16bpp(bmp, x1, y1, pixel16); gdi_SetPixel_16bpp(bmp, x1, y2, pixel16); gdi_SetPixel_16bpp(bmp, x2, y2, pixel16); } else if (bpp == 8) { for (i = x1; i < x2; i++) { gdi_SetPixel_8bpp(bmp, i, y1, pixel8); gdi_SetPixel_8bpp(bmp, i, y2, pixel8); } for (i = y1; i < y2; i++) { gdi_SetPixel_8bpp(bmp, x1, i, pixel8); gdi_SetPixel_8bpp(bmp, x2, i, pixel8); } } e2 = 2 * e; if (e2 >= dx) { x1++; x2--; e += dx += c; } if (e2 <= dy) { y1++; y2--; e += dy += a; } } while (x1 <= x2); while (y1 - y2 < b) { if (bpp == 32) { gdi_SetPixel_32bpp(bmp, x1 - 1, ++y1, pixel32); gdi_SetPixel_32bpp(bmp, x1 - 1, --y2, pixel32); } else if (bpp == 16) { gdi_SetPixel_16bpp(bmp, x1 - 1, ++y1, pixel16); gdi_SetPixel_16bpp(bmp, x1 - 1, --y2, pixel16); } else if (bpp == 8) { gdi_SetPixel_8bpp(bmp, x1 - 1, ++y1, pixel8); gdi_SetPixel_8bpp(bmp, x1 - 1, --y2, pixel8); } } } /** * Draw an ellipse * @param hdc device context * @param nLeftRect x1 * @param nTopRect y1 * @param nRightRect x2 * @param nBottomRect y2 * @return */ int gdi_Ellipse(HGDI_DC hdc, int nLeftRect, int nTopRect, int nRightRect, int nBottomRect) { Ellipse_Bresenham(hdc, nLeftRect, nTopRect, nRightRect, nBottomRect); return 1; } /** * Fill a rectangle with the given brush.\n * @msdn{dd162719} * @param hdc device context * @param rect rectangle * @param hbr brush * @return 1 if successful, 0 otherwise */ int gdi_FillRect(HGDI_DC hdc, HGDI_RECT rect, HGDI_BRUSH hbr) { p_FillRect _FillRect = FillRect_[IBPP(hdc->bitsPerPixel)]; if (_FillRect != NULL) return _FillRect(hdc, rect, hbr); else return 0; } /** * * @param hdc device context * @param lpPoints array of points * @param nCount number of points * @return */ int gdi_Polygon(HGDI_DC hdc, GDI_POINT *lpPoints, int nCount) { return 1; } /** * Draw a series of closed polygons * @param hdc device context * @param lpPoints array of series of points * @param lpPolyCounts array of number of points in each series * @param nCount count of number of points in lpPolyCounts * @return */ int gdi_PolyPolygon(HGDI_DC hdc, GDI_POINT *lpPoints, int *lpPolyCounts, int nCount) { return 1; } /** * Draw a rectangle * @param hdc device context * @param nLeftRect x1 * @param nTopRect y1 * @param nRightRect x2 * @param nBottomRect y2 * @return */ int gdi_Rectangle(HGDI_DC hdc, int nLeftRect, int nTopRect, int nRightRect, int nBottomRect) { return 1; } FreeRDP-1.0.2/libfreerdp-kbd/000077500000000000000000000000001207112532300156115ustar00rootroot00000000000000FreeRDP-1.0.2/libfreerdp-kbd/CMakeLists.txt000066400000000000000000000030511207112532300203500ustar00rootroot00000000000000# FreeRDP: A Remote Desktop Protocol Client # libfreerdp-kbd cmake build script # # Copyright 2011 O.S. Systems Software Ltda. # Copyright 2011 Otavio Salvador # Copyright 2011 Marc-Andre Moreau # # 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(FREERDP_KBD_SRCS locales.c layouts.c layouts_xkb.c layouts_xkb.h x_layout_id_table.c x_layout_id_table.h libkbd.c libkbd.h) add_library(freerdp-kbd ${FREERDP_KBD_SRCS}) find_suggested_package(X11) if(WITH_X11) target_link_libraries(freerdp-kbd ${X11_LIBRARIES}) endif() if(NOT APPLE) find_suggested_package(XKBFile) if(WITH_X11) if(WITH_XKBFILE) add_definitions(-DWITH_XKBFILE) include_directories(${XKBFILE_INCLUDE_DIRS}) target_link_libraries(freerdp-kbd ${XKBFILE_LIBRARIES}) endif() endif() endif() add_definitions(-DKEYMAP_PATH="${FREERDP_KEYMAP_PATH}") set_target_properties(freerdp-kbd PROPERTIES VERSION ${FREERDP_VERSION_FULL} SOVERSION ${FREERDP_VERSION} PREFIX "lib") install(TARGETS freerdp-kbd DESTINATION ${CMAKE_INSTALL_LIBDIR}) FreeRDP-1.0.2/libfreerdp-kbd/layouts.c000066400000000000000000000254771207112532300174740ustar00rootroot00000000000000/** * FreeRDP: A Remote Desktop Protocol Client * XKB-based Keyboard Mapping to Microsoft Keyboard System * * Copyright 2009 Marc-Andre Moreau * * 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. */ #include #include #include #include "libkbd.h" #include typedef struct { /* Keyboard layout code */ unsigned int code; /* Keyboard layout name */ char name[50]; } keyboardLayout; /* * In Windows XP, this information is available in the system registry at * HKEY_LOCAL_MACHINE/SYSTEM/CurrentControlSet001/Control/Keyboard Layouts/ */ static const keyboardLayout keyboardLayouts[] = { { KBD_ARABIC_101, "Arabic (101)" }, { KBD_BULGARIAN, "Bulgarian" }, { KBD_CHINESE_TRADITIONAL_US, "Chinese (Traditional) - US Keyboard" }, { KBD_CZECH, "Czech" }, { KBD_DANISH, "Danish" }, { KBD_GERMAN, "German" }, { KBD_GREEK, "Greek" }, { KBD_US, "US" }, { KBD_SPANISH, "Spanish" }, { KBD_FINNISH, "Finnish" }, { KBD_FRENCH, "French" }, { KBD_HEBREW, "Hebrew" }, { KBD_HUNGARIAN, "Hungarian" }, { KBD_ICELANDIC, "Icelandic" }, { KBD_ITALIAN, "Italian" }, { KBD_JAPANESE, "Japanese" }, { KBD_KOREAN, "Korean" }, { KBD_DUTCH, "Dutch" }, { KBD_NORWEGIAN, "Norwegian" }, { KBD_POLISH_PROGRAMMERS, "Polish (Programmers)" }, { KBD_PORTUGUESE_BRAZILIAN_ABNT,"Portuguese (Brazilian ABNT)" }, { KBD_ROMANIAN, "Romanian" }, { KBD_RUSSIAN, "Russian" }, { KBD_CROATIAN, "Croatian" }, { KBD_SLOVAK, "Slovak" }, { KBD_ALBANIAN, "Albanian" }, { KBD_SWEDISH, "Swedish" }, { KBD_THAI_KEDMANEE, "Thai Kedmanee" }, { KBD_TURKISH_Q, "Turkish Q" }, { KBD_URDU, "Urdu" }, { KBD_UKRAINIAN, "Ukrainian" }, { KBD_BELARUSIAN, "Belarusian" }, { KBD_SLOVENIAN, "Slovenian" }, { KBD_ESTONIAN, "Estonian" }, { KBD_LATVIAN, "Latvian" }, { KBD_LITHUANIAN_IBM, "Lithuanian IBM" }, { KBD_FARSI, "Farsi" }, { KBD_VIETNAMESE, "Vietnamese" }, { KBD_ARMENIAN_EASTERN, "Armenian Eastern" }, { KBD_AZERI_LATIN, "Azeri Latin" }, { KBD_FYRO_MACEDONIAN, "FYRO Macedonian" }, { KBD_GEORGIAN, "Georgian" }, { KBD_FAEROESE, "Faeroese" }, { KBD_DEVANAGARI_INSCRIPT, "Devanagari - INSCRIPT" }, { KBD_MALTESE_47_KEY, "Maltese 47-key" }, { KBD_NORWEGIAN_WITH_SAMI, "Norwegian with Sami" }, { KBD_KAZAKH, "Kazakh" }, { KBD_KYRGYZ_CYRILLIC, "Kyrgyz Cyrillic" }, { KBD_TATAR, "Tatar" }, { KBD_BENGALI, "Bengali" }, { KBD_PUNJABI, "Punjabi" }, { KBD_GUJARATI, "Gujarati" }, { KBD_TAMIL, "Tamil" }, { KBD_TELUGU, "Telugu" }, { KBD_KANNADA, "Kannada" }, { KBD_MALAYALAM, "Malayalam" }, { KBD_MARATHI, "Marathi" }, { KBD_MONGOLIAN_CYRILLIC, "Mongolian Cyrillic" }, { KBD_UNITED_KINGDOM_EXTENDED, "United Kingdom Extended" }, { KBD_SYRIAC, "Syriac" }, { KBD_NEPALI, "Nepali" }, { KBD_PASHTO, "Pashto" }, { KBD_DIVEHI_PHONETIC, "Divehi Phonetic" }, { KBD_LUXEMBOURGISH, "Luxembourgish" }, { KBD_MAORI, "Maori" }, { KBD_CHINESE_SIMPLIFIED_US, "Chinese (Simplified) - US Keyboard" }, { KBD_SWISS_GERMAN, "Swiss German" }, { KBD_UNITED_KINGDOM, "United Kingdom" }, { KBD_LATIN_AMERICAN, "Latin American" }, { KBD_BELGIAN_FRENCH, "Belgian French" }, { KBD_BELGIAN_PERIOD, "Belgian (Period)" }, { KBD_PORTUGUESE, "Portuguese" }, { KBD_SERBIAN_LATIN, "Serbian (Latin)" }, { KBD_AZERI_CYRILLIC, "Azeri Cyrillic" }, { KBD_SWEDISH_WITH_SAMI, "Swedish with Sami" }, { KBD_UZBEK_CYRILLIC, "Uzbek Cyrillic" }, { KBD_INUKTITUT_LATIN, "Inuktitut Latin" }, { KBD_CANADIAN_FRENCH_LEGACY, "Canadian French (legacy)" }, { KBD_SERBIAN_CYRILLIC, "Serbian (Cyrillic)" }, { KBD_CANADIAN_FRENCH, "Canadian French" }, { KBD_SWISS_FRENCH, "Swiss French" }, { KBD_BOSNIAN, "Bosnian" }, { KBD_IRISH, "Irish" }, { KBD_BOSNIAN_CYRILLIC, "Bosnian Cyrillic" } }; typedef struct { /* Keyboard layout code */ unsigned int code; /* Keyboard variant ID */ unsigned short id; /* Keyboard layout variant name */ char name[50]; } keyboardLayoutVariant; static const keyboardLayoutVariant keyboardLayoutVariants[] = { { KBD_ARABIC_102, 0x0028, "Arabic (102)" }, { KBD_BULGARIAN_LATIN, 0x0004, "Bulgarian (Latin)" }, { KBD_CZECH_QWERTY, 0x0005, "Czech (QWERTY)" }, { KBD_GERMAN_IBM, 0x0012, "German (IBM)" }, { KBD_GREEK_220, 0x0016, "Greek (220)" }, { KBD_UNITED_STATES_DVORAK, 0x0002, "United States-Dvorak" }, { KBD_SPANISH_VARIATION, 0x0086, "Spanish Variation" }, { KBD_HUNGARIAN_101_KEY, 0x0006, "Hungarian 101-key" }, { KBD_ITALIAN_142, 0x0003, "Italian (142)" }, { KBD_POLISH_214, 0x0007, "Polish (214)" }, { KBD_PORTUGUESE_BRAZILIAN_ABNT2, 0x001D, "Portuguese (Brazilian ABNT2)" }, { KBD_RUSSIAN_TYPEWRITER, 0x0008, "Russian (Typewriter)" }, { KBD_SLOVAK_QWERTY, 0x0013, "Slovak (QWERTY)" }, { KBD_THAI_PATTACHOTE, 0x0021, "Thai Pattachote" }, { KBD_TURKISH_F, 0x0014, "Turkish F" }, { KBD_LATVIAN_QWERTY, 0x0015, "Latvian (QWERTY)" }, { KBD_LITHUANIAN, 0x0027, "Lithuanian" }, { KBD_ARMENIAN_WESTERN, 0x0025, "Armenian Western" }, { KBD_HINDI_TRADITIONAL, 0x000C, "Hindi Traditional" }, { KBD_MALTESE_48_KEY, 0x002B, "Maltese 48-key" }, { KBD_SAMI_EXTENDED_NORWAY, 0x002C, "Sami Extended Norway" }, { KBD_BENGALI_INSCRIPT, 0x002A, "Bengali (Inscript)" }, { KBD_SYRIAC_PHONETIC, 0x000E, "Syriac Phonetic" }, { KBD_DIVEHI_TYPEWRITER, 0x000D, "Divehi Typewriter" }, { KBD_BELGIAN_COMMA, 0x001E, "Belgian (Comma)" }, { KBD_FINNISH_WITH_SAMI, 0x002D, "Finnish with Sami" }, { KBD_CANADIAN_MULTILINGUAL_STANDARD, 0x0020, "Canadian Multilingual Standard" }, { KBD_GAELIC, 0x0026, "Gaelic" }, { KBD_ARABIC_102_AZERTY, 0x0029, "Arabic (102) AZERTY" }, { KBD_CZECH_PROGRAMMERS, 0x000A, "Czech Programmers" }, { KBD_GREEK_319, 0x0018, "Greek (319)" }, { KBD_UNITED_STATES_INTERNATIONAL, 0x0001, "United States-International" }, { KBD_THAI_KEDMANEE_NON_SHIFTLOCK, 0x0022, "Thai Kedmanee (non-ShiftLock)" }, { KBD_SAMI_EXTENDED_FINLAND_SWEDEN, 0x002E, "Sami Extended Finland-Sweden" }, { KBD_GREEK_220_LATIN, 0x0017, "Greek (220) Latin" }, { KBD_UNITED_STATES_DVORAK_FOR_LEFT_HAND, 0x001A, "United States-Dvorak for left hand" }, { KBD_THAI_PATTACHOTE_NON_SHIFTLOCK, 0x0023, "Thai Pattachote (non-ShiftLock)" }, { KBD_GREEK_319_LATIN, 0x0011, "Greek (319) Latin" }, { KBD_UNITED_STATES_DVORAK_FOR_RIGHT_HAND, 0x001B, "United States-Dvorak for right hand" }, { KBD_GREEK_LATIN, 0x0019, "Greek Latin" }, { KBD_US_ENGLISH_TABLE_FOR_IBM_ARABIC_238_L, 0x000B, "US English Table for IBM Arabic 238_L" }, { KBD_GREEK_POLYTONIC, 0x001F, "Greek Polytonic" }, { KBD_GERMAN_NEO, 0x00C0, "German Neo" } }; /* Input Method Editor (IME) */ typedef struct { /* Keyboard layout code */ unsigned int code; /* IME file name */ char fileName[32]; /* Keyboard layout name */ char name[50]; } keyboardIME; /* Global Input Method Editors (IME) */ static const keyboardIME keyboardIMEs[] = { { KBD_CHINESE_TRADITIONAL_PHONETIC, "phon.ime", "Chinese (Traditional) - Phonetic" }, { KBD_JAPANESE_INPUT_SYSTEM_MS_IME2002, "imjp81.ime", "Japanese Input System (MS-IME2002)" }, { KBD_KOREAN_INPUT_SYSTEM_IME_2000, "imekr61.ime", "Korean Input System (IME 2000)" }, { KBD_CHINESE_SIMPLIFIED_QUANPIN, "winpy.ime", "Chinese (Simplified) - QuanPin" }, { KBD_CHINESE_TRADITIONAL_CHANGJIE, "chajei.ime", "Chinese (Traditional) - ChangJie" }, { KBD_CHINESE_SIMPLIFIED_SHUANGPIN, "winsp.ime", "Chinese (Simplified) - ShuangPin" }, { KBD_CHINESE_TRADITIONAL_QUICK, "quick.ime", "Chinese (Traditional) - Quick" }, { KBD_CHINESE_SIMPLIFIED_ZHENGMA, "winzm.ime", "Chinese (Simplified) - ZhengMa" }, { KBD_CHINESE_TRADITIONAL_BIG5_CODE, "winime.ime", "Chinese (Traditional) - Big5 Code" }, { KBD_CHINESE_TRADITIONAL_ARRAY, "winar30.ime", "Chinese (Traditional) - Array" }, { KBD_CHINESE_SIMPLIFIED_NEIMA, "wingb.ime", "Chinese (Simplified) - NeiMa" }, { KBD_CHINESE_TRADITIONAL_DAYI, "dayi.ime", "Chinese (Traditional) - DaYi" }, { KBD_CHINESE_TRADITIONAL_UNICODE, "unicdime.ime", "Chinese (Traditional) - Unicode" }, { KBD_CHINESE_TRADITIONAL_NEW_PHONETIC, "TINTLGNT.IME", "Chinese (Traditional) - New Phonetic" }, { KBD_CHINESE_TRADITIONAL_NEW_CHANGJIE, "CINTLGNT.IME", "Chinese (Traditional) - New ChangJie" }, { KBD_CHINESE_TRADITIONAL_MICROSOFT_PINYIN_IME_3, "pintlgnt.ime", "Chinese (Traditional) - Microsoft Pinyin IME 3.0" }, { KBD_CHINESE_TRADITIONAL_ALPHANUMERIC, "romanime.ime", "Chinese (Traditional) - Alphanumeric" } }; rdpKeyboardLayout* get_keyboard_layouts(int types) { int num, len, i; rdpKeyboardLayout * layouts; num = 0; layouts = (rdpKeyboardLayout *) malloc((num + 1) * sizeof(rdpKeyboardLayout)); if ((types & RDP_KEYBOARD_LAYOUT_TYPE_STANDARD) != 0) { len = sizeof(keyboardLayouts) / sizeof(keyboardLayout); layouts = (rdpKeyboardLayout *) realloc(layouts, (num + len + 1) * sizeof(rdpKeyboardLayout)); for (i = 0; i < len; i++, num++) { layouts[num].code = keyboardLayouts[i].code; strcpy(layouts[num].name, keyboardLayouts[i].name); } } if ((types & RDP_KEYBOARD_LAYOUT_TYPE_VARIANT) != 0) { len = sizeof(keyboardLayoutVariants) / sizeof(keyboardLayoutVariant); layouts = (rdpKeyboardLayout *) realloc(layouts, (num + len + 1) * sizeof(rdpKeyboardLayout)); for (i = 0; i < len; i++, num++) { layouts[num].code = keyboardLayoutVariants[i].code; strcpy(layouts[num].name, keyboardLayoutVariants[i].name); } } if ((types & RDP_KEYBOARD_LAYOUT_TYPE_IME) != 0) { len = sizeof(keyboardIMEs) / sizeof(keyboardIME); layouts = (rdpKeyboardLayout *) realloc(layouts, (num + len + 1) * sizeof(rdpKeyboardLayout)); for (i = 0; i < len; i++, num++) { layouts[num].code = keyboardIMEs[i].code; strcpy(layouts[num].name, keyboardIMEs[i].name); } } memset(&layouts[num], 0, sizeof(rdpKeyboardLayout)); return layouts; } const char* get_layout_name(unsigned int keyboardLayoutID) { int i; for (i = 0; i < sizeof(keyboardLayouts) / sizeof(keyboardLayout); i++) { if (keyboardLayouts[i].code == keyboardLayoutID) return keyboardLayouts[i].name; } for (i = 0; i < sizeof(keyboardLayoutVariants) / sizeof(keyboardLayoutVariant); i++) { if (keyboardLayoutVariants[i].code == keyboardLayoutID) return keyboardLayoutVariants[i].name; } for (i = 0; i < sizeof(keyboardIMEs) / sizeof(keyboardIME); i++) { if (keyboardIMEs[i].code == keyboardLayoutID) return keyboardIMEs[i].name; } return "unknown"; } FreeRDP-1.0.2/libfreerdp-kbd/layouts_xkb.c000066400000000000000000000266251207112532300203340ustar00rootroot00000000000000/** * FreeRDP: A Remote Desktop Protocol Client * XKB-based Keyboard Mapping to Microsoft Keyboard System * * Copyright 2009 Marc-Andre Moreau * * 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. */ #include #include #include #ifdef WITH_XKBFILE #include #include #include #include #endif #include "libkbd.h" #include #include "x_layout_id_table.h" #include "layouts_xkb.h" #ifndef KEYMAP_PATH #define KEYMAP_PATH "/usr/local/freerdp/keymaps" #endif #ifdef WITH_XKBFILE int init_xkb(void* dpy) { return XkbQueryExtension(dpy, NULL, NULL, NULL, NULL, NULL); } /* return substring starting after nth comma, ending at following comma */ static char* comma_substring(char* s, int n) { char *p; if (!s) return ""; while (n-- > 0) { if (!(p = strchr(s, ','))) break; s = p + 1; } if ((p = strchr(s, ','))) *p = 0; return s; } unsigned int detect_keyboard_layout_from_xkb(void* dpy) { char *layout, *variant; unsigned int keyboard_layout = 0, group = 0; XkbRF_VarDefsRec rules_names; XKeyboardState coreKbdState; XkbStateRec state; DEBUG_KBD("display: %p", dpy); if (dpy && XkbRF_GetNamesProp(dpy, NULL, &rules_names)) { DEBUG_KBD("layouts: %s", rules_names.layout ? rules_names.layout : ""); DEBUG_KBD("variants: %s", rules_names.variant ? rules_names.variant : ""); XGetKeyboardControl(dpy, &coreKbdState); if (XkbGetState(dpy, XkbUseCoreKbd, &state) == Success) group = state.group; DEBUG_KBD("group: %d", state.group); layout = comma_substring(rules_names.layout, group); variant = comma_substring(rules_names.variant, group); DEBUG_KBD("layout: %s", layout ? layout : ""); DEBUG_KBD("variant: %s", variant ? variant : ""); keyboard_layout = find_keyboard_layout_in_xorg_rules(layout, variant); free(rules_names.model); free(rules_names.layout); free(rules_names.variant); free(rules_names.options); } return keyboard_layout; } int init_keycodes_from_xkb(void* dpy, RdpScancodes x_keycode_to_rdp_scancode, uint8 rdp_scancode_to_x_keycode[256][2]) { int ret = 0; XkbDescPtr xkb; if (dpy && (xkb = XkbGetMap(dpy, 0, XkbUseCoreKbd))) { if (XkbGetNames(dpy, XkbKeyNamesMask, xkb) == Success) { int i, j; char buf[5] = {42, 42, 42, 42, 0}; /* end-of-string at pos 5 */ for (i = xkb->min_key_code; i <= xkb->max_key_code; i++) { memcpy(buf, xkb->names->keys[i].name, 4); /* TODO: Use more efficient search ... but it is so fast that it doesn't matter */ j = sizeof(virtualKeyboard) / sizeof(virtualKeyboard[0]) - 1; while (j >= 0) { if (virtualKeyboard[j].x_keyname && !strcmp(buf, virtualKeyboard[j].x_keyname)) break; j--; } if (j >= 0) { DEBUG_KBD("X keycode %3d has keyname %-4s -> RDP scancode %d/%d", i, buf, virtualKeyboard[j].extended, virtualKeyboard[j].scancode); x_keycode_to_rdp_scancode[i].extended = virtualKeyboard[j].extended; x_keycode_to_rdp_scancode[i].keycode = virtualKeyboard[j].scancode; x_keycode_to_rdp_scancode[i].keyname = virtualKeyboard[j].x_keyname; if (x_keycode_to_rdp_scancode[i].extended) rdp_scancode_to_x_keycode[virtualKeyboard[j].scancode][1] = i; else rdp_scancode_to_x_keycode[virtualKeyboard[j].scancode][0] = i; } else { DEBUG_KBD("X key code %3d has keyname %-4s -> ??? - not found", i, buf); } } ret = 1; } XkbFreeKeyboard(xkb, 0, 1); } return ret; } #else /* Default built-in keymap */ static const KeycodeToVkcode defaultKeycodeToVkcode = { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x1B, 0x31, 0x32, 0x33, 0x34, 0x35, 0x36, 0x37, 0x38, 0x39, 0x30, 0xBD, 0xBB, 0x08, 0x09, 0x51, 0x57, 0x45, 0x52, 0x54, 0x59, 0x55, 0x49, 0x4F, 0x50, 0xDB, 0xDD, 0x0D, 0xA2, 0x41, 0x53, 0x44, 0x46, 0x47, 0x48, 0x4A, 0x4B, 0x4C, 0xBA, 0xDE, 0xC0, 0xA0, 0x00, 0x5A, 0x58, 0x43, 0x56, 0x42, 0x4E, 0x4D, 0xBC, 0xBE, 0xBF, 0xA1, 0x6A, 0x12, 0x20, 0x14, 0x70, 0x71, 0x72, 0x73, 0x74, 0x75, 0x76, 0x77, 0x78, 0x79, 0x90, 0x91, 0x67, 0x68, 0x69, 0x6D, 0x64, 0x65, 0x66, 0x6B, 0x61, 0x62, 0x63, 0x60, 0x6E, 0x00, 0x00, 0x00, 0x7A, 0x7B, 0x24, 0x26, 0x21, 0x25, 0x00, 0x27, 0x23, 0x28, 0x22, 0x2D, 0x2E, 0x0D, 0xA3, 0x13, 0x2C, 0x6F, 0x12, 0x00, 0x5B, 0x5C, 0x5D, 0x7C, 0x7D, 0x7E, 0x7F, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xA1, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }; static int load_xkb_keyboard(KeycodeToVkcode map, char* kbd) { char* pch; char *beg, *end; char* home; char buffer[1024] = ""; char xkbfile[256] = ""; char xkbfilepath[512] = ""; char xkbmap[256] = ""; char xkbinc[256] = ""; FILE* fp; int kbdFound = 0; int i = 0; int keycode = 0; char keycodeString[32] = ""; char vkcodeName[128] = ""; beg = kbd; /* Extract file name and keymap name */ if ((end = strrchr(kbd, '(')) != NULL) { strncpy(xkbfile, &kbd[beg - kbd], end - beg); beg = end + 1; if ((end = strrchr(kbd, ')')) != NULL) { strncpy(xkbmap, &kbd[beg - kbd], end - beg); xkbmap[end - beg] = '\0'; } } else { /* The keyboard name is the same as the file name */ strcpy(xkbfile, kbd); strcpy(xkbmap, kbd); } /* Get path to file relative to freerdp's directory */ snprintf(xkbfilepath, sizeof(xkbfilepath), "keymaps/%s", xkbfile); DEBUG_KBD("Loading keymap %s, first trying %s", kbd, xkbfilepath); /* * Open the file for reading only * It can happen that the same file is opened twice at the same time * in order to load multiple keyboard maps from the same file, but * it does not matter: files can be opened as many times as we want * when it is for reading only. */ if ((fp = fopen(xkbfilepath, "r")) == NULL) { /* Look first in path given at compile time (install path) */ snprintf(xkbfilepath, sizeof(xkbfilepath), "%s/%s", KEYMAP_PATH, xkbfile); if ((fp = fopen(xkbfilepath, "r")) == NULL) { /* If ran from the root of the source tree */ snprintf(xkbfilepath, sizeof(xkbfilepath), "./keymaps/%s", xkbfile); /* If ran from the client directory */ if((fp = fopen(xkbfilepath, "r")) == NULL) snprintf(xkbfilepath, sizeof(xkbfilepath), "../../keymaps/%s", xkbfile); if ((fp = fopen(xkbfilepath, "r")) == NULL) { /* File wasn't found in the source tree, try ~/.freerdp/ folder */ if ((home = getenv("HOME")) == NULL) return 0; /* Get path to file in ~/.freerdp/ folder */ snprintf(xkbfilepath, sizeof(xkbfilepath), "%s/.freerdp/keymaps/%s", home, xkbfile); if ((fp = fopen(xkbfilepath, "r")) == NULL) { /* Try /usr/share/freerdp folder */ snprintf(xkbfilepath, sizeof(xkbfilepath), "/usr/share/freerdp/keymaps/%s", xkbfile); if ((fp = fopen(xkbfilepath, "r")) == NULL) { /* Try /usr/local/share/freerdp folder */ snprintf(xkbfilepath, sizeof(xkbfilepath), "/usr/local/share/freerdp/keymaps/%s", xkbfile); if ((fp = fopen(xkbfilepath, "r")) == NULL) { /* Error: Could not find keymap */ DEBUG_KBD("keymaps for %s not found", xkbfile); return 0; } } } } } } DEBUG_KBD("xkbfilepath: %s", xkbfilepath); while(fgets(buffer, sizeof(buffer), fp) != NULL) { if (buffer[0] == '#') { continue; /* Skip comments */ } if (kbdFound) { /* Closing curly bracket and semicolon */ if ((pch = strstr(buffer, "};")) != NULL) { break; } else if ((pch = strstr(buffer, "VK_")) != NULL) { /* The end is delimited by the first white space */ end = strcspn(pch, " \t\n\0") + pch; /* We copy the virtual key code name in a string */ beg = pch; strncpy(vkcodeName, beg, end - beg); vkcodeName[end - beg] = '\0'; /* Now we want to extract the virtual key code itself which is in between '<' and '>' */ if ((beg = strchr(pch + 3, '<')) == NULL) break; else beg++; if ((end = strchr(beg, '>')) == NULL) break; /* We copy the string representing the number in a string */ strncpy(keycodeString, beg, end - beg); keycodeString[end - beg] = '\0'; /* Convert the string representing the code to an integer */ keycode = atoi(keycodeString); /* Make sure it is a valid keycode */ if (keycode < 0 || keycode > 255) break; /* Load this key mapping in the keyboard mapping */ for(i = 0; i < sizeof(virtualKeyboard) / sizeof(virtualKey); i++) { if (strcmp(vkcodeName, virtualKeyboard[i].name) == 0) { map[keycode] = i; } } } else if ((pch = strstr(buffer, ": extends")) != NULL) { /* * This map extends another keymap We extract its name * and we recursively load the keymap we need to include. */ if ((beg = strchr(pch + sizeof(": extends"), '"')) == NULL) break; beg++; if ((end = strchr(beg, '"')) == NULL) break; strncpy(xkbinc, beg, end - beg); xkbinc[end - beg] = '\0'; load_xkb_keyboard(map, xkbinc); /* Load included keymap */ } } else if ((pch = strstr(buffer, "keyboard")) != NULL) { /* Keyboard map identifier */ if ((beg = strchr(pch + sizeof("keyboard"), '"')) == NULL) break; beg++; if ((end = strchr(beg, '"')) == NULL) break; pch = beg; buffer[end - beg] = '\0'; /* Does it match our keymap name? */ if (strncmp(xkbmap, pch, strlen(xkbmap)) == 0) kbdFound = 1; } } fclose(fp); /* Don't forget to close file */ return 1; } void load_keyboard_map(KeycodeToVkcode keycodeToVkcode, char *xkbfile) { char* kbd; char* xkbfileEnd; int keymapLoaded = 0; memset(keycodeToVkcode, 0, sizeof(keycodeToVkcode)); kbd = xkbfile; xkbfileEnd = xkbfile + strlen(xkbfile); #ifdef __APPLE__ /* Apple X11 breaks XKB detection */ keymapLoaded += load_xkb_keyboard(keycodeToVkcode, "macosx(macosx)"); #else do { /* Multiple maps are separated by '+' */ int kbdlen = strcspn(kbd + 1, "+") + 1; kbd[kbdlen] = '\0'; /* Load keyboard map */ keymapLoaded += load_xkb_keyboard(keycodeToVkcode, kbd); kbd += kbdlen + 1; } while (kbd < xkbfileEnd); #endif DEBUG_KBD("loaded %d keymaps", keymapLoaded); if (keymapLoaded <= 0) { /* No keymap was loaded, load default hard-coded keymap */ DEBUG_KBD("using default keymap"); memcpy(keycodeToVkcode, defaultKeycodeToVkcode, sizeof(keycodeToVkcode)); } } #endif FreeRDP-1.0.2/libfreerdp-kbd/layouts_xkb.h000066400000000000000000000023671207112532300203360ustar00rootroot00000000000000/** * FreeRDP: A Remote Desktop Protocol Client * XKB-based Keyboard Mapping to Microsoft Keyboard System * * Copyright 2009 Marc-Andre Moreau * * 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. */ #ifndef __LAYOUTS_XKB_H #define __LAYOUTS_XKB_H typedef unsigned char KeycodeToVkcode[256]; typedef struct { unsigned char extended; unsigned char keycode; char* keyname; } RdpKeycodeRec, RdpScancodes[256]; #ifdef WITH_XKBFILE int init_xkb(void *dpy); unsigned int detect_keyboard_layout_from_xkb(void *dpy); int init_keycodes_from_xkb(void* dpy, RdpScancodes x_keycode_to_rdp_scancode, uint8 rdp_scancode_to_x_keycode[256][2]); #else void load_keyboard_map(KeycodeToVkcode keycodeToVkcode, char *xkbfile); #endif #endif FreeRDP-1.0.2/libfreerdp-kbd/libkbd.c000066400000000000000000000116731207112532300172140ustar00rootroot00000000000000/** * FreeRDP: A Remote Desktop Protocol Client * XKB-based Keyboard Mapping to Microsoft Keyboard System * * Copyright 2009 Marc-Andre Moreau * * 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. */ #include #include #include #include #include #include "libkbd.h" #include #include #include #include "layouts_xkb.h" /* * The actual mapping from X keycodes to RDP keycodes, initialized from xkb keycodes or similar. * Used directly by freerdp_kbd_get_scancode_by_keycode. The mapping is a global variable, * but it only depends on which keycodes the X servers keyboard driver uses and is thus very static. */ RdpScancodes x_keycode_to_rdp_scancode; uint8 rdp_scancode_to_x_keycode[256][2]; #ifndef WITH_XKBFILE static unsigned int detect_keyboard(void* dpy, unsigned int keyboardLayoutID, char* xkbfile, size_t xkbfilelength) { xkbfile[0] = '\0'; if (keyboardLayoutID != 0) DEBUG_KBD("keyboard layout configuration: %X", keyboardLayoutID); #if defined(sun) if (keyboardLayoutID == 0) { keyboardLayoutID = detect_keyboard_type_and_layout_sunos(xkbfile, xkbfilelength); DEBUG_KBD("detect_keyboard_type_and_layout_sunos: %X %s", keyboardLayoutID, xkbfile); } #endif if (keyboardLayoutID == 0) { keyboardLayoutID = detect_keyboard_layout_from_locale(); DEBUG_KBD("detect_keyboard_layout_from_locale: %X", keyboardLayoutID); } if (keyboardLayoutID == 0) { keyboardLayoutID = 0x0409; DEBUG_KBD("using default keyboard layout: %X", keyboardLayoutID); } if (xkbfile[0] == '\0') { strncpy(xkbfile, "base", xkbfilelength); DEBUG_KBD("using default keyboard layout: %s", xkbfile); } return keyboardLayoutID; } #endif /* * Initialize global keyboard mapping and return the suggested server side layout. * dpy must be a X Display* or NULL. */ unsigned int freerdp_kbd_init(void* dpy, unsigned int keyboard_layout_id) { memset(x_keycode_to_rdp_scancode, 0, sizeof(x_keycode_to_rdp_scancode)); memset(rdp_scancode_to_x_keycode, '\0', sizeof(rdp_scancode_to_x_keycode)); #ifdef WITH_XKBFILE if (!init_xkb(dpy)) { DEBUG_KBD("Error initializing xkb"); return 0; } if (keyboard_layout_id == 0) { keyboard_layout_id = detect_keyboard_layout_from_xkb(dpy); DEBUG_KBD("detect_keyboard_layout_from_xkb: %X", keyboard_layout_id); } init_keycodes_from_xkb(dpy, x_keycode_to_rdp_scancode, rdp_scancode_to_x_keycode); #else int vkcode; int keycode; char xkbfile[256]; KeycodeToVkcode keycodeToVkcode; if (keyboard_layout_id == 0) keyboard_layout_id = detect_keyboard(dpy, keyboard_layout_id, xkbfile, sizeof(xkbfile)); DEBUG_KBD("Using keyboard layout 0x%X with xkb name %s and xkbfile %s", keyboard_layout_id, get_layout_name(keyboard_layout_id), xkbfile); load_keyboard_map(keycodeToVkcode, xkbfile); for (keycode = 0; keycode < 256; keycode++) { vkcode = keycodeToVkcode[keycode]; DEBUG_KBD("X keycode %3d VK %3d %-19s-> RDP scancode %d/%d", keycode, vkcode, virtualKeyboard[vkcode].name, virtualKeyboard[vkcode].extended, virtualKeyboard[vkcode].scancode); x_keycode_to_rdp_scancode[keycode].keycode = virtualKeyboard[vkcode].scancode; x_keycode_to_rdp_scancode[keycode].extended = virtualKeyboard[vkcode].extended; x_keycode_to_rdp_scancode[keycode].keyname = virtualKeyboard[vkcode].name; if (x_keycode_to_rdp_scancode[keycode].extended) rdp_scancode_to_x_keycode[virtualKeyboard[vkcode].scancode][1] = keycode; else rdp_scancode_to_x_keycode[virtualKeyboard[vkcode].scancode][0] = keycode; } #endif return keyboard_layout_id; } rdpKeyboardLayout* freerdp_kbd_get_layouts(int types) { return get_keyboard_layouts(types); } uint8 freerdp_kbd_get_scancode_by_keycode(uint8 keycode, boolean* extended) { DEBUG_KBD("%2x %4s -> %d/%d", keycode, x_keycode_to_rdp_scancode[keycode].keyname, x_keycode_to_rdp_scancode[keycode].extended, x_keycode_to_rdp_scancode[keycode].keycode); *extended = x_keycode_to_rdp_scancode[keycode].extended; return x_keycode_to_rdp_scancode[keycode].keycode; } uint8 freerdp_kbd_get_keycode_by_scancode(uint8 scancode, boolean extended) { if (extended) return rdp_scancode_to_x_keycode[scancode][1]; else return rdp_scancode_to_x_keycode[scancode][0]; } uint8 freerdp_kbd_get_scancode_by_virtualkey(int vkcode, boolean* extended) { *extended = virtualKeyboard[vkcode].extended; return virtualKeyboard[vkcode].scancode; } FreeRDP-1.0.2/libfreerdp-kbd/libkbd.h000066400000000000000000000017461207112532300172210ustar00rootroot00000000000000/** * FreeRDP: A Remote Desktop Protocol Client * XKB-based Keyboard Mapping to Microsoft Keyboard System * * Copyright 2009 Marc-Andre Moreau * * 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. */ #ifndef __LIBKBD_H #define __LIBKBD_H #include #ifdef WITH_DEBUG_KBD #define DEBUG_KBD(fmt, ...) DEBUG_CLASS(KBD, fmt, ## __VA_ARGS__) #else #define DEBUG_KBD(fmt, ...) DEBUG_NULL(fmt, ## __VA_ARGS__) #endif #endif /* __LIBKBD_H */ FreeRDP-1.0.2/libfreerdp-kbd/locales.c000066400000000000000000000667621207112532300174200ustar00rootroot00000000000000/** * FreeRDP: A Remote Desktop Protocol Client * XKB-based Keyboard Mapping to Microsoft Keyboard System * * Copyright 2009 Marc-Andre Moreau * * 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. */ #include #include #include #include "libkbd.h" #include typedef struct { /* Two or three letter language code */ char language[4]; /* Two or three letter country code (Sometimes with Cyrl_ prefix) */ char country[10]; /* 32-bit unsigned integer corresponding to the locale */ unsigned int code; } locale; /* * Refer to MSDN article "Locale Identifier Constants and Strings": * http://msdn.microsoft.com/en-us/library/ms776260.aspx */ static const locale locales[] = { { "af", "ZA", AFRIKAANS }, /* Afrikaans (South Africa) */ { "sq", "AL", ALBANIAN }, /* Albanian (Albania) */ { "gsw", "FR", ALSATIAN }, /* Windows Vista and later: Alsatian (France) */ { "am", "ET", AMHARIC }, /* Windows Vista and later: Amharic (Ethiopia) */ { "ar", "DZ", ARABIC_ALGERIA }, /* Arabic (Algeria) */ { "ar", "BH", ARABIC_BAHRAIN }, /* Arabic (Bahrain) */ { "ar", "EG", ARABIC_EGYPT }, /* Arabic (Egypt) */ { "ar", "IQ", ARABIC_IRAQ }, /* Arabic (Iraq) */ { "ar", "JO", ARABIC_JORDAN }, /* Arabic (Jordan) */ { "ar", "KW", ARABIC_KUWAIT }, /* Arabic (Kuwait) */ { "ar", "LB", ARABIC_LEBANON }, /* Arabic (Lebanon) */ { "ar", "LY", ARABIC_LIBYA }, /* Arabic (Libya) */ { "ar", "MA", ARABIC_MOROCCO }, /* Arabic (Morocco) */ { "ar", "OM", ARABIC_OMAN }, /* Arabic (Oman) */ { "ar", "QA", ARABIC_QATAR }, /* Arabic (Qatar) */ { "ar", "SA", ARABIC_SAUDI_ARABIA }, /* Arabic (Saudi Arabia) */ { "ar", "SY", ARABIC_SYRIA }, /* Arabic (Syria) */ { "ar", "TN", ARABIC_TUNISIA }, /* Arabic (Tunisia) */ { "ar", "AE", ARABIC_UAE }, /* Arabic (U.A.E.) */ { "ar", "YE", ARABIC_YEMEN }, /* Arabic (Yemen) */ { "az", "AZ", AZERI_LATIN }, /* Azeri (Latin) */ { "az", "Cyrl_AZ", AZERI_CYRILLIC }, /* Azeri (Cyrillic) */ { "hy", "AM", ARMENIAN }, /* Windows 2000 and later: Armenian (Armenia) */ { "as", "IN", ASSAMESE }, /* Windows Vista and later: Assamese (India) */ { "ba", "RU", BASHKIR }, /* Windows Vista and later: Bashkir (Russia) */ { "eu", "ES", BASQUE }, /* Basque (Basque) */ { "be", "BY", BELARUSIAN }, /* Belarusian (Belarus) */ { "bn", "IN", BENGALI_INDIA }, /* Windows XP SP2 and later: Bengali (India) */ { "br", "FR", BRETON }, /* Breton (France) */ { "bs", "BA", BOSNIAN_LATIN }, /* Bosnian (Latin) */ { "bg", "BG", BULGARIAN }, /* Bulgarian (Bulgaria) */ { "ca", "ES", CATALAN }, /* Catalan (Catalan) */ { "zh", "HK", CHINESE_HONG_KONG }, /* Chinese (Hong Kong SAR, PRC) */ { "zh", "MO", CHINESE_MACAU }, /* Windows 98/Me, Windows XP and later: Chinese (Macao SAR) */ { "zh", "CN", CHINESE_PRC }, /* Chinese (PRC) */ { "zh", "SG", CHINESE_SINGAPORE }, /* Chinese (Singapore) */ { "zh", "TW", CHINESE_TAIWAN }, /* Chinese (Taiwan) */ { "hr", "BA", CROATIAN_BOSNIA_HERZEGOVINA }, /* Windows XP SP2 and later: Croatian (Bosnia and Herzegovina, Latin) */ { "hr", "HR", CROATIAN }, /* Croatian (Croatia) */ { "cs", "CZ", CZECH }, /* Czech (Czech Republic) */ { "da", "DK", DANISH }, /* Danish (Denmark) */ { "prs", "AF", DARI }, /* Windows XP and later: Dari (Afghanistan) */ { "dv", "MV", DIVEHI }, /* Windows XP and later: Divehi (Maldives) */ { "nl", "BE", DUTCH_BELGIAN }, /* Dutch (Belgium) */ { "nl", "NL", DUTCH_STANDARD }, /* Dutch (Netherlands) */ { "en", "AU", ENGLISH_AUSTRALIAN }, /* English (Australia) */ { "en", "BZ", ENGLISH_BELIZE }, /* English (Belize) */ { "en", "CA", ENGLISH_CANADIAN }, /* English (Canada) */ { "en", "CB", ENGLISH_CARIBBEAN }, /* English (Carribean) */ { "en", "IN", ENGLISH_INDIA }, /* Windows Vista and later: English (India) */ { "en", "IE", ENGLISH_IRELAND }, /* English (Ireland) */ { "en", "JM", ENGLISH_JAMAICA }, /* English (Jamaica) */ { "en", "MY", ENGLISH_MALAYSIA }, /* Windows Vista and later: English (Malaysia) */ { "en", "NZ", ENGLISH_NEW_ZEALAND }, /* English (New Zealand) */ { "en", "PH", ENGLISH_PHILIPPINES }, /* Windows 98/Me, Windows 2000 and later: English (Philippines) */ { "en", "SG", ENGLISH_SINGAPORE }, /* Windows Vista and later: English (Singapore) */ { "en", "ZA", ENGLISH_SOUTH_AFRICA }, /* English (South Africa) */ { "en", "TT", ENGLISH_TRINIDAD }, /* English (Trinidad and Tobago) */ { "en", "GB", ENGLISH_UNITED_KINGDOM }, /* English (United Kingdom) */ { "en", "US", ENGLISH_UNITED_STATES }, /* English (United States) */ { "en", "ZW", ENGLISH_ZIMBABWE }, /* Windows 98/Me, Windows 2000 and later: English (Zimbabwe) */ { "et", "EE", ESTONIAN }, /* Estonian (Estonia) */ { "fo", "FO", FAEROESE }, /* Faroese (Faroe Islands) */ { "fil", "PH", FILIPINO }, /* Windows XP SP2 and later (downloadable); Windows Vista and later: Filipino (Philippines) */ { "fi", "FI", FINNISH }, /* Finnish (Finland) */ { "fr", "BE", FRENCH_BELGIAN }, /* French (Belgium) */ { "fr", "CA", FRENCH_CANADIAN }, /* French (Canada) */ { "fr", "FR", FRENCH_STANDARD }, /* French (France) */ { "fr", "LU", FRENCH_LUXEMBOURG }, /* French (Luxembourg) */ { "fr", "MC", FRENCH_MONACO }, /* French (Monaco) */ { "fr", "CH", FRENCH_SWISS }, /* French (Switzerland) */ { "fy", "NL", FRISIAN }, /* Windows XP SP2 and later (downloadable); Windows Vista and later: Frisian (Netherlands) */ { "gl", "ES", GALICIAN }, /* Windows XP and later: Galician (Spain) */ { "ka", "GE", GEORGIAN }, /* Windows 2000 and later: Georgian (Georgia) */ { "de", "AT", GERMAN_AUSTRIAN }, /* German (Austria) */ { "de", "DE", GERMAN_STANDARD }, /* German (Germany) */ { "de", "LI", GERMAN_LIECHTENSTEIN }, /* German (Liechtenstein) */ { "de", "LU", GERMAN_LUXEMBOURG }, /* German (Luxembourg) */ { "de", "CH", GERMAN_SWISS }, /* German (Switzerland) */ { "el", "GR", GREEK }, /* Greek (Greece) */ { "kl", "GL", GREENLANDIC }, /* Windows Vista and later: Greenlandic (Greenland) */ { "gu", "IN", GUJARATI }, /* Windows XP and later: Gujarati (India) */ { "he", "IL", HEBREW }, /* Hebrew (Israel) */ { "hi", "IN", HINDI }, /* Windows 2000 and later: Hindi (India) */ { "hu", "HU", HUNGARIAN }, /* Hungarian (Hungary) */ { "is", "IS", ICELANDIC }, /* Icelandic (Iceland) */ { "ig", "NG", IGBO }, /* Igbo (Nigeria) */ { "id", "ID", INDONESIAN }, /* Indonesian (Indonesia) */ { "ga", "IE", IRISH }, /* Windows XP SP2 and later (downloadable); Windows Vista and later: Irish (Ireland) */ { "it", "IT", ITALIAN_STANDARD }, /* Italian (Italy) */ { "it", "CH", ITALIAN_SWISS }, /* Italian (Switzerland) */ { "ja", "JP", JAPANESE }, /* Japanese (Japan) */ { "kn", "IN", KANNADA }, /* Windows XP and later: Kannada (India) */ { "kk", "KZ", KAZAKH }, /* Windows 2000 and later: Kazakh (Kazakhstan) */ { "kh", "KH", KHMER }, /* Windows Vista and later: Khmer (Cambodia) */ { "qut", "GT", KICHE }, /* Windows Vista and later: K'iche (Guatemala) */ { "rw", "RW", KINYARWANDA }, /* Windows Vista and later: Kinyarwanda (Rwanda) */ { "kok", "IN", KONKANI }, /* Windows 2000 and later: Konkani (India) */ { "ko", "KR", KOREAN }, /* Korean (Korea) */ { "ky", "KG", KYRGYZ }, /* Windows XP and later: Kyrgyz (Kyrgyzstan) */ { "lo", "LA", LAO }, /* Windows Vista and later: Lao (Lao PDR) */ { "lv", "LV", LATVIAN }, /* Latvian (Latvia) */ { "lt", "LT", LITHUANIAN }, /* Lithuanian (Lithuania) */ { "dsb", "DE", LOWER_SORBIAN }, /* Windows Vista and later: Lower Sorbian (Germany) */ { "lb", "LU", LUXEMBOURGISH }, /* Windows XP SP2 and later (downloadable); Windows Vista and later: Luxembourgish (Luxembourg) */ { "mk", "MK", MACEDONIAN }, /* Windows 2000 and later: Macedonian (Macedonia, FYROM) */ { "ms", "BN", MALAY_BRUNEI_DARUSSALAM }, /* Windows 2000 and later: Malay (Brunei Darussalam) */ { "ms", "MY", MALAY_MALAYSIA }, /* Windows 2000 and later: Malay (Malaysia) */ { "ml", "IN", MALAYALAM }, /* Windows XP SP2 and later: Malayalam (India) */ { "mt", "MT", MALTESE }, /* Windows XP SP2 and later: Maltese (Malta) */ { "mi", "NZ", MAORI }, /* Windows XP SP2 and later: Maori (New Zealand) */ { "arn", "CL", MAPUDUNGUN }, /* Windows XP SP2 and later (downloadable); Windows Vista and later: Mapudungun (Chile) */ { "mr", "IN", MARATHI }, /* Windows 2000 and later: Marathi (India) */ { "moh", "CA", MOHAWK }, /* Windows XP SP2 and later (downloadable); Windows Vista and later: Mohawk (Canada) */ { "mn", "MN", MONGOLIAN }, /* Mongolian */ { "ne", "NP", NEPALI }, /* Windows XP SP2 and later (downloadable); Windows Vista and later: Nepali (Nepal) */ { "nb", "NO", NORWEGIAN_BOKMAL }, /* Norwegian (Bokmal, Norway) */ { "nn", "NO", NORWEGIAN_NYNORSK }, /* Norwegian (Nynorsk, Norway) */ { "oc", "FR", OCCITAN }, /* Occitan (France) */ { "or", "IN", ORIYA }, /* Oriya (India) */ { "ps", "AF", PASHTO }, /* Windows XP SP2 and later (downloadable); Windows Vista and later: Pashto (Afghanistan) */ { "fa", "IR", FARSI }, /* Persian (Iran) */ { "pl", "PL", POLISH }, /* Polish (Poland) */ { "pt", "BR", PORTUGUESE_BRAZILIAN }, /* Portuguese (Brazil) */ { "pt", "PT", PORTUGUESE_STANDARD }, /* Portuguese (Portugal) */ { "pa", "IN", PUNJABI }, /* Windows XP and later: Punjabi (India) */ { "quz", "BO", QUECHUA_BOLIVIA }, /* Windows XP SP2 and later: Quechua (Bolivia) */ { "quz", "EC", QUECHUA_ECUADOR }, /* Windows XP SP2 and later: Quechua (Ecuador) */ { "quz", "PE", QUECHUA_PERU }, /* Windows XP SP2 and later: Quechua (Peru) */ { "ro", "RO", ROMANIAN }, /* Romanian (Romania) */ { "rm", "CH", ROMANSH }, /* Windows XP SP2 and later (downloadable); Windows Vista and later: Romansh (Switzerland) */ { "ru", "RU", RUSSIAN }, /* Russian (Russia) */ { "smn", "FI", SAMI_INARI }, /* Windows XP SP2 and later: Sami (Inari, Finland) */ { "smj", "NO", SAMI_LULE_NORWAY }, /* Windows XP SP2 and later: Sami (Lule, Norway) */ { "smj", "SE", SAMI_LULE_SWEDEN }, /* Windows XP SP2 and later: Sami (Lule, Sweden) */ { "se", "FI", SAMI_NORTHERN_FINLAND }, /* Windows XP SP2 and later: Sami (Northern, Finland) */ { "se", "NO", SAMI_NORTHERN_NORWAY }, /* Windows XP SP2 and later: Sami (Northern, Norway) */ { "se", "SE", SAMI_NORTHERN_SWEDEN }, /* Windows XP SP2 and later: Sami (Northern, Sweden) */ { "sms", "FI", SAMI_SKOLT }, /* Windows XP SP2 and later: Sami (Skolt, Finland) */ { "sma", "NO", SAMI_SOUTHERN_NORWAY }, /* Windows XP SP2 and later: Sami (Southern, Norway) */ { "sma", "SE", SAMI_SOUTHERN_SWEDEN }, /* Windows XP SP2 and later: Sami (Southern, Sweden) */ { "sa", "IN", SANSKRIT }, /* Windows 2000 and later: Sanskrit (India) */ { "sr", "SP", SERBIAN_LATIN }, /* Serbian (Latin) */ { "sr", "SIH", SERBIAN_LATIN_BOSNIA_HERZEGOVINA }, /* Serbian (Latin) (Bosnia and Herzegovina) */ { "sr", "Cyrl_SP", SERBIAN_CYRILLIC }, /* Serbian (Cyrillic) */ { "sr", "Cyrl_SIH", SERBIAN_CYRILLIC_BOSNIA_HERZEGOVINA }, /* Serbian (Cyrillic) (Bosnia and Herzegovina) */ { "ns", "ZA", SESOTHO_SA_LEBOA }, /* Windows XP SP2 and later: Sesotho sa Leboa/Northern Sotho (South Africa) */ { "tn", "ZA", TSWANA }, /* Windows XP SP2 and later: Setswana/Tswana (South Africa) */ { "si", "LK", SINHALA }, /* Windows Vista and later: Sinhala (Sri Lanka) */ { "sk", "SK", SLOVAK }, /* Slovak (Slovakia) */ { "sl", "SI", SLOVENIAN }, /* Slovenian (Slovenia) */ { "es", "AR", SPANISH_ARGENTINA }, /* Spanish (Argentina) */ { "es", "BO", SPANISH_BOLIVIA }, /* Spanish (Bolivia) */ { "es", "CL", SPANISH_CHILE }, /* Spanish (Chile) */ { "es", "CO", SPANISH_COLOMBIA }, /* Spanish (Colombia) */ { "es", "CR", SPANISH_COSTA_RICA }, /* Spanish (Costa Rica) */ { "es", "DO", SPANISH_DOMINICAN_REPUBLIC }, /* Spanish (Dominican Republic) */ { "es", "EC", SPANISH_ECUADOR }, /* Spanish (Ecuador) */ { "es", "SV", SPANISH_EL_SALVADOR }, /* Spanish (El Salvador) */ { "es", "GT", SPANISH_GUATEMALA }, /* Spanish (Guatemala) */ { "es", "HN", SPANISH_HONDURAS }, /* Spanish (Honduras) */ { "es", "MX", SPANISH_MEXICAN }, /* Spanish (Mexico) */ { "es", "NI", SPANISH_NICARAGUA }, /* Spanish (Nicaragua) */ { "es", "PA", SPANISH_PANAMA }, /* Spanish (Panama) */ { "es", "PY", SPANISH_PARAGUAY }, /* Spanish (Paraguay) */ { "es", "PE", SPANISH_PERU }, /* Spanish (Peru) */ { "es", "PR", SPANISH_PUERTO_RICO }, /* Spanish (Puerto Rico) */ { "es", "ES", SPANISH_MODERN_SORT }, /* Spanish (Spain) */ { "es", "ES", SPANISH_TRADITIONAL_SORT }, /* Spanish (Spain, Traditional Sort) */ { "es", "US", SPANISH_UNITED_STATES }, /* Windows Vista and later: Spanish (United States) */ { "es", "UY", SPANISH_URUGUAY }, /* Spanish (Uruguay) */ { "es", "VE", SPANISH_VENEZUELA }, /* Spanish (Venezuela) */ { "sw", "KE", SWAHILI }, /* Windows 2000 and later: Swahili (Kenya) */ { "sv", "FI", SWEDISH_FINLAND }, /* Swedish (Finland) */ { "sv", "SE", SWEDISH }, /* Swedish (Sweden) */ { "syr", "SY", SYRIAC }, /* Windows XP and later: Syriac (Syria) */ { "ta", "IN", TAMIL }, /* Windows 2000 and later: Tamil (India) */ { "tt", "RU", TATAR }, /* Windows XP and later: Tatar (Russia) */ { "te", "IN", TELUGU }, /* Windows XP and later: Telugu (India) */ { "th", "TH", THAI }, /* Thai (Thailand) */ { "bo", "BT", TIBETAN_BHUTAN }, /* Windows Vista and later: Tibetan (Bhutan) */ { "bo", "CN", TIBETAN_PRC }, /* Windows Vista and later: Tibetan (PRC) */ { "tr", "TR", TURKISH }, /* Turkish (Turkey) */ { "tk", "TM", TURKMEN }, /* Windows Vista and later: Turkmen (Turkmenistan) */ { "ug", "CN", UIGHUR }, /* Windows Vista and later: Uighur (PRC) */ { "uk", "UA", UKRAINIAN }, /* Ukrainian (Ukraine) */ { "wen", "DE", UPPER_SORBIAN }, /* Windows Vista and later: Upper Sorbian (Germany) */ { "tr", "IN", URDU_INDIA }, /* Urdu (India) */ { "ur", "PK", URDU }, /* Windows 98/Me, Windows 2000 and later: Urdu (Pakistan) */ { "uz", "UZ", UZBEK_LATIN }, /* Uzbek (Latin) */ { "uz", "Cyrl_UZ", UZBEK_CYRILLIC }, /* Uzbek (Cyrillic) */ { "vi", "VN", VIETNAMESE }, /* Windows 98/Me, Windows NT 4.0 and later: Vietnamese (Vietnam) */ { "cy", "GB", WELSH }, /* Windows XP SP2 and later: Welsh (United Kingdom) */ { "wo", "SN", WOLOF }, /* Windows Vista and later: Wolof (Senegal) */ { "xh", "ZA", XHOSA }, /* Windows XP SP2 and later: Xhosa/isiXhosa (South Africa) */ { "sah", "RU", YAKUT }, /* Windows Vista and later: Yakut (Russia) */ { "ii", "CN", YI }, /* Windows Vista and later: Yi (PRC) */ { "yo", "NG", YORUBA }, /* Windows Vista and later: Yoruba (Nigeria) */ { "zu", "ZA", ZULU } /* Windows XP SP2 and later: Zulu/isiZulu (South Africa) */ }; typedef struct { /* Locale ID */ unsigned int locale; /* Array of associated keyboard layouts */ unsigned int keyboardLayouts[5]; } localeAndKeyboardLayout; /* TODO: Use KBD_* defines instead of hardcoded values */ static const localeAndKeyboardLayout defaultKeyboardLayouts[] = { { AFRIKAANS, { 0x00000409, 0x00000409, 0x0, 0x0, 0x0 } }, { ALBANIAN, { 0x0000041c, 0x00000409, 0x0, 0x0, 0x0 } }, { ARABIC_SAUDI_ARABIA, { 0x00000409, 0x00000401, 0x0, 0x0, 0x0 } }, { ARABIC_IRAQ, { 0x00000409, 0x00000401, 0x0, 0x0, 0x0 } }, { ARABIC_EGYPT, { 0x00000409, 0x00000401, 0x0, 0x0, 0x0 } }, { ARABIC_LIBYA, { 0x0000040c, 0x00020401, 0x0, 0x0, 0x0 } }, { ARABIC_ALGERIA, { 0x0000040c, 0x00020401, 0x0, 0x0, 0x0 } }, { ARABIC_MOROCCO, { 0x0000040c, 0x00020401, 0x0, 0x0, 0x0 } }, { ARABIC_TUNISIA, { 0x0000040c, 0x00020401, 0x0, 0x0, 0x0 } }, { ARABIC_OMAN, { 0x00000409, 0x00000401, 0x0, 0x0, 0x0 } }, { ARABIC_YEMEN, { 0x00000409, 0x00000401, 0x0, 0x0, 0x0 } }, { ARABIC_SYRIA, { 0x00000409, 0x00000401, 0x0, 0x0, 0x0 } }, { ARABIC_JORDAN, { 0x00000409, 0x00000401, 0x0, 0x0, 0x0 } }, { ARABIC_LEBANON, { 0x00000409, 0x00000401, 0x0, 0x0, 0x0 } }, { ARABIC_KUWAIT, { 0x00000409, 0x00000401, 0x0, 0x0, 0x0 } }, { ARABIC_UAE, { 0x00000409, 0x00000401, 0x0, 0x0, 0x0 } }, { ARABIC_BAHRAIN, { 0x00000409, 0x00000401, 0x0, 0x0, 0x0 } }, { ARABIC_QATAR, { 0x00000409, 0x00000401, 0x0, 0x0, 0x0 } }, { ARMENIAN, { 0x0000042b, 0x00000409, 0x00000419, 0x0, 0x0 } }, { AZERI_LATIN, { 0x0000042c, 0x0000082c, 0x00000419, 0x0, 0x0 } }, { AZERI_CYRILLIC, { 0x0000082c, 0x0000042c, 0x00000419, 0x0, 0x0 } }, { BASQUE, { 0x0000040a, 0x00000409, 0x0, 0x0, 0x0 } }, { BELARUSIAN, { 0x00000423, 0x00000409, 0x00000419, 0x0, 0x0 } }, { BENGALI_INDIA, { 0x00000445, 0x00000409, 0x0, 0x0, 0x0 } }, { BOSNIAN_LATIN, { 0x0000141A, 0x00000409, 0x0, 0x0, 0x0 } }, { BULGARIAN, { 0x00000402, 0x00000409, 0x0, 0x0, 0x0 } }, { CATALAN, { 0x0000040a, 0x00000409, 0x0, 0x0, 0x0 } }, { CHINESE_TAIWAN, { 0x00000404, 0xe0080404, 0xE0010404, 0x0, 0x0 } }, { CHINESE_PRC, { 0x00000804, 0xe00e0804, 0xe0010804, 0xe0030804, 0xe0040804 } }, { CHINESE_HONG_KONG, { 0x00000409, 0xe0080404, 0x0, 0x0, 0x0 } }, { CHINESE_SINGAPORE, { 0x00000409, 0xe00e0804, 0xe0010804, 0xe0030804, 0xe0040804 } }, { CHINESE_MACAU, { 0x00000409, 0xe00e0804, 0xe0020404, 0xe0080404 } }, { CROATIAN, { 0x0000041a, 0x00000409, 0x0, 0x0, 0x0 } }, { CROATIAN_BOSNIA_HERZEGOVINA, { 0x0000041a, 0x00000409, 0x0, 0x0, 0x0 } }, { CZECH, { 0x00000405, 0x00000409, 0x0, 0x0, 0x0 } }, { DANISH, { 0x00000406, 0x00000409, 0x0, 0x0, 0x0 } }, { DIVEHI, { 0x00000409, 0x00000465, 0x0, 0x0, 0x0 } }, { DUTCH_STANDARD, { 0x00020409, 0x00000413, 0x00000409, 0x0, 0x0 } }, { DUTCH_BELGIAN, { 0x00000813, 0x00000409, 0x0, 0x0, 0x0 } }, { ENGLISH_UNITED_STATES, { 0x00000409, 0x0, 0x0, 0x0, 0x0 } }, { ENGLISH_UNITED_KINGDOM, { 0x00000809, 0x0, 0x0, 0x0, 0x0 } }, { ENGLISH_AUSTRALIAN, { 0x00000409, 0x0, 0x0, 0x0, 0x0 } }, { ENGLISH_CANADIAN, { 0x00000409, 0x00011009, 0x00001009, 0x0, 0x0 } }, { ENGLISH_NEW_ZEALAND, { 0x00000409, 0x0, 0x0, 0x0, 0x0 } }, { ENGLISH_IRELAND, { 0x00001809, 0x00011809, 0x0, 0x0, 0x0 } }, { ENGLISH_SOUTH_AFRICA, { 0x00000409, 0x0, 0x0, 0x0, 0x0 } }, { ENGLISH_JAMAICA, { 0x00000409, 0x0, 0x0, 0x0, 0x0 } }, { ENGLISH_CARIBBEAN, { 0x00000409, 0x0, 0x0, 0x0, 0x0 } }, { ENGLISH_BELIZE, { 0x00000409, 0x0, 0x0, 0x0, 0x0 } }, { ENGLISH_TRINIDAD, { 0x00000409, 0x0, 0x0, 0x0, 0x0 } }, { ENGLISH_ZIMBABWE, { 0x00000409, 0x0, 0x0, 0x0, 0x0 } }, { ENGLISH_PHILIPPINES, { 0x00000409, 0x0, 0x0, 0x0, 0x0 } }, { ESTONIAN, { 0x00000425, 0x0, 0x0, 0x0, 0x0 } }, { FAEROESE, { 0x00000406, 0x00000409, 0x0, 0x0, 0x0 } }, { FARSI, { 0x00000409, 0x00000429, 0x00000401, 0x0, 0x0 } }, { FINNISH, { 0x0000040b, 0x00000409, 0x0, 0x0, 0x0 } }, { FRENCH_STANDARD, { 0x0000040c, 0x00000409, 0x0, 0x0, 0x0 } }, { FRENCH_BELGIAN, { 0x0000080c, 0x00000409, 0x0, 0x0, 0x0 } }, { FRENCH_CANADIAN, { 0x00000C0C, 0x00011009, 0x00000409, 0x0, 0x0 } }, { FRENCH_SWISS, { 0x0000100c, 0x00000409, 0x0, 0x0, 0x0 } }, { FRENCH_LUXEMBOURG, { 0x0000040c, 0x00000409, 0x0, 0x0, 0x0 } }, { FRENCH_MONACO, { 0x0000040c, 0x00000409, 0x0, 0x0, 0x0 } }, { GEORGIAN, { 0x00000437, 0x00000409, 0x00000419, 0x0, 0x0 } }, { GALICIAN, { 0x0000040a, 0x00000409, 0x0, 0x0, 0x0 } }, { GERMAN_STANDARD, { 0x00000407, 0x00000409, 0x0, 0x0, 0x0 } }, { GERMAN_SWISS, { 0x00000807, 0x00000409, 0x0, 0x0, 0x0 } }, { GERMAN_AUSTRIAN, { 0x00000407, 0x00000409, 0x0, 0x0, 0x0 } }, { GERMAN_LUXEMBOURG, { 0x00000407, 0x00000409, 0x0, 0x0, 0x0 } }, { GERMAN_LIECHTENSTEIN, { 0x00000407, 0x00000409, 0x0, 0x0, 0x0 } }, { GREEK, { 0x00000408, 0x00000409, 0x0, 0x0, 0x0 } }, { GUJARATI, { 0x00000409, 0x00000447, 0x00010439, 0x0, 0x0 } }, { HEBREW, { 0x00000409, 0x0000040d, 0x0, 0x0, 0x0 } }, { HINDI, { 0x00000409, 0x00010439, 0x00000439, 0x0, 0x0 } }, { HUNGARIAN, { 0x0000040e, 0x00000409, 0x0, 0x0, 0x0 } }, { ICELANDIC, { 0x0000040f, 0x00000409, 0x0, 0x0, 0x0 } }, { INDONESIAN, { 0x00000409, 0x00000409, 0x0, 0x0, 0x0 } }, { ITALIAN_STANDARD, { 0x00000410, 0x00000409, 0x0, 0x0, 0x0 } }, { ITALIAN_SWISS, { 0x00000410, 0x00000409, 0x0, 0x0, 0x0 } }, { JAPANESE, { 0xe0010411, 0x0, 0x0, 0x0, 0x0 } }, { KANNADA, { 0x00000409, 0x0000044b, 0x00010439, 0x0, 0x0 } }, { KAZAKH, { 0x0000043f, 0x00000409, 0x00000419, 0x0, 0x0 } }, { KONKANI, { 0x00000409, 0x00000439, 0x0, 0x0, 0x0 } }, { KOREAN, { 0xE0010412, 0x0, 0x0, 0x0, 0x0 } }, { KYRGYZ, { 0x00000440, 0x00000409, 0x0, 0x0, 0x0 } }, { LATVIAN, { 0x00010426, 0x0, 0x0, 0x0, 0x0 } }, { LITHUANIAN, { 0x00010427, 0x0, 0x0, 0x0, 0x0 } }, { MACEDONIAN, { 0x0000042f, 0x00000409, 0x0, 0x0, 0x0 } }, { MALAY_MALAYSIA, { 0x00000409, 0x0, 0x0, 0x0, 0x0 } }, { MALAY_BRUNEI_DARUSSALAM, { 0x00000409, 0x0, 0x0, 0x0, 0x0 } }, { MALAYALAM, { 0x00000409, 0x0000044c, 0x0, 0x0, 0x0 } }, { MALTESE, { 0x00000409, 0x0000043a, 0x0, 0x0, 0x0 } }, { MAORI, { 0x00000409, 0x00000481, 0x0, 0x0, 0x0 } }, { MARATHI, { 0x00000409, 0x0000044e, 0x00000439, 0x0, 0x0 } }, { MONGOLIAN, { 0x00000450, 0x00000409, 0x0, 0x0, 0x0 } }, { NORWEGIAN_BOKMAL, { 0x00000414, 0x00000409, 0x0, 0x0, 0x0 } }, { NORWEGIAN_NYNORSK, { 0x00000414, 0x00000409, 0x0, 0x0, 0x0 } }, { POLISH, { 0x00010415, 0x00000415, 0x00000409, 0x0, 0x0 } }, { PORTUGUESE_BRAZILIAN, { 0x00000416, 0x00000409, 0x0, 0x0, 0x0 } }, { PORTUGUESE_STANDARD, { 0x00000816, 0x00000409, 0x0, 0x0, 0x0 } }, { PUNJABI, { 0x00000409, 0x00000446, 0x00010439, 0x0, 0x0 } }, { QUECHUA_BOLIVIA, { 0x00000409, 0x0000080A, 0x0, 0x0, 0x0 } }, { QUECHUA_ECUADOR, { 0x00000409, 0x0000080A, 0x0, 0x0, 0x0 } }, { QUECHUA_PERU, { 0x00000409, 0x0000080A, 0x0, 0x0, 0x0 } }, { ROMANIAN, { 0x00000418, 0x00000409, 0x0, 0x0, 0x0 } }, { RUSSIAN, { 0x00000419, 0x00000409, 0x0, 0x0, 0x0 } }, { SAMI_INARI, { 0x0001083b, 0x00000409, 0x0, 0x0, 0x0 } }, { SAMI_LULE_NORWAY, { 0x0000043b, 0x00000409, 0x0, 0x0, 0x0 } }, { SAMI_LULE_SWEDEN, { 0x0000083b, 0x00000409, 0x0, 0x0, 0x0 } }, { SAMI_NORTHERN_FINLAND, { 0x0001083b, 0x00000409, 0x0, 0x0, 0x0 } }, { SAMI_NORTHERN_NORWAY, { 0x0000043b, 0x00000409, 0x0, 0x0, 0x0 } }, { SAMI_NORTHERN_SWEDEN, { 0x0000083b, 0x00000409, 0x0, 0x0, 0x0 } }, { SAMI_SKOLT, { 0x0001083b, 0x00000409, 0x0, 0x0, 0x0 } }, { SAMI_SOUTHERN_NORWAY, { 0x0000043b, 0x00000409, 0x0, 0x0, 0x0 } }, { SAMI_SOUTHERN_SWEDEN, { 0x0000083b, 0x00000409, 0x0, 0x0, 0x0 } }, { SANSKRIT, { 0x00000409, 0x00000439, 0x0, 0x0, 0x0 } }, { SERBIAN_LATIN, { 0x0000081a, 0x00000409, 0x0, 0x0, 0x0 } }, { SERBIAN_LATIN_BOSNIA_HERZEGOVINA, { 0x0000081a, 0x00000409, 0x0, 0x0, 0x0 } }, { SERBIAN_CYRILLIC, { 0x00000c1a, 0x00000409, 0x0, 0x0, 0x0 } }, { SERBIAN_CYRILLIC_BOSNIA_HERZEGOVINA, { 0x00000c1a, 0x00000409, 0x0, 0x0, 0x0 } }, { SLOVAK, { 0x0000041b, 0x00000409, 0x0, 0x0, 0x0 } }, { SLOVENIAN, { 0x00000424, 0x00000409, 0x0, 0x0, 0x0 } }, { SPANISH_TRADITIONAL_SORT, { 0x0000040a, 0x00000409, 0x0, 0x0, 0x0 } }, { SPANISH_MEXICAN, { 0x0000080a, 0x00000409, 0x0, 0x0, 0x0 } }, { SPANISH_MODERN_SORT, { 0x0000040a, 0x00000409, 0x0, 0x0, 0x0 } }, { SPANISH_GUATEMALA, { 0x0000080a, 0x00000409, 0x0, 0x0, 0x0 } }, { SPANISH_COSTA_RICA, { 0x0000080a, 0x00000409, 0x0, 0x0, 0x0 } }, { SPANISH_PANAMA, { 0x0000080a, 0x00000409, 0x0, 0x0, 0x0 } }, { SPANISH_DOMINICAN_REPUBLIC, { 0x0000080a, 0x00000409, 0x0, 0x0, 0x0 } }, { SPANISH_VENEZUELA, { 0x0000080a, 0x00000409, 0x0, 0x0, 0x0 } }, { SPANISH_COLOMBIA, { 0x0000080a, 0x00000409, 0x0, 0x0, 0x0 } }, { SPANISH_PERU, { 0x0000080a, 0x00000409, 0x0, 0x0, 0x0 } }, { SPANISH_ARGENTINA, { 0x0000080a, 0x00000409, 0x0, 0x0, 0x0 } }, { SPANISH_ECUADOR, { 0x0000080a, 0x00000409, 0x0, 0x0, 0x0 } }, { SPANISH_CHILE, { 0x0000080a, 0x00000409, 0x0, 0x0, 0x0 } }, { SPANISH_URUGUAY, { 0x0000080a, 0x00000409, 0x0, 0x0, 0x0 } }, { SPANISH_PARAGUAY, { 0x0000080a, 0x00000409, 0x0, 0x0, 0x0 } }, { SPANISH_BOLIVIA, { 0x0000080a, 0x00000409, 0x0, 0x0, 0x0 } }, { SPANISH_EL_SALVADOR, { 0x0000080a, 0x00000409, 0x0, 0x0, 0x0 } }, { SPANISH_HONDURAS, { 0x0000080a, 0x00000409, 0x0, 0x0, 0x0 } }, { SPANISH_NICARAGUA, { 0x0000080a, 0x00000409, 0x0, 0x0, 0x0 } }, { SPANISH_PUERTO_RICO, { 0x0000080a, 0x00000409, 0x0, 0x0, 0x0 } }, { SWAHILI, { 0x00000409, 0x0, 0x0, 0x0, 0x0 } }, { SWEDISH, { 0x0000041d, 0x00000409, 0x0, 0x0, 0x0 } }, { SWEDISH_FINLAND, { 0x0000041d, 0x00000409, 0x0, 0x0, 0x0 } }, { SYRIAC, { 0x00000409, 0x0000045a, 0x0, 0x0, 0x0 } }, { TAMIL, { 0x00000409, 0x00000449, 0x0, 0x0, 0x0 } }, { TATAR, { 0x00000444, 0x00000409, 0x00000419, 0x0, 0x0 } }, { TELUGU, { 0x00000409, 0x0000044a, 0x00010439, 0x0, 0x0 } }, { THAI, { 0x00000409, 0x0000041e, 0x0, 0x0, 0x0 } }, { TSWANA, { 0x00000409, 0x0000041f, 0x0, 0x0, 0x0 } }, { UKRAINIAN, { 0x00000422, 0x00000409, 0x0, 0x0, 0x0 } }, { TURKISH, { 0x0000041f, 0x0000041f, 0x0, 0x0, 0x0 } }, { UKRAINIAN, { 0x00000422, 0x00000409, 0x0, 0x0, 0x0 } }, { URDU, { 0x00000401, 0x00000409, 0x0, 0x0, 0x0 } }, { UZBEK_LATIN, { 0x00000409, 0x00000843, 0x00000419, 0x0, 0x0 } }, { UZBEK_CYRILLIC, { 0x00000843, 0x00000409, 0x00000419, 0x0, 0x0 } }, { VIETNAMESE, { 0x00000409, 0x0000042a, 0x0, 0x0, 0x0 } }, { WELSH, { 0x00000452, 0x00000809, 0x0, 0x0, 0x0 } }, { XHOSA, { 0x00000409, 0x00000409, 0x0, 0x0, 0x0 } }, }; unsigned int detect_keyboard_layout_from_locale() { int dot; int i, j, k; int underscore; char language[4]; char country[10]; /* LANG = _. */ char* envLang = getenv("LANG"); /* Get locale from environment variable LANG */ if (envLang == NULL) return 0; /* LANG environment variable was not set */ underscore = strcspn(envLang, "_"); if (underscore > 3) return 0; /* The language name should not be more than 3 letters long */ else { /* Get language code */ strncpy(language, envLang, underscore); language[underscore] = '\0'; } /* * There is always the special case of "C" or "POSIX" as locale name * In this case, use a U.S. keyboard and a U.S. keyboard layout */ if ((strcmp(language, "C") == 0) || (strcmp(language, "POSIX") == 0)) return ENGLISH_UNITED_STATES; /* U.S. Keyboard Layout */ dot = strcspn(envLang, "."); /* Get country code */ if (dot > underscore) { strncpy(country, &envLang[underscore + 1], dot - underscore - 1); country[dot - underscore - 1] = '\0'; } else return 0; /* Invalid locale */ for (i = 0; i < sizeof(locales) / sizeof(locale); i++) { if ((strcmp(language, locales[i].language) == 0) && (strcmp(country, locales[i].country) == 0)) break; } DEBUG_KBD("Found locale : %s_%s", locales[i].language, locales[i].country); for (j = 0; j < sizeof(defaultKeyboardLayouts) / sizeof(localeAndKeyboardLayout); j++) { if (defaultKeyboardLayouts[j].locale == locales[i].code) { /* Locale found in list of default keyboard layouts */ for (k = 0; k < 5; k++) { if (defaultKeyboardLayouts[j].keyboardLayouts[k] == ENGLISH_UNITED_STATES) { continue; /* Skip, try to get a more localized keyboard layout */ } else if (defaultKeyboardLayouts[j].keyboardLayouts[k] == 0) { break; /* No more keyboard layouts */ } else { return defaultKeyboardLayouts[j].keyboardLayouts[k]; } } /* * If we skip the ENGLISH_UNITED_STATES keyboard layout but there are no * other possible keyboard layout for the locale, we end up here with k > 1 */ if (k >= 1) return ENGLISH_UNITED_STATES; else return 0; } } return 0; /* Could not detect the current keyboard layout from locale */ } FreeRDP-1.0.2/libfreerdp-kbd/x_layout_id_table.c000066400000000000000000001266641207112532300214630ustar00rootroot00000000000000/** * FreeRDP: A Remote Desktop Protocol Client * XKB-based Keyboard Mapping to Microsoft Keyboard System * * Copyright 2009 Marc-Andre Moreau * * 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. */ #include #include #include #include "libkbd.h" #include #include "x_layout_id_table.h" typedef struct { /* XKB Keyboard layout variant */ const char* variant; /* Keyboard Layout ID */ unsigned int keyboardLayoutID; } xkbVariant; typedef struct { /* XKB Keyboard layout */ const char* layout; /* Keyboard Layout ID */ unsigned int keyboardLayoutID; const xkbVariant* variants; } xkbLayout; /* Those have been generated automatically and are waiting to be filled by hand */ /* USA */ static const xkbVariant us_variants[] = { { "chr", 0 }, /* Cherokee */ { "euro", 0 }, /* With EuroSign on 5 */ { "intl", KBD_UNITED_STATES_INTERNATIONAL }, /* International (with dead keys) */ { "alt-intl", KBD_UNITED_STATES_INTERNATIONAL }, /* Alternative international (former us_intl) */ { "colemak", 0 }, /* Colemak */ { "dvorak", KBD_UNITED_STATES_DVORAK }, /* Dvorak */ { "dvorak-intl", KBD_UNITED_STATES_DVORAK }, /* Dvorak international */ { "dvorak-l", KBD_UNITED_STATES_DVORAK_FOR_LEFT_HAND }, /* Left handed Dvorak */ { "dvorak-r", KBD_UNITED_STATES_DVORAK_FOR_RIGHT_HAND }, /* Right handed Dvorak */ { "dvorak-classic", KBD_UNITED_STATES_DVORAK }, /* Classic Dvorak */ { "dvp", KBD_UNITED_STATES_DVORAK }, /* Programmer Dvorak */ { "rus", 0 }, /* Russian phonetic */ { "mac", KBD_US }, /* Macintosh */ { "altgr-intl", KBD_UNITED_STATES_INTERNATIONAL }, /* International (AltGr dead keys) */ { "olpc2", KBD_US }, /* Group toggle on multiply/divide key */ { "", 0 }, }; /* Afghanistan */ static const xkbVariant af_variants[] = { { "ps", KBD_PASHTO }, /* Pashto */ { "uz", KBD_UZBEK_CYRILLIC }, /* Southern Uzbek */ { "olpc-ps", KBD_PASHTO }, /* OLPC Pashto */ { "olpc-fa", 0 }, /* OLPC Dari */ { "olpc-uz", KBD_UZBEK_CYRILLIC }, /* OLPC Southern Uzbek */ { "", 0 }, }; /* Arabic */ static const xkbVariant ara_variants[] = { { "azerty", KBD_ARABIC_102_AZERTY }, /* azerty */ { "azerty_digits", KBD_ARABIC_102_AZERTY }, /* azerty/digits */ { "digits", KBD_ARABIC_102_AZERTY }, /* digits */ { "qwerty", KBD_ARABIC_101 }, /* qwerty */ { "qwerty_digits", KBD_ARABIC_101 }, /* qwerty/digits */ { "buckwalter", KBD_US_ENGLISH_TABLE_FOR_IBM_ARABIC_238_L }, /* Buckwalter */ { "", 0 }, }; /* Armenia */ static const xkbVariant am_variants[] = { { "phonetic", 0 }, /* Phonetic */ { "phonetic-alt", 0 }, /* Alternative Phonetic */ { "eastern", KBD_ARMENIAN_EASTERN }, /* Eastern */ { "western", KBD_ARMENIAN_WESTERN }, /* Western */ { "eastern-alt", KBD_ARMENIAN_EASTERN }, /* Alternative Eastern */ { "", 0 }, }; /* Azerbaijan */ static const xkbVariant az_variants[] = { { "cyrillic", KBD_AZERI_CYRILLIC }, /* Cyrillic */ { "", 0 }, }; /* Belarus */ static const xkbVariant by_variants[] = { { "winkeys", KBD_BELARUSIAN }, /* Winkeys */ { "latin", KBD_BELARUSIAN }, /* Latin */ { "", 0 }, }; /* Belgium */ static const xkbVariant be_variants[] = { { "oss", KBD_BELGIAN_FRENCH }, /* Alternative */ { "oss_latin9", KBD_BELGIAN_FRENCH }, /* Alternative, latin-9 only */ { "oss_sundeadkeys", KBD_BELGIAN_PERIOD }, /* Alternative, Sun dead keys */ { "iso-alternate", KBD_BELGIAN_COMMA }, /* ISO Alternate */ { "nodeadkeys", KBD_BELGIAN_COMMA }, /* Eliminate dead keys */ { "sundeadkeys", KBD_BELGIAN_PERIOD }, /* Sun dead keys */ { "wang", KBD_BELGIAN_FRENCH }, /* Wang model 724 azerty */ { "", 0 }, }; /* Bangladesh */ static const xkbVariant bd_variants[] = { { "probhat", KBD_BENGALI_INSCRIPT }, /* Probhat */ { "", 0 }, }; /* India */ static const xkbVariant in_variants[] = { { "ben", KBD_BENGALI }, /* Bengali */ { "ben_probhat", KBD_BENGALI_INSCRIPT }, /* Bengali Probhat */ { "guj", KBD_GUJARATI }, /* Gujarati */ { "guru", 0 }, /* Gurmukhi */ { "jhelum", 0 }, /* Gurmukhi Jhelum */ { "kan", KBD_KANNADA }, /* Kannada */ { "mal", KBD_MALAYALAM }, /* Malayalam */ { "mal_lalitha", KBD_MALAYALAM }, /* Malayalam Lalitha */ { "ori", 0 }, /* Oriya */ { "tam_unicode", KBD_TAMIL }, /* Tamil Unicode */ { "tam_TAB", KBD_TAMIL }, /* Tamil TAB Typewriter */ { "tam_TSCII", KBD_TAMIL }, /* Tamil TSCII Typewriter */ { "tam", KBD_TAMIL }, /* Tamil */ { "tel", KBD_TELUGU }, /* Telugu */ { "urd-phonetic", KBD_URDU }, /* Urdu, Phonetic */ { "urd-phonetic3", KBD_URDU }, /* Urdu, Alternative phonetic */ { "urd-winkeys", KBD_URDU }, /* Urdu, Winkeys */ { "bolnagri", KBD_HINDI_TRADITIONAL }, /* Hindi Bolnagri */ { "hin-wx", KBD_HINDI_TRADITIONAL }, /* Hindi Wx */ { "", 0 }, }; /* Bosnia and Herzegovina */ static const xkbVariant ba_variants[] = { { "alternatequotes", KBD_BOSNIAN }, /* Use guillemets for quotes */ { "unicode", KBD_BOSNIAN }, /* Use Bosnian digraphs */ { "unicodeus", KBD_BOSNIAN }, /* US keyboard with Bosnian digraphs */ { "us", KBD_BOSNIAN_CYRILLIC }, /* US keyboard with Bosnian letters */ { "", 0 }, }; /* Brazil */ static const xkbVariant br_variants[] = { { "nodeadkeys", KBD_PORTUGUESE_BRAZILIAN_ABNT2 }, /* Eliminate dead keys */ { "dvorak", KBD_UNITED_STATES_DVORAK }, /* Dvorak */ { "nativo", KBD_PORTUGUESE_BRAZILIAN_ABNT2 }, /* Nativo */ { "nativo-us", KBD_PORTUGUESE_BRAZILIAN_ABNT2 }, /* Nativo for USA keyboards */ { "nativo-epo", KBD_PORTUGUESE_BRAZILIAN_ABNT2 }, /* Nativo for Esperanto */ { "", 0 }, }; /* Bulgaria */ static const xkbVariant bg_variants[] = { { "phonetic", KBD_BULGARIAN_LATIN }, /* Traditional Phonetic */ { "bas_phonetic", KBD_BULGARIAN_LATIN }, /* Standard Phonetic */ { "", 0 }, }; /* Morocco */ static const xkbVariant ma_variants[] = { { "french", KBD_FRENCH }, /* French */ { "tifinagh", 0 }, /* Tifinagh */ { "tifinagh-alt", 0 }, /* Tifinagh Alternative */ { "tifinagh-alt-phonetic", 0 }, /* Tifinagh Alternative Phonetic */ { "tifinagh-extended", 0 }, /* Tifinagh Extended */ { "tifinagh-phonetic", 0 }, /* Tifinagh Phonetic */ { "tifinagh-extended-phonetic", 0 }, /* Tifinagh Extended Phonetic */ { "", 0 }, }; /* Canada */ static const xkbVariant ca_variants[] = { { "fr-dvorak", KBD_UNITED_STATES_DVORAK }, /* French Dvorak */ { "fr-legacy", KBD_CANADIAN_FRENCH }, /* French (legacy) */ { "multix", KBD_CANADIAN_MULTILINGUAL_STANDARD }, /* Multilingual */ { "multi", KBD_CANADIAN_MULTILINGUAL_STANDARD }, /* Multilingual, first part */ { "multi-2gr", KBD_CANADIAN_MULTILINGUAL_STANDARD }, /* Multilingual, second part */ { "ike", KBD_INUKTITUT_LATIN }, /* Inuktitut */ { "shs", 0 }, /* Secwepemctsin */ { "kut", 0 }, /* Ktunaxa */ { "eng", KBD_US }, /* English */ { "", 0 }, }; /* China */ static const xkbVariant cn_variants[] = { { "tib", 0 }, /* Tibetan */ { "tib_asciinum", 0 }, /* Tibetan (with ASCII numerals) */ { "", 0 }, }; /* Croatia */ static const xkbVariant hr_variants[] = { { "alternatequotes", KBD_CROATIAN }, /* Use guillemets for quotes */ { "unicode", KBD_CROATIAN }, /* Use Croatian digraphs */ { "unicodeus", KBD_CROATIAN }, /* US keyboard with Croatian digraphs */ { "us", KBD_CROATIAN }, /* US keyboard with Croatian letters */ { "", 0 }, }; /* Czechia */ static const xkbVariant cz_variants[] = { { "bksl", KBD_CZECH_PROGRAMMERS }, /* With <\|> key */ { "qwerty", KBD_CZECH_QWERTY }, /* qwerty */ { "qwerty_bksl", KBD_CZECH_QWERTY }, /* qwerty, extended Backslash */ { "ucw", KBD_CZECH }, /* UCW layout (accented letters only) */ { "", 0 }, }; /* Denmark */ static const xkbVariant dk_variants[] = { { "nodeadkeys", KBD_DANISH }, /* Eliminate dead keys */ { "mac", KBD_DANISH }, /* Macintosh */ { "mac_nodeadkeys", KBD_DANISH }, /* Macintosh, eliminate dead keys */ { "dvorak", KBD_UNITED_STATES_DVORAK }, /* Dvorak */ { "", 0 }, }; /* Netherlands */ static const xkbVariant nl_variants[] = { { "sundeadkeys", KBD_SWISS_FRENCH }, /* Sun dead keys */ { "mac", KBD_SWISS_FRENCH }, /* Macintosh */ { "std", KBD_SWISS_FRENCH }, /* Standard */ { "", 0 }, }; /* Estonia */ static const xkbVariant ee_variants[] = { { "nodeadkeys", KBD_US }, /* Eliminate dead keys */ { "dvorak", KBD_UNITED_STATES_DVORAK }, /* Dvorak */ { "us", KBD_UNITED_STATES_INTERNATIONAL }, /* US keyboard with Estonian letters */ { "", 0 }, }; /* Iran */ static const xkbVariant ir_variants[] = { { "pro", 0 }, /* Pro */ { "keypad", 0 }, /* Keypad */ { "pro_keypad", 0 }, /* Pro Keypad */ { "ku", 0 }, /* Kurdish, Latin Q */ { "ku_f", 0 }, /* Kurdish, (F) */ { "ku_alt", 0 }, /* Kurdish, Latin Alt-Q */ { "ku_ara", 0 }, /* Kurdish, Arabic-Latin */ { "", 0 }, }; /* Iraq */ static const xkbVariant iq_variants[] = { { "ku", 0 }, /* Kurdish, Latin Q */ { "ku_f", 0 }, /* Kurdish, (F) */ { "ku_alt", 0 }, /* Kurdish, Latin Alt-Q */ { "ku_ara", 0 }, /* Kurdish, Arabic-Latin */ { "", 0 }, }; /* Faroe Islands */ static const xkbVariant fo_variants[] = { { "nodeadkeys", 0 }, /* Eliminate dead keys */ { "", 0 }, }; /* Finland */ static const xkbVariant fi_variants[] = { { "nodeadkeys", 0 }, /* Eliminate dead keys */ { "smi", 0 }, /* Northern Saami */ { "classic", 0 }, /* Classic */ { "mac", 0 }, /* Macintosh */ { "", 0 }, }; /* France */ static const xkbVariant fr_variants[] = { { "nodeadkeys", 0 }, /* Eliminate dead keys */ { "sundeadkeys", 0 }, /* Sun dead keys */ { "oss", 0 }, /* Alternative */ { "oss_latin9", 0 }, /* Alternative, latin-9 only */ { "oss_nodeadkeys", 0 }, /* Alternative, eliminate dead keys */ { "oss_sundeadkeys", 0 }, /* Alternative, Sun dead keys */ { "latin9", 0 }, /* (Legacy) Alternative */ { "latin9_nodeadkeys", 0 }, /* (Legacy) Alternative, eliminate dead keys */ { "latin9_sundeadkeys", 0 }, /* (Legacy) Alternative, Sun dead keys */ { "bepo", 0 }, /* Bepo, ergonomic, Dvorak way */ { "bepo_latin9", 0 }, /* Bepo, ergonomic, Dvorak way, latin-9 only */ { "dvorak", 0 }, /* Dvorak */ { "mac", 0 }, /* Macintosh */ { "bre", 0 }, /* Breton */ { "oci", 0 }, /* Occitan */ { "geo", 0 }, /* Georgian AZERTY Tskapo */ { "", 0 }, }; /* Ghana */ static const xkbVariant gh_variants[] = { { "generic", 0 }, /* Multilingual */ { "akan", 0 }, /* Akan */ { "ewe", 0 }, /* Ewe */ { "fula", 0 }, /* Fula */ { "ga", 0 }, /* Ga */ { "hausa", 0 }, /* Hausa */ { "", 0 }, }; /* Georgia */ static const xkbVariant ge_variants[] = { { "ergonomic", 0 }, /* Ergonomic */ { "mess", 0 }, /* MESS */ { "ru", 0 }, /* Russian */ { "os", 0 }, /* Ossetian */ { "", 0 }, }; /* Germany */ static const xkbVariant de_variants[] = { { "deadacute", KBD_GERMAN }, /* Dead acute */ { "deadgraveacute", KBD_GERMAN }, /* Dead grave acute */ { "nodeadkeys", KBD_GERMAN }, /* Eliminate dead keys */ { "ro", KBD_GERMAN }, /* Romanian keyboard with German letters */ { "ro_nodeadkeys", KBD_GERMAN }, /* Romanian keyboard with German letters, eliminate dead keys */ { "dvorak", KBD_UNITED_STATES_DVORAK }, /* Dvorak */ { "sundeadkeys", KBD_GERMAN }, /* Sun dead keys */ { "neo", KBD_GERMAN_NEO }, /* Neo 2 */ { "mac", KBD_GERMAN }, /* Macintosh */ { "mac_nodeadkeys", KBD_GERMAN }, /* Macintosh, eliminate dead keys */ { "dsb", KBD_GERMAN }, /* Lower Sorbian */ { "dsb_qwertz", KBD_GERMAN }, /* Lower Sorbian (qwertz) */ { "qwerty", KBD_GERMAN_IBM }, /* qwerty */ { "", 0 }, }; /* Greece */ static const xkbVariant gr_variants[] = { { "simple", KBD_GREEK_220 }, /* Simple */ { "extended", KBD_GREEK_319 }, /* Extended */ { "nodeadkeys", KBD_GREEK_319}, /* Eliminate dead keys */ { "polytonic", KBD_GREEK_POLYTONIC }, /* Polytonic */ { "", 0 }, }; /* Hungary */ static const xkbVariant hu_variants[] = { { "standard", KBD_HUNGARIAN_101_KEY }, /* Standard */ { "nodeadkeys", KBD_HUNGARIAN_101_KEY }, /* Eliminate dead keys */ { "qwerty", KBD_HUNGARIAN_101_KEY }, /* qwerty */ { "101_qwertz_comma_dead", KBD_HUNGARIAN_101_KEY }, /* 101/qwertz/comma/Dead keys */ { "101_qwertz_comma_nodead", KBD_HUNGARIAN_101_KEY }, /* 101/qwertz/comma/Eliminate dead keys */ { "101_qwertz_dot_dead", KBD_HUNGARIAN_101_KEY }, /* 101/qwertz/dot/Dead keys */ { "101_qwertz_dot_nodead", KBD_HUNGARIAN_101_KEY }, /* 101/qwertz/dot/Eliminate dead keys */ { "101_qwerty_comma_dead", KBD_HUNGARIAN_101_KEY }, /* 101/qwerty/comma/Dead keys */ { "101_qwerty_comma_nodead", KBD_HUNGARIAN_101_KEY }, /* 101/qwerty/comma/Eliminate dead keys */ { "101_qwerty_dot_dead", KBD_HUNGARIAN_101_KEY }, /* 101/qwerty/dot/Dead keys */ { "101_qwerty_dot_nodead", KBD_HUNGARIAN_101_KEY }, /* 101/qwerty/dot/Eliminate dead keys */ { "102_qwertz_comma_dead", KBD_HUNGARIAN_101_KEY }, /* 102/qwertz/comma/Dead keys */ { "102_qwertz_comma_nodead", KBD_HUNGARIAN_101_KEY }, /* 102/qwertz/comma/Eliminate dead keys */ { "102_qwertz_dot_dead", KBD_HUNGARIAN_101_KEY }, /* 102/qwertz/dot/Dead keys */ { "102_qwertz_dot_nodead", KBD_HUNGARIAN_101_KEY }, /* 102/qwertz/dot/Eliminate dead keys */ { "102_qwerty_comma_dead", KBD_HUNGARIAN_101_KEY }, /* 102/qwerty/comma/Dead keys */ { "102_qwerty_comma_nodead", KBD_HUNGARIAN_101_KEY }, /* 102/qwerty/comma/Eliminate dead keys */ { "102_qwerty_dot_dead", KBD_HUNGARIAN_101_KEY }, /* 102/qwerty/dot/Dead keys */ { "102_qwerty_dot_nodead", KBD_HUNGARIAN_101_KEY }, /* 102/qwerty/dot/Eliminate dead keys */ { "", 0 }, }; /* Iceland */ static const xkbVariant is_variants[] = { { "Sundeadkeys", KBD_ICELANDIC }, /* Sun dead keys */ { "nodeadkeys", KBD_ICELANDIC }, /* Eliminate dead keys */ { "mac", KBD_ICELANDIC }, /* Macintosh */ { "dvorak", KBD_UNITED_STATES_DVORAK }, /* Dvorak */ { "", 0 }, }; /* Israel */ static const xkbVariant il_variants[] = { { "lyx", KBD_HEBREW }, /* lyx */ { "phonetic", KBD_HEBREW }, /* Phonetic */ { "biblical", KBD_HEBREW }, /* Biblical Hebrew (Tiro) */ { "", 0 }, }; /* Italy */ static const xkbVariant it_variants[] = { { "nodeadkeys", KBD_ITALIAN_142 }, /* Eliminate dead keys */ { "mac", KBD_ITALIAN }, /* Macintosh */ { "geo", KBD_GEORGIAN }, /* Georgian */ { "", 0 }, }; /* Japan */ static const xkbVariant jp_variants[] = { { "kana", KBD_JAPANESE_INPUT_SYSTEM_MS_IME2002 }, /* Kana */ { "OADG109A", KBD_JAPANESE_INPUT_SYSTEM_MS_IME2002 }, /* OADG 109A */ { "", 0 }, }; /* Kyrgyzstan */ static const xkbVariant kg_variants[] = { { "phonetic", KBD_KYRGYZ_CYRILLIC }, /* Phonetic */ { "", 0 }, }; /* Kazakhstan */ static const xkbVariant kz_variants[] = { { "ruskaz", KBD_KAZAKH }, /* Russian with Kazakh */ { "kazrus", KBD_KAZAKH }, /* Kazakh with Russian */ { "", 0 }, }; /* Latin America */ static const xkbVariant latam_variants[] = { { "nodeadkeys", KBD_LATIN_AMERICAN }, /* Eliminate dead keys */ { "deadtilde", KBD_LATIN_AMERICAN }, /* Include dead tilde */ { "sundeadkeys", KBD_LATIN_AMERICAN }, /* Sun dead keys */ { "", 0 }, }; /* Lithuania */ static const xkbVariant lt_variants[] = { { "std", KBD_LITHUANIAN }, /* Standard */ { "us", KBD_LITHUANIAN_IBM }, /* US keyboard with Lithuanian letters */ { "ibm", KBD_LITHUANIAN_IBM }, /* IBM (LST 1205-92) */ { "lekp", KBD_LITHUANIAN }, /* LEKP */ { "lekpa", KBD_LITHUANIAN }, /* LEKPa */ { "balticplus", KBD_LITHUANIAN }, /* Baltic+ */ { "", 0 }, }; /* Latvia */ static const xkbVariant lv_variants[] = { { "apostrophe", KBD_LATVIAN }, /* Apostrophe (') variant */ { "tilde", KBD_LATVIAN }, /* Tilde (~) variant */ { "fkey", KBD_LATVIAN }, /* F-letter (F) variant */ { "", 0 }, }; /* Montenegro */ static const xkbVariant me_variants[] = { { "cyrillic", 0 }, /* Cyrillic */ { "cyrillicyz", 0 }, /* Cyrillic, Z and ZHE swapped */ { "latinunicode", 0 }, /* Latin unicode */ { "latinyz", 0 }, /* Latin qwerty */ { "latinunicodeyz", 0 }, /* Latin unicode qwerty */ { "cyrillicalternatequotes", 0 }, /* Cyrillic with guillemets */ { "latinalternatequotes", 0 }, /* Latin with guillemets */ { "", 0 }, }; /* Macedonia */ static const xkbVariant mk_variants[] = { { "nodeadkeys", KBD_FYRO_MACEDONIAN }, /* Eliminate dead keys */ { "", 0 }, }; /* Malta */ static const xkbVariant mt_variants[] = { { "us", KBD_MALTESE_48_KEY }, /* Maltese keyboard with US layout */ { "", 0 }, }; /* Norway */ static const xkbVariant no_variants[] = { { "nodeadkeys", KBD_NORWEGIAN }, /* Eliminate dead keys */ { "dvorak", KBD_UNITED_STATES_DVORAK }, /* Dvorak */ { "smi", KBD_NORWEGIAN_WITH_SAMI }, /* Northern Saami */ { "smi_nodeadkeys", KBD_SAMI_EXTENDED_NORWAY }, /* Northern Saami, eliminate dead keys */ { "mac", KBD_NORWEGIAN }, /* Macintosh */ { "mac_nodeadkeys", KBD_SAMI_EXTENDED_NORWAY }, /* Macintosh, eliminate dead keys */ { "", 0 }, }; /* Poland */ static const xkbVariant pl_variants[] = { { "qwertz", KBD_POLISH_214 }, /* qwertz */ { "dvorak", KBD_UNITED_STATES_DVORAK }, /* Dvorak */ { "dvorak_quotes", KBD_UNITED_STATES_DVORAK }, /* Dvorak, Polish quotes on quotemark key */ { "dvorak_altquotes", KBD_UNITED_STATES_DVORAK }, /* Dvorak, Polish quotes on key 1 */ { "csb", 0 }, /* Kashubian */ { "ru_phonetic_dvorak", KBD_UNITED_STATES_DVORAK }, /* Russian phonetic Dvorak */ { "", 0 }, }; /* Portugal */ static const xkbVariant pt_variants[] = { { "nodeadkeys", KBD_PORTUGUESE }, /* Eliminate dead keys */ { "sundeadkeys", KBD_PORTUGUESE }, /* Sun dead keys */ { "mac", KBD_PORTUGUESE }, /* Macintosh */ { "mac_nodeadkeys", KBD_PORTUGUESE }, /* Macintosh, eliminate dead keys */ { "mac_sundeadkeys", KBD_PORTUGUESE }, /* Macintosh, Sun dead keys */ { "nativo", KBD_PORTUGUESE }, /* Nativo */ { "nativo-us", KBD_PORTUGUESE }, /* Nativo for USA keyboards */ { "nativo-epo", KBD_PORTUGUESE }, /* Nativo for Esperanto */ { "", 0 }, }; /* Romania */ static const xkbVariant ro_variants[] = { { "cedilla", KBD_ROMANIAN }, /* Cedilla */ { "std", KBD_ROMANIAN }, /* Standard */ { "std_cedilla", KBD_ROMANIAN }, /* Standard (Cedilla) */ { "winkeys", KBD_ROMANIAN }, /* Winkeys */ { "crh_f", KBD_TURKISH_F }, /* Crimean Tatar (Turkish F) */ { "crh_alt", KBD_TURKISH_Q }, /* Crimean Tatar (Turkish Alt-Q) */ { "crh_dobruca1", KBD_TATAR }, /* Crimean Tatar (Dobruca-1 Q) */ { "crh_dobruca2", KBD_TATAR }, /* Crimean Tatar (Dobruca-2 Q) */ { "", 0 }, }; /* Russia */ static const xkbVariant ru_variants[] = { { "phonetic", KBD_RUSSIAN }, /* Phonetic */ { "phonetic_winkeys", KBD_RUSSIAN }, /* Phonetic Winkeys */ { "typewriter", KBD_RUSSIAN_TYPEWRITER }, /* Typewriter */ { "legacy", KBD_RUSSIAN }, /* Legacy */ { "tt", KBD_TATAR }, /* Tatar */ { "os_legacy", 0 }, /* Ossetian, legacy */ { "os_winkeys", 0 }, /* Ossetian, Winkeys */ { "cv", 0 }, /* Chuvash */ { "cv_latin", 0 }, /* Chuvash Latin */ { "udm", 0 }, /* Udmurt */ { "kom", 0 }, /* Komi */ { "sah", 0 }, /* Yakut */ { "xal", 0 }, /* Kalmyk */ { "dos", 0 }, /* DOS */ { "", 0 }, }; /* Serbia */ static const xkbVariant rs_variants[] = { { "yz", KBD_SERBIAN_CYRILLIC }, /* Z and ZHE swapped */ { "latin", KBD_SERBIAN_LATIN }, /* Latin */ { "latinunicode", KBD_SERBIAN_LATIN }, /* Latin Unicode */ { "latinyz", KBD_SERBIAN_LATIN }, /* Latin qwerty */ { "latinunicodeyz", KBD_SERBIAN_LATIN }, /* Latin Unicode qwerty */ { "alternatequotes", KBD_SERBIAN_CYRILLIC }, /* With guillemets */ { "latinalternatequotes", KBD_SERBIAN_LATIN }, /* Latin with guillemets */ { "", 0 }, }; /* Slovenia */ static const xkbVariant si_variants[] = { { "alternatequotes", KBD_SLOVENIAN }, /* Use guillemets for quotes */ { "us", KBD_UNITED_STATES_INTERNATIONAL }, /* US keyboard with Slovenian letters */ { "", 0 }, }; /* Slovakia */ static const xkbVariant sk_variants[] = { { "bksl", KBD_SLOVAK }, /* Extended Backslash */ { "qwerty", KBD_SLOVAK_QWERTY }, /* qwerty */ { "qwerty_bksl", KBD_SLOVAK_QWERTY }, /* qwerty, extended Backslash */ { "", 0 }, }; /* Spain */ static const xkbVariant es_variants[] = { { "nodeadkeys", KBD_SPANISH_VARIATION }, /* Eliminate dead keys */ { "deadtilde", KBD_SPANISH_VARIATION }, /* Include dead tilde */ { "sundeadkeys", KBD_SPANISH }, /* Sun dead keys */ { "dvorak", KBD_UNITED_STATES_DVORAK }, /* Dvorak */ { "ast", KBD_SPANISH_VARIATION }, /* Asturian variant with bottom-dot H and bottom-dot L */ { "cat", KBD_SPANISH_VARIATION }, /* Catalan variant with middle-dot L */ { "mac", KBD_SPANISH }, /* Macintosh */ { "", 0 }, }; /* Sweden */ static const xkbVariant se_variants[] = { { "nodeadkeys", KBD_SWEDISH }, /* Eliminate dead keys */ { "dvorak", KBD_UNITED_STATES_DVORAK }, /* Dvorak */ { "rus", KBD_RUSSIAN }, /* Russian phonetic */ { "rus_nodeadkeys", KBD_RUSSIAN }, /* Russian phonetic, eliminate dead keys */ { "smi", KBD_SWEDISH_WITH_SAMI }, /* Northern Saami */ { "mac", KBD_SWEDISH }, /* Macintosh */ { "svdvorak", KBD_UNITED_STATES_DVORAK }, /* Svdvorak */ { "", 0 }, }; /* Switzerland */ static const xkbVariant ch_variants[] = { { "de_nodeadkeys", KBD_SWISS_GERMAN }, /* German, eliminate dead keys */ { "de_sundeadkeys", KBD_SWISS_GERMAN }, /* German, Sun dead keys */ { "fr", KBD_SWISS_FRENCH }, /* French */ { "fr_nodeadkeys", KBD_SWISS_FRENCH }, /* French, eliminate dead keys */ { "fr_sundeadkeys", KBD_SWISS_FRENCH }, /* French, Sun dead keys */ { "fr_mac", KBD_SWISS_FRENCH }, /* French (Macintosh) */ { "de_mac", KBD_SWISS_GERMAN }, /* German (Macintosh) */ { "", 0 }, }; /* Syria */ static const xkbVariant sy_variants[] = { { "syc", KBD_SYRIAC }, /* Syriac */ { "syc_phonetic", KBD_SYRIAC_PHONETIC }, /* Syriac phonetic */ { "ku", 0 }, /* Kurdish, Latin Q */ { "ku_f", 0 }, /* Kurdish, (F) */ { "ku_alt", 0 }, /* Kurdish, Latin Alt-Q */ { "", 0 }, }; /* Tajikistan */ static const xkbVariant tj_variants[] = { { "legacy", 0 }, /* Legacy */ { "", 0 }, }; /* Sri Lanka */ static const xkbVariant lk_variants[] = { { "tam_unicode", KBD_TAMIL }, /* Tamil Unicode */ { "tam_TAB", KBD_TAMIL }, /* Tamil TAB Typewriter */ { "", 0 }, }; /* Thailand */ static const xkbVariant th_variants[] = { { "tis", KBD_THAI_KEDMANEE_NON_SHIFTLOCK }, /* TIS-820.2538 */ { "pat", KBD_THAI_PATTACHOTE }, /* Pattachote */ { "", 0 }, }; /* Turkey */ static const xkbVariant tr_variants[] = { { "f", KBD_TURKISH_F }, /* (F) */ { "alt", KBD_TURKISH_Q }, /* Alt-Q */ { "sundeadkeys", KBD_TURKISH_F }, /* Sun dead keys */ { "ku", 0 }, /* Kurdish, Latin Q */ { "ku_f", 0 }, /* Kurdish, (F) */ { "ku_alt", 0 }, /* Kurdish, Latin Alt-Q */ { "intl", KBD_TURKISH_F }, /* International (with dead keys) */ { "crh", KBD_TATAR }, /* Crimean Tatar (Turkish Q) */ { "crh_f", KBD_TURKISH_F }, /* Crimean Tatar (Turkish F) */ { "crh_alt", KBD_TURKISH_Q }, /* Crimean Tatar (Turkish Alt-Q) */ { "", 0 }, }; /* Ukraine */ static const xkbVariant ua_variants[] = { { "phonetic", KBD_UKRAINIAN }, /* Phonetic */ { "typewriter", KBD_UKRAINIAN }, /* Typewriter */ { "winkeys", KBD_UKRAINIAN }, /* Winkeys */ { "legacy", KBD_UKRAINIAN }, /* Legacy */ { "rstu", KBD_UKRAINIAN }, /* Standard RSTU */ { "rstu_ru", KBD_UKRAINIAN }, /* Standard RSTU on Russian layout */ { "homophonic", KBD_UKRAINIAN }, /* Homophonic */ { "crh", KBD_TATAR }, /* Crimean Tatar (Turkish Q) */ { "crh_f", KBD_TURKISH_F }, /* Crimean Tatar (Turkish F) */ { "crh_alt", KBD_TURKISH_Q }, /* Crimean Tatar (Turkish Alt-Q) */ { "", 0 }, }; /* United Kingdom */ static const xkbVariant gb_variants[] = { { "extd", KBD_UNITED_KINGDOM_EXTENDED }, /* Extended - Winkeys */ { "intl", KBD_UNITED_KINGDOM_EXTENDED }, /* International (with dead keys) */ { "dvorak", KBD_UNITED_STATES_DVORAK }, /* Dvorak */ { "dvorakukp", KBD_UNITED_STATES_DVORAK }, /* Dvorak (UK Punctuation) */ { "mac", KBD_UNITED_KINGDOM }, /* Macintosh */ { "colemak", 0 }, /* Colemak */ { "", 0 }, }; /* Uzbekistan */ static const xkbVariant uz_variants[] = { { "latin", 0 }, /* Latin */ { "crh", KBD_TATAR }, /* Crimean Tatar (Turkish Q) */ { "crh_f", KBD_TURKISH_F }, /* Crimean Tatar (Turkish F) */ { "crh_alt", KBD_TURKISH_Q }, /* Crimean Tatar (Turkish Alt-Q) */ { "", 0 }, }; /* Korea, Republic of */ static const xkbVariant kr_variants[] = { { "kr104", KBD_KOREAN_INPUT_SYSTEM_IME_2000 }, /* 101/104 key Compatible */ { "", 0 }, }; /* Ireland */ static const xkbVariant ie_variants[] = { { "CloGaelach", KBD_GAELIC }, /* CloGaelach */ { "UnicodeExpert", KBD_GAELIC }, /* UnicodeExpert */ { "ogam", KBD_GAELIC }, /* Ogham */ { "ogam_is434", KBD_GAELIC }, /* Ogham IS434 */ { "", 0 }, }; /* Pakistan */ static const xkbVariant pk_variants[] = { { "urd-crulp", 0 }, /* CRULP */ { "urd-nla", 0 }, /* NLA */ { "ara", KBD_ARABIC_101 }, /* Arabic */ { "", 0 }, }; /* Esperanto */ static const xkbVariant epo_variants[] = { { "legacy", 0 }, /* displaced semicolon and quote (obsolete) */ { "", 0 }, }; /* Nigeria */ static const xkbVariant ng_variants[] = { { "igbo", 0 }, /* Igbo */ { "yoruba", 0 }, /* Yoruba */ { "hausa", 0 }, /* Hausa */ { "", 0 }, }; /* Braille */ static const xkbVariant brai_variants[] = { { "left_hand", 0 }, /* Left hand */ { "right_hand", 0 }, /* Right hand */ { "", 0 }, }; /* Turkmenistan */ static const xkbVariant tm_variants[] = { { "alt", KBD_TURKISH_Q }, /* Alt-Q */ { "", 0 }, }; static const xkbLayout xkbLayouts[] = { { "us", KBD_US, us_variants }, /* USA */ { "ad", 0, NULL }, /* Andorra */ { "af", KBD_FARSI, af_variants }, /* Afghanistan */ { "ara", KBD_ARABIC_101, ara_variants }, /* Arabic */ { "al", 0, NULL }, /* Albania */ { "am", KBD_ARMENIAN_EASTERN, am_variants }, /* Armenia */ { "az", KBD_AZERI_CYRILLIC, az_variants }, /* Azerbaijan */ { "by", KBD_BELARUSIAN, by_variants }, /* Belarus */ { "be", KBD_BELGIAN_FRENCH, be_variants }, /* Belgium */ { "bd", KBD_BENGALI, bd_variants }, /* Bangladesh */ { "in", KBD_HINDI_TRADITIONAL, in_variants }, /* India */ { "ba", KBD_CROATIAN, ba_variants }, /* Bosnia and Herzegovina */ { "br", KBD_PORTUGUESE_BRAZILIAN_ABNT, br_variants }, /* Brazil */ { "bg", KBD_BULGARIAN_LATIN, bg_variants }, /* Bulgaria */ { "ma", KBD_FRENCH, ma_variants }, /* Morocco */ { "mm", 0, NULL }, /* Myanmar */ { "ca", KBD_US, ca_variants }, /* Canada */ { "cd", 0, NULL }, /* Congo, Democratic Republic of the */ { "cn", KBD_CHINESE_TRADITIONAL_PHONETIC, cn_variants }, /* China */ { "hr", KBD_CROATIAN, hr_variants }, /* Croatia */ { "cz", KBD_CZECH, cz_variants }, /* Czechia */ { "dk", KBD_DANISH, dk_variants }, /* Denmark */ { "nl", KBD_DUTCH, nl_variants }, /* Netherlands */ { "bt", 0, NULL }, /* Bhutan */ { "ee", KBD_ESTONIAN, ee_variants }, /* Estonia */ { "ir", 0, ir_variants }, /* Iran */ { "iq", 0, iq_variants }, /* Iraq */ { "fo", 0, fo_variants }, /* Faroe Islands */ { "fi", KBD_FINNISH, fi_variants }, /* Finland */ { "fr", KBD_FRENCH, fr_variants }, /* France */ { "gh", 0, gh_variants }, /* Ghana */ { "gn", 0, NULL }, /* Guinea */ { "ge", KBD_GEORGIAN, ge_variants }, /* Georgia */ { "de", KBD_GERMAN, de_variants }, /* Germany */ { "gr", KBD_GREEK, gr_variants }, /* Greece */ { "hu", KBD_HUNGARIAN, hu_variants }, /* Hungary */ { "is", KBD_ICELANDIC, is_variants }, /* Iceland */ { "il", KBD_HEBREW, il_variants }, /* Israel */ { "it", KBD_ITALIAN, it_variants }, /* Italy */ { "jp", KBD_JAPANESE_INPUT_SYSTEM_MS_IME2002, jp_variants }, /* Japan */ { "kg", 0, kg_variants }, /* Kyrgyzstan */ { "kh", 0, NULL }, /* Cambodia */ { "kz", KBD_KAZAKH, kz_variants }, /* Kazakhstan */ { "la", 0, NULL }, /* Laos */ { "latam", KBD_LATIN_AMERICAN, latam_variants }, /* Latin America */ { "lt", KBD_LITHUANIAN, lt_variants }, /* Lithuania */ { "lv", KBD_LATVIAN, lv_variants }, /* Latvia */ { "mao", KBD_MAORI, NULL }, /* Maori */ { "me", KBD_SERBIAN_LATIN, me_variants }, /* Montenegro */ { "mk", KBD_FYRO_MACEDONIAN, mk_variants }, /* Macedonia */ { "mt", KBD_MALTESE_48_KEY, mt_variants }, /* Malta */ { "mn", KBD_MONGOLIAN_CYRILLIC, NULL }, /* Mongolia */ { "no", KBD_NORWEGIAN, no_variants }, /* Norway */ { "pl", KBD_POLISH_214, pl_variants }, /* Poland */ { "pt", KBD_PORTUGUESE, pt_variants }, /* Portugal */ { "ro", KBD_ROMANIAN, ro_variants }, /* Romania */ { "ru", KBD_RUSSIAN, ru_variants }, /* Russia */ { "rs", KBD_SERBIAN_LATIN, rs_variants }, /* Serbia */ { "si", KBD_SLOVENIAN, si_variants }, /* Slovenia */ { "sk", KBD_SLOVAK, sk_variants }, /* Slovakia */ { "es", KBD_SPANISH, es_variants }, /* Spain */ { "se", KBD_SWEDISH, se_variants }, /* Sweden */ { "ch", KBD_SWISS_FRENCH, ch_variants }, /* Switzerland */ { "sy", KBD_SYRIAC, sy_variants }, /* Syria */ { "tj", 0, tj_variants }, /* Tajikistan */ { "lk", 0, lk_variants }, /* Sri Lanka */ { "th", KBD_THAI_KEDMANEE, th_variants }, /* Thailand */ { "tr", KBD_TURKISH_Q, tr_variants }, /* Turkey */ { "ua", KBD_UKRAINIAN, ua_variants }, /* Ukraine */ { "gb", KBD_UNITED_KINGDOM, gb_variants }, /* United Kingdom */ { "uz", KBD_UZBEK_CYRILLIC, uz_variants }, /* Uzbekistan */ { "vn", KBD_VIETNAMESE, NULL }, /* Vietnam */ { "kr", KBD_KOREAN_INPUT_SYSTEM_IME_2000, kr_variants }, /* Korea, Republic of */ { "ie", KBD_UNITED_KINGDOM, ie_variants }, /* Ireland */ { "pk", 0, pk_variants }, /* Pakistan */ { "mv", 0, NULL }, /* Maldives */ { "za", 0, NULL }, /* South Africa */ { "epo", 0, epo_variants }, /* Esperanto */ { "np", KBD_NEPALI, NULL }, /* Nepal */ { "ng", 0, ng_variants }, /* Nigeria */ { "et", 0, NULL }, /* Ethiopia */ { "sn", 0, NULL }, /* Senegal */ { "brai", 0, brai_variants }, /* Braille */ { "tm", KBD_TURKISH_Q, tm_variants }, /* Turkmenistan */ }; /* OpenSolaris 2008.11 and 2009.06 keyboard layouts * * While OpenSolaris comes with Xorg and XKB, it maintains a set of keyboard layout * names that map directly to a particular keyboard layout in XKB. Fortunately for us, * this way of doing things comes from Solaris, which is XKB unaware. The same keyboard * layout naming system is used in Solaris, so we can use the same XKB configuration as * we would on OpenSolaris and get an accurate keyboard layout detection :) * * We can check for the current keyboard layout using the "kbd -l" command: * * type=6 * layout=33 (0x21) * delay(ms)=500 * rate(ms)=40 * * We can check at runtime if the kbd utility is present, parse the output, and use the * keyboard layout indicated by the index given (in this case, 33, or US-English). */ typedef struct _SunOSKeyboard { /* Sun keyboard type */ int type; /* Layout */ int layout; /* XKB keyboard */ char* xkbType; /* XKB keyboard layout */ unsigned int keyboardLayoutID; } SunOSKeyboard; static const SunOSKeyboard SunOSKeyboards[] = { { 4, 0, "sun(type4)", KBD_US }, /* US4 */ { 4, 1, "sun(type4)", KBD_US }, /* US4 */ { 4, 2, "sun(type4tuv)", KBD_FRENCH }, /* FranceBelg4 */ { 4, 3, "sun(type4_ca)", KBD_US }, /* Canada4 */ { 4, 4, "sun(type4tuv)", KBD_DANISH }, /* Denmark4 */ { 4, 5, "sun(type4tuv)", KBD_GERMAN }, /* Germany4 */ { 4, 6, "sun(type4tuv)", KBD_ITALIAN }, /* Italy4 */ { 4, 7, "sun(type4tuv)", KBD_DUTCH }, /* Netherland4 */ { 4, 8, "sun(type4tuv)", KBD_NORWEGIAN }, /* Norway4 */ { 4, 9, "sun(type4tuv)", KBD_PORTUGUESE }, /* Portugal4 */ { 4, 10, "sun(type4tuv)", KBD_SPANISH }, /* SpainLatAm4 */ { 4, 11, "sun(type4tuv)", KBD_SWEDISH }, /* SwedenFin4 */ { 4, 12, "sun(type4tuv)", KBD_SWISS_FRENCH }, /* Switzer_Fr4 */ { 4, 13, "sun(type4tuv)", KBD_SWISS_GERMAN }, /* Switzer_Ge4 */ { 4, 14, "sun(type4tuv)", KBD_UNITED_KINGDOM }, /* UK4 */ { 4, 16, "sun(type4)", KBD_KOREAN_INPUT_SYSTEM_IME_2000 }, /* Korea4 */ { 4, 17, "sun(type4)", KBD_CHINESE_TRADITIONAL_PHONETIC }, /* Taiwan4 */ { 4, 32, "sun(type4jp)", KBD_JAPANESE_INPUT_SYSTEM_MS_IME2002 }, /* Japan4 */ { 4, 19, "sun(type5)", KBD_US }, /* US101A_PC */ { 4, 33, "sun(type5)", KBD_US }, /* US5 */ { 4, 34, "sun(type5unix)", KBD_US }, /* US_UNIX5 */ { 4, 35, "sun(type5tuv)", KBD_FRENCH }, /* France5 */ { 4, 36, "sun(type5tuv)", KBD_DANISH }, /* Denmark5 */ { 4, 37, "sun(type5tuv)", KBD_GERMAN }, /* Germany5 */ { 4, 38, "sun(type5tuv)", KBD_ITALIAN }, /* Italy5 */ { 4, 39, "sun(type5tuv)", KBD_DUTCH }, /* Netherland5 */ { 4, 40, "sun(type5tuv)", KBD_NORWEGIAN }, /* Norway5 */ { 4, 41, "sun(type5tuv)", KBD_PORTUGUESE }, /* Portugal5 */ { 4, 42, "sun(type5tuv)", KBD_SPANISH }, /* Spain5 */ { 4, 43, "sun(type5tuv)", KBD_SWEDISH }, /* Sweden5 */ { 4, 44, "sun(type5tuv)", KBD_SWISS_FRENCH }, /* Switzer_Fr5 */ { 4, 45, "sun(type5tuv)", KBD_SWISS_GERMAN }, /* Switzer_Ge5 */ { 4, 46, "sun(type5tuv)", KBD_UNITED_KINGDOM }, /* UK5 */ { 4, 47, "sun(type5)", KBD_KOREAN_INPUT_SYSTEM_IME_2000 }, /* Korea5 */ { 4, 48, "sun(type5)", KBD_CHINESE_TRADITIONAL_PHONETIC }, /* Taiwan5 */ { 4, 49, "sun(type5jp)", KBD_JAPANESE_INPUT_SYSTEM_MS_IME2002 }, /* Japan5 */ { 4, 50, "sun(type5tuv)", KBD_CANADIAN_FRENCH }, /* Canada_Fr5 */ { 4, 51, "sun(type5tuv)", KBD_HUNGARIAN }, /* Hungary5 */ { 4, 52, "sun(type5tuv)", KBD_POLISH_214 }, /* Poland5 */ { 4, 53, "sun(type5tuv)", KBD_CZECH }, /* Czech5 */ { 4, 54, "sun(type5tuv)", KBD_RUSSIAN }, /* Russia5 */ { 4, 55, "sun(type5tuv)", KBD_LATVIAN }, /* Latvia5 */ { 4, 57, "sun(type5tuv)", KBD_GREEK }, /* Greece5 */ { 4, 59, "sun(type5tuv)", KBD_LITHUANIAN }, /* Lithuania5 */ { 4, 63, "sun(type5tuv)", KBD_CANADIAN_FRENCH }, /* Canada_Fr5_TBITS5 */ { 4, 56, "sun(type5tuv)", KBD_TURKISH_Q }, /* TurkeyQ5 */ { 4, 58, "sun(type5tuv)", KBD_ARABIC_101 }, /* Arabic5 */ { 4, 60, "sun(type5tuv)", KBD_BELGIAN_FRENCH }, /* Belgian5 */ { 4, 62, "sun(type5tuv)", KBD_TURKISH_F }, /* TurkeyF5 */ { 4, 80, "sun(type5hobo)", KBD_US }, /* US5_Hobo */ { 4, 81, "sun(type5hobo)", KBD_US }, /* US_UNIX5_Hobo */ { 4, 82, "sun(type5tuvhobo)", KBD_FRENCH }, /* France5_Hobo */ { 4, 83, "sun(type5tuvhobo)", KBD_DANISH }, /* Denmark5_Hobo */ { 4, 84, "sun(type5tuvhobo)", KBD_GERMAN }, /* Germany5_Hobo */ { 4, 85, "sun(type5tuvhobo)", KBD_ITALIAN }, /* Italy5_Hobo */ { 4, 86, "sun(type5tuvhobo)", KBD_DUTCH }, /* Netherland5_Hobo */ { 4, 87, "sun(type5tuvhobo)", KBD_NORWEGIAN }, /* Norway5_Hobo */ { 4, 88, "sun(type5tuvhobo)", KBD_PORTUGUESE }, /* Portugal5_Hobo */ { 4, 89, "sun(type5tuvhobo)", KBD_SPANISH }, /* Spain5_Hobo */ { 4, 90, "sun(type5tuvhobo)", KBD_SWEDISH }, /* Sweden5_Hobo */ { 4, 91, "sun(type5tuvhobo)", KBD_SWISS_FRENCH }, /* Switzer_Fr5_Hobo */ { 4, 92, "sun(type5tuvhobo)", KBD_SWISS_GERMAN }, /* Switzer_Ge5_Hobo */ { 4, 93, "sun(type5tuvhobo)", KBD_UNITED_KINGDOM }, /* UK5_Hobo */ { 4, 94, "sun(type5hobo)", KBD_KOREAN_INPUT_SYSTEM_IME_2000 }, /* Korea5_Hobo */ { 4, 95, "sun(type5hobo)", KBD_CHINESE_TRADITIONAL_PHONETIC }, /* Taiwan5_Hobo */ { 4, 96, "sun(type5jphobo)", KBD_JAPANESE_INPUT_SYSTEM_MS_IME2002 }, /* Japan5_Hobo */ { 4, 97, "sun(type5tuvhobo)", KBD_CANADIAN_FRENCH }, /* Canada_Fr5_Hobo */ { 101, 1, "digital_vndr/pc(pc104)", KBD_US }, /* US101A_x86 */ { 101, 34, "digital_vndr/pc(pc104)", KBD_US }, /* J3100_x86 */ { 101, 35, "digital_vndr/pc(pc104)", KBD_FRENCH }, /* France_x86 */ { 101, 36, "digital_vndr/pc(pc104)", KBD_DANISH }, /* Denmark_x86 */ { 101, 37, "digital_vndr/pc(pc104)", KBD_GERMAN }, /* Germany_x86 */ { 101, 38, "digital_vndr/pc(pc104)", KBD_ITALIAN }, /* Italy_x86 */ { 101, 39, "digital_vndr/pc(pc104)", KBD_DUTCH }, /* Netherland_x86 */ { 101, 40, "digital_vndr/pc(pc104)", KBD_NORWEGIAN }, /* Norway_x86 */ { 101, 41, "digital_vndr/pc(pc104)", KBD_PORTUGUESE }, /* Portugal_x86 */ { 101, 42, "digital_vndr/pc(pc104)", KBD_SPANISH }, /* Spain_x86 */ { 101, 43, "digital_vndr/pc(pc104)", KBD_SWEDISH }, /* Sweden_x86 */ { 101, 44, "digital_vndr/pc(pc104)", KBD_SWISS_FRENCH }, /* Switzer_Fr_x86 */ { 101, 45, "digital_vndr/pc(pc104)", KBD_SWISS_GERMAN }, /* Switzer_Ge_x86 */ { 101, 46, "digital_vndr/pc(pc104)", KBD_UNITED_KINGDOM }, /* UK_x86 */ { 101, 47, "digital_vndr/pc(pc104)", KBD_KOREAN_INPUT_SYSTEM_IME_2000 }, /* Korea_x86 */ { 101, 48, "digital_vndr/pc(pc104)", KBD_CHINESE_TRADITIONAL_PHONETIC }, /* Taiwan_x86 */ { 101, 49, "digital_vndr/pc(lk411jj)", KBD_JAPANESE_INPUT_SYSTEM_MS_IME2002 }, /* Japan_x86 */ { 101, 50, "digital_vndr/pc(pc104)", KBD_CANADIAN_FRENCH }, /* Canada_Fr2_x86 */ { 101, 51, "digital_vndr/pc(pc104)", KBD_HUNGARIAN }, /* Hungary_x86 */ { 101, 52, "digital_vndr/pc(pc104)", KBD_POLISH_214 }, /* Poland_x86 */ { 101, 53, "digital_vndr/pc(pc104)", KBD_CZECH }, /* Czech_x86 */ { 101, 54, "digital_vndr/pc(pc104)", KBD_RUSSIAN }, /* Russia_x86 */ { 101, 55, "digital_vndr/pc(pc104)", KBD_LATVIAN }, /* Latvia_x86 */ { 101, 56, "digital_vndr/pc(pc104)", KBD_TURKISH_Q }, /* Turkey_x86 */ { 101, 57, "digital_vndr/pc(pc104)", KBD_GREEK }, /* Greece_x86 */ { 101, 59, "digital_vndr/pc(pc104)", KBD_LITHUANIAN }, /* Lithuania_x86 */ { 101, 1001, "digital_vndr/pc(pc104)", KBD_US }, /* MS_US101A_x86 */ { 6, 6, "sun(type6tuv)", KBD_DANISH }, /* Denmark6_usb */ { 6, 7, "sun(type6tuv)", KBD_FINNISH }, /* Finnish6_usb */ { 6, 8, "sun(type6tuv)", KBD_FRENCH }, /* France6_usb */ { 6, 9, "sun(type6tuv)", KBD_GERMAN }, /* Germany6_usb */ { 6, 14, "sun(type6tuv)", KBD_ITALIAN }, /* Italy6_usb */ { 6, 15, "sun(type6jp)", KBD_JAPANESE_INPUT_SYSTEM_MS_IME2002 }, /* Japan7_usb */ { 6, 16, "sun(type6)", KBD_KOREAN_INPUT_SYSTEM_IME_2000 }, /* Korea6_usb */ { 6, 18, "sun(type6tuv)", KBD_DUTCH }, /* Netherland6_usb */ { 6, 19, "sun(type6tuv)", KBD_NORWEGIAN }, /* Norway6_usb */ { 6, 22, "sun(type6tuv)", KBD_PORTUGUESE }, /* Portugal6_usb */ { 6, 23, "sun(type6tuv)", KBD_RUSSIAN }, /* Russia6_usb */ { 6, 25, "sun(type6tuv)", KBD_SPANISH }, /* Spain6_usb */ { 6, 26, "sun(type6tuv)", KBD_SWEDISH }, /* Sweden6_usb */ { 6, 27, "sun(type6tuv)", KBD_SWISS_FRENCH }, /* Switzer_Fr6_usb */ { 6, 28, "sun(type6tuv)", KBD_SWISS_GERMAN }, /* Switzer_Ge6_usb */ { 6, 30, "sun(type6)", KBD_CHINESE_TRADITIONAL_PHONETIC }, /* Taiwan6_usb */ { 6, 32, "sun(type6tuv)", KBD_UNITED_KINGDOM }, /* UK6_usb */ { 6, 33, "sun(type6)", KBD_US }, /* US6_usb */ { 6, 1, "sun(type6tuv)", KBD_ARABIC_101 }, /* Arabic6_usb */ { 6, 2, "sun(type6tuv)", KBD_BELGIAN_FRENCH }, /* Belgian6_usb */ { 6, 31, "sun(type6tuv)", KBD_TURKISH_Q }, /* TurkeyQ6_usb */ { 6, 35, "sun(type6tuv)", KBD_TURKISH_F }, /* TurkeyF6_usb */ { 6, 271, "sun(type6jp)", KBD_JAPANESE_INPUT_SYSTEM_MS_IME2002 }, /* Japan6_usb */ { 6, 264, "sun(type6tuv)", KBD_ALBANIAN }, /* Albanian6_usb */ { 6, 261, "sun(type6tuv)", KBD_BELARUSIAN }, /* Belarusian6_usb */ { 6, 260, "sun(type6tuv)", KBD_BULGARIAN }, /* Bulgarian6_usb */ { 6, 259, "sun(type6tuv)", KBD_CROATIAN }, /* Croatian6_usb */ { 6, 5, "sun(type6tuv)", KBD_CZECH }, /* Czech6_usb */ { 6, 4, "sun(type6tuv)", KBD_CANADIAN_FRENCH }, /* French-Canadian6_usb */ { 6, 12, "sun(type6tuv)", KBD_HUNGARIAN }, /* Hungarian6_usb */ { 6, 10, "sun(type6tuv)", KBD_GREEK }, /* Greek6_usb */ { 6, 17, "sun(type6)", KBD_LATIN_AMERICAN }, /* Latin-American6_usb */ { 6, 265, "sun(type6tuv)", KBD_LITHUANIAN }, /* Lithuanian6_usb */ { 6, 266, "sun(type6tuv)", KBD_LATVIAN }, /* Latvian6_usb */ { 6, 267, "sun(type6tuv)", KBD_FYRO_MACEDONIAN }, /* Macedonian6_usb */ { 6, 263, "sun(type6tuv)", KBD_MALTESE_47_KEY }, /* Malta_UK6_usb */ { 6, 262, "sun(type6tuv)", KBD_MALTESE_48_KEY }, /* Malta_US6_usb */ { 6, 21, "sun(type6tuv)", KBD_POLISH_214 }, /* Polish6_usb */ { 6, 257, "sun(type6tuv)", KBD_SERBIAN_LATIN }, /* Serbia-And-Montenegro6_usb */ { 6, 256, "sun(type6tuv)", KBD_SLOVENIAN }, /* Slovenian6_usb */ { 6, 24, "sun(type6tuv)", KBD_SLOVAK }, /* Slovakian6_usb */ { 6, 3, "sun(type6)", KBD_CANADIAN_MULTILINGUAL_STANDARD }, /* Canada_Bi6_usb */ { 6, 272, "sun(type6)", KBD_PORTUGUESE_BRAZILIAN_ABNT } /* Brazil6_usb */ }; unsigned int find_keyboard_layout_in_xorg_rules(char* layout, char* variant) { int i; int j; if ((layout == NULL) || (variant == NULL)) return 0; DEBUG_KBD("xkbLayout: %s\txkbVariant: %s\n", layout, variant); for (i = 0; i < sizeof(xkbLayouts) / sizeof(xkbLayout); i++) { if (strcmp(xkbLayouts[i].layout, layout) == 0) { for (j = 0; xkbLayouts[i].variants[j].variant != NULL && strlen(xkbLayouts[i].variants[j].variant) > 0; j++) { if (strcmp(xkbLayouts[i].variants[j].variant, variant) == 0) { return xkbLayouts[i].variants[j].keyboardLayoutID; } } return xkbLayouts[i].keyboardLayoutID; } } return 0; } #if defined(sun) unsigned int detect_keyboard_type_and_layout_sunos(char* xkbfile, int length) { FILE* kbd; int i; int type = 0; int layout = 0; char* pch; char* beg; char* end; char buffer[1024]; /* Sample output for "kbd -t -l" : USB keyboard type=6 layout=3 (0x03) delay(ms)=500 rate(ms)=40 */ kbd = popen("kbd -t -l", "r"); if (kbd < 0) return 0; while(fgets(buffer, sizeof(buffer), kbd) != NULL) { if((pch = strstr(buffer, "type=")) != NULL) { beg = pch + sizeof("type=") - 1; end = strchr(beg, '\n'); end[0] = '\0'; type = atoi(beg); } else if((pch = strstr(buffer, "layout=")) != NULL) { beg = pch + sizeof("layout=") - 1; end = strchr(beg, ' '); end[0] = '\0'; layout = atoi(beg); } } pclose(kbd); for(i = 0; i < sizeof(SunOSKeyboards) / sizeof(SunOSKeyboard); i++) { if(SunOSKeyboards[i].type == type) { if(SunOSKeyboards[i].layout == layout) { strncpy(xkbfile, SunOSKeyboards[i].xkbType, length); return SunOSKeyboards[i].keyboardLayoutID; } } } return 0; } #endif FreeRDP-1.0.2/libfreerdp-kbd/x_layout_id_table.h000066400000000000000000000020341207112532300214500ustar00rootroot00000000000000/** * FreeRDP: A Remote Desktop Protocol Client * XKB-based Keyboard Mapping to Microsoft Keyboard System * * Copyright 2009 Marc-Andre Moreau * * 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. */ /* Hardcoded mapping from xkb layout names and variants to RDP layout ids */ #ifndef __LAYOUTS_X_H #define __LAYOUTS_X_H unsigned int find_keyboard_layout_in_xorg_rules(char* layout, char* variant); #if defined(sun) unsigned int detect_keyboard_type_and_layout_sunos(char* xkbfile, int length); #endif #endif FreeRDP-1.0.2/libfreerdp-rail/000077500000000000000000000000001207112532300160005ustar00rootroot00000000000000FreeRDP-1.0.2/libfreerdp-rail/CMakeLists.txt000066400000000000000000000022111207112532300205340ustar00rootroot00000000000000# FreeRDP: A Remote Desktop Protocol Client # libfreerdp-rail cmake build script # # Copyright 2011 O.S. Systems Software Ltda. # Copyright 2011 Otavio Salvador # Copyright 2011 Marc-Andre Moreau # # 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(FREERDP_RAIL_SRCS window_list.c window.c icon.c rail.c librail.h) add_library(freerdp-rail ${FREERDP_RAIL_SRCS}) set_target_properties(freerdp-rail PROPERTIES VERSION ${FREERDP_VERSION_FULL} SOVERSION ${FREERDP_VERSION} PREFIX "lib") target_link_libraries(freerdp-rail freerdp-utils) install(TARGETS freerdp-rail DESTINATION ${CMAKE_INSTALL_LIBDIR}) FreeRDP-1.0.2/libfreerdp-rail/icon.c000066400000000000000000000050371207112532300171010ustar00rootroot00000000000000/** * FreeRDP: A Remote Desktop Protocol Client * Window Icon Cache * * Copyright 2011 Marc-Andre Moreau * * 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. */ #include #include #include #include #include ICON_INFO* icon_cache_get(rdpIconCache* cache, uint8 id, uint16 index, void** extra) { ICON_INFO* entry; if (id >= cache->numCaches) { printf("invalid window icon cache id:%d\n", id); return (ICON_INFO*) NULL; } if (index >= cache->numCacheEntries) { printf("invalid window icon cache index:%d in cache id:%d\n", index, id); return (ICON_INFO*) NULL; } entry = cache->caches[id].entries[index].entry; if (extra != NULL) *extra = cache->caches[id].entries[index].extra; return entry; } void icon_cache_put(rdpIconCache* cache, uint8 id, uint16 index, ICON_INFO* entry, void* extra) { if (id >= cache->numCaches) { printf("invalid window icon cache id:%d\n", id); return; } if (index >= cache->numCacheEntries) { printf("invalid window icon cache index:%d in cache id:%d\n", index, id); return; } cache->caches[id].entries[index].entry = entry; if (extra != NULL) cache->caches[id].entries[index].extra = extra; } rdpIconCache* icon_cache_new(rdpRail* rail) { rdpIconCache* cache; cache = (rdpIconCache*) xzalloc(sizeof(rdpIconCache)); if (cache != NULL) { int i; cache->rail = rail; cache->numCaches = (uint8) rail->settings->num_icon_cache_entries; cache->numCacheEntries = rail->settings->num_icon_cache_entries; cache->caches = xzalloc(cache->numCaches * sizeof(WINDOW_ICON_CACHE)); for (i = 0; i < cache->numCaches; i++) { cache->caches[i].entries = xzalloc(cache->numCacheEntries * sizeof(rdpIconCache)); } } return cache; } void icon_cache_free(rdpIconCache* cache) { if (cache != NULL) { int i; for (i = 0; i < cache->numCaches; i++) { xfree(cache->caches[i].entries); } xfree(cache->caches); xfree(cache); } } FreeRDP-1.0.2/libfreerdp-rail/librail.h000066400000000000000000000017431207112532300175740ustar00rootroot00000000000000/** * FreeRDP: A Remote Desktop Protocol Client * Remote Applications Integrated Locally (RAIL) * * Copyright 2011 Marc-Andre Moreau * * 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. */ #ifndef __LIBRAIL_H #define __LIBRAIL_H #include #ifdef WITH_DEBUG_RAIL #define DEBUG_RAIL(fmt, ...) DEBUG_CLASS(RAIL, fmt, ## __VA_ARGS__) #else #define DEBUG_RAIL(fmt, ...) DEBUG_NULL(fmt, ## __VA_ARGS__) #endif #endif /* __LIBRAIL_H */ FreeRDP-1.0.2/libfreerdp-rail/rail.c000066400000000000000000000102521207112532300170730ustar00rootroot00000000000000/** * FreeRDP: A Remote Desktop Protocol Client * Remote Applications Integrated Locally (RAIL) * * Copyright 2011 Marc-Andre Moreau * * 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. */ #include #include #include "librail.h" #include #include static void rail_WindowCreate(rdpContext* context, WINDOW_ORDER_INFO* orderInfo, WINDOW_STATE_ORDER* window_state) { rdpRail* rail = context->rail; window_list_create(rail->list, orderInfo, window_state); } static void rail_WindowUpdate(rdpContext* context, WINDOW_ORDER_INFO* orderInfo, WINDOW_STATE_ORDER* window_state) { rdpRail* rail = context->rail; window_list_update(rail->list, orderInfo, window_state); } static void rail_WindowDelete(rdpContext* context, WINDOW_ORDER_INFO* orderInfo) { rdpRail* rail = context->rail; window_list_delete(rail->list, orderInfo); } static void rail_WindowIcon(rdpContext* context, WINDOW_ORDER_INFO* orderInfo, WINDOW_ICON_ORDER* window_icon) { rdpIcon* icon; rdpWindow* window; rdpRail* rail = context->rail; if (window_icon->iconInfo->cacheEntry != 0xFFFF) { /* cache icon */ } window = window_list_get_by_id(rail->list, orderInfo->windowId); icon = (rdpIcon*) xzalloc(sizeof(rdpIcon)); icon->entry = window_icon->iconInfo; icon->big = (orderInfo->fieldFlags & WINDOW_ORDER_FIELD_ICON_BIG) ? true : false; DEBUG_RAIL("Window Icon: %dx%d@%dbpp cbBitsColor:%d cbBitsMask:%d cbColorTable:%d", window_icon->iconInfo->width, window_icon->iconInfo->height, window_icon->iconInfo->bpp, window_icon->iconInfo->cbBitsColor, window_icon->iconInfo->cbBitsMask, window_icon->iconInfo->cbColorTable); if (icon->big) window->bigIcon = icon; else window->smallIcon = icon; IFCALL(rail->rail_SetWindowIcon, rail, window, icon); } static void rail_WindowCachedIcon(rdpContext* context, WINDOW_ORDER_INFO* orderInfo, WINDOW_CACHED_ICON_ORDER* window_cached_icon) { } static void rail_NotifyIconCreate(rdpContext* context, WINDOW_ORDER_INFO* orderInfo, NOTIFY_ICON_STATE_ORDER* notify_icon_state) { } static void rail_NotifyIconUpdate(rdpContext* context, WINDOW_ORDER_INFO* orderInfo, NOTIFY_ICON_STATE_ORDER* notify_icon_state) { } static void rail_NotifyIconDelete(rdpContext* context, WINDOW_ORDER_INFO* orderInfo) { } static void rail_MonitoredDesktop(rdpContext* context, WINDOW_ORDER_INFO* orderInfo, MONITORED_DESKTOP_ORDER* monitored_desktop) { } static void rail_NonMonitoredDesktop(rdpContext* context, WINDOW_ORDER_INFO* orderInfo) { } void rail_register_update_callbacks(rdpRail* rail, rdpUpdate* update) { rdpWindowUpdate* window = update->window; window->WindowCreate = rail_WindowCreate; window->WindowUpdate = rail_WindowUpdate; window->WindowDelete = rail_WindowDelete; window->WindowIcon = rail_WindowIcon; window->WindowCachedIcon = rail_WindowCachedIcon; window->NotifyIconCreate = rail_NotifyIconCreate; window->NotifyIconUpdate = rail_NotifyIconUpdate; window->NotifyIconDelete = rail_NotifyIconDelete; window->MonitoredDesktop = rail_MonitoredDesktop; window->NonMonitoredDesktop = rail_NonMonitoredDesktop; } rdpRail* rail_new(rdpSettings* settings) { rdpRail* rail; rail = (rdpRail*) xzalloc(sizeof(rdpRail)); if (rail != NULL) { rail->settings = settings; rail->cache = icon_cache_new(rail); rail->list = window_list_new(rail); rail->uniconv = freerdp_uniconv_new(); rail->clrconv = (CLRCONV*) xzalloc(sizeof(CLRCONV)); } return rail; } void rail_free(rdpRail* rail) { if (rail != NULL) { icon_cache_free(rail->cache); window_list_free(rail->list); freerdp_uniconv_free(rail->uniconv); xfree(rail->clrconv); xfree(rail); } } FreeRDP-1.0.2/libfreerdp-rail/window.c000066400000000000000000000247401207112532300174620ustar00rootroot00000000000000/** * FreeRDP: A Remote Desktop Protocol Client * RAIL Windows * * Copyright 2011 Marc-Andre Moreau * * 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. */ #include #include #include #include #include "librail.h" #include struct _WINDOW_STYLE { uint32 style; const char* name; boolean multi; }; typedef struct _WINDOW_STYLE WINDOW_STYLE; static const WINDOW_STYLE WINDOW_STYLES[] = { { WS_BORDER, "WS_BORDER", false }, { WS_CAPTION, "WS_CAPTION", false }, { WS_CHILD, "WS_CHILD", false }, { WS_CLIPCHILDREN, "WS_CLIPCHILDREN", false }, { WS_CLIPSIBLINGS, "WS_CLIPSIBLINGS", false }, { WS_DISABLED, "WS_DISABLED", false }, { WS_DLGFRAME, "WS_DLGFRAME", false }, { WS_GROUP, "WS_GROUP", false }, { WS_HSCROLL, "WS_HSCROLL", false }, { WS_ICONIC, "WS_ICONIC", false }, { WS_MAXIMIZE, "WS_MAXIMIZE", false }, { WS_MAXIMIZEBOX, "WS_MAXIMIZEBOX", false }, { WS_MINIMIZE, "WS_MINIMIZE", false }, { WS_MINIMIZEBOX, "WS_MINIMIZEBOX", false }, { WS_OVERLAPPED, "WS_OVERLAPPED", false }, { WS_OVERLAPPEDWINDOW, "WS_OVERLAPPEDWINDOW", true }, { WS_POPUP, "WS_POPUP", false }, { WS_POPUPWINDOW, "WS_POPUPWINDOW", true }, { WS_SIZEBOX, "WS_SIZEBOX", false }, { WS_SYSMENU, "WS_SYSMENU", false }, { WS_TABSTOP, "WS_TABSTOP", false }, { WS_THICKFRAME, "WS_THICKFRAME", false }, { WS_VISIBLE, "WS_VISIBLE", false } }; static const WINDOW_STYLE EXTENDED_WINDOW_STYLES[] = { { WS_EX_ACCEPTFILES, "WS_EX_ACCEPTFILES", false }, { WS_EX_APPWINDOW, "WS_EX_APPWINDOW", false }, { WS_EX_CLIENTEDGE, "WS_EX_CLIENTEDGE", false }, { WS_EX_COMPOSITED, "WS_EX_COMPOSITED", false }, { WS_EX_CONTEXTHELP, "WS_EX_CONTEXTHELP", false }, { WS_EX_CONTROLPARENT, "WS_EX_CONTROLPARENT", false }, { WS_EX_DLGMODALFRAME, "WS_EX_DLGMODALFRAME", false }, { WS_EX_LAYERED, "WS_EX_LAYERED", false }, { WS_EX_LAYOUTRTL, "WS_EX_LAYOUTRTL", false }, { WS_EX_LEFT, "WS_EX_LEFT", false }, { WS_EX_LEFTSCROLLBAR, "WS_EX_LEFTSCROLLBAR", false }, { WS_EX_LTRREADING, "WS_EX_LTRREADING", false }, { WS_EX_MDICHILD, "WS_EX_MDICHILD", false }, { WS_EX_NOACTIVATE, "WS_EX_NOACTIVATE", false }, { WS_EX_NOINHERITLAYOUT, "WS_EX_NOINHERITLAYOUT", false }, { WS_EX_NOPARENTNOTIFY, "WS_EX_NOPARENTNOTIFY", false }, { WS_EX_OVERLAPPEDWINDOW, "WS_EX_OVERLAPPEDWINDOW", true }, { WS_EX_PALETTEWINDOW, "WS_EX_PALETTEWINDOW", true }, { WS_EX_RIGHT, "WS_EX_RIGHT", false }, { WS_EX_RIGHTSCROLLBAR, "WS_EX_RIGHTSCROLLBAR", false }, { WS_EX_RTLREADING, "WS_EX_RTLREADING", false }, { WS_EX_STATICEDGE, "WS_EX_STATICEDGE", false }, { WS_EX_TOOLWINDOW, "WS_EX_TOOLWINDOW", false }, { WS_EX_TOPMOST, "WS_EX_TOPMOST", false }, { WS_EX_TRANSPARENT, "WS_EX_TRANSPARENT", false }, { WS_EX_WINDOWEDGE, "WS_EX_WINDOWEDGE", false } }; void print_window_styles(uint32 style) { int i; printf("Window Styles:\n{\n"); for (i = 0; i < sizeof(WINDOW_STYLES) / sizeof(WINDOW_STYLE); i++) { if (style & WINDOW_STYLES[i].style) { if (WINDOW_STYLES[i].multi) { if ((style & WINDOW_STYLES[i].style) != WINDOW_STYLES[i].style) continue; } printf("\t%s\n", WINDOW_STYLES[i].name); } } printf("}\n"); } void print_extended_window_styles(uint32 style) { int i; printf("Extended Window Styles:\n{\n"); for (i = 0; i < sizeof(EXTENDED_WINDOW_STYLES) / sizeof(WINDOW_STYLE); i++) { if (style & EXTENDED_WINDOW_STYLES[i].style) { if (EXTENDED_WINDOW_STYLES[i].multi) { if ((style & EXTENDED_WINDOW_STYLES[i].style) != EXTENDED_WINDOW_STYLES[i].style) continue; } printf("\t%s\n", EXTENDED_WINDOW_STYLES[i].name); } } printf("}\n"); } void window_state_update(rdpWindow* window, WINDOW_ORDER_INFO* orderInfo, WINDOW_STATE_ORDER* window_state) { window->fieldFlags = orderInfo->fieldFlags; if (orderInfo->fieldFlags & WINDOW_ORDER_FIELD_OWNER) { window->ownerWindowId = window_state->ownerWindowId; DEBUG_RAIL("ownerWindowId:0x%08X", window->ownerWindowId); } DEBUG_RAIL("windowId=0x%X ownerWindowId=0x%X", window->windowId, window->ownerWindowId); if (orderInfo->fieldFlags & WINDOW_ORDER_FIELD_STYLE) { window->style = window_state->style; window->extendedStyle = window_state->extendedStyle; #ifdef WITH_DEBUG_RAIL print_window_styles(window->style); print_extended_window_styles(window->extendedStyle); #endif } if (orderInfo->fieldFlags & WINDOW_ORDER_FIELD_SHOW) { window->showState = window_state->showState; DEBUG_RAIL("ShowState:%d", window->showState); } if (orderInfo->fieldFlags & WINDOW_ORDER_FIELD_TITLE) { window->titleInfo.length = window_state->titleInfo.length; window->titleInfo.string = xmalloc(window_state->titleInfo.length); memcpy(window->titleInfo.string, window_state->titleInfo.string, window->titleInfo.length); #ifdef WITH_DEBUG_RAIL freerdp_hexdump(window->titleInfo.string, window->titleInfo.length); #endif } if (orderInfo->fieldFlags & WINDOW_ORDER_FIELD_CLIENT_AREA_OFFSET) { window->clientOffsetX = window_state->clientOffsetX; window->clientOffsetY = window_state->clientOffsetY; DEBUG_RAIL("Client Area Offset: (%d, %d)", window->clientOffsetX, window->clientOffsetY); } if (orderInfo->fieldFlags & WINDOW_ORDER_FIELD_CLIENT_AREA_SIZE) { window->clientAreaWidth = window_state->clientAreaWidth; window->clientAreaHeight = window_state->clientAreaHeight; DEBUG_RAIL("Client Area Size: (%d, %d)", window->clientAreaWidth, window->clientAreaHeight); } if (orderInfo->fieldFlags & WINDOW_ORDER_FIELD_RP_CONTENT) { window->RPContent = window_state->RPContent; } if (orderInfo->fieldFlags & WINDOW_ORDER_FIELD_ROOT_PARENT) { window->rootParentHandle = window_state->rootParentHandle; } if (orderInfo->fieldFlags & WINDOW_ORDER_FIELD_WND_OFFSET) { window->windowOffsetX = window_state->windowOffsetX; window->windowOffsetY = window_state->windowOffsetY; DEBUG_RAIL("Window Offset: (%d, %d)", window->windowOffsetX, window->windowOffsetY); } if (orderInfo->fieldFlags & WINDOW_ORDER_FIELD_WND_CLIENT_DELTA) { window->windowClientDeltaX = window_state->windowClientDeltaX; window->windowClientDeltaY = window_state->windowClientDeltaY; DEBUG_RAIL("Window Client Delta: (%d, %d)", window->windowClientDeltaX, window->windowClientDeltaY); } if (orderInfo->fieldFlags & WINDOW_ORDER_FIELD_WND_SIZE) { window->windowWidth = window_state->windowWidth; window->windowHeight = window_state->windowHeight; DEBUG_RAIL("Window Size: (%d, %d)", window->windowWidth, window->windowHeight); } if (orderInfo->fieldFlags & WINDOW_ORDER_FIELD_WND_RECTS) { int i; if (window->windowRects != NULL) xfree(window->windowRects); window->windowRects = window_state->windowRects; window->numWindowRects = window_state->numWindowRects; for (i = 0; i < (int) window_state->numWindowRects; i++) { DEBUG_RAIL("Window Rect #%d: left:%d top:%d right:%d bottom:%d", i, window_state->windowRects[i].left, window_state->windowRects[i].top, window_state->windowRects[i].right, window_state->windowRects[i].bottom); } } if (orderInfo->fieldFlags & WINDOW_ORDER_FIELD_VIS_OFFSET) { window->visibleOffsetX = window_state->visibleOffsetX; window->visibleOffsetY = window_state->visibleOffsetY; DEBUG_RAIL("Window Visible Offset: (%d, %d)", window->visibleOffsetX, window->visibleOffsetY); } if (orderInfo->fieldFlags & WINDOW_ORDER_FIELD_VISIBILITY) { int i; if (window->visibilityRects != NULL) xfree(window->visibilityRects); window->visibilityRects = window_state->visibilityRects; window->numVisibilityRects = window_state->numVisibilityRects; for (i = 0; i < (int) window_state->numVisibilityRects; i++) { DEBUG_RAIL("Visibility Rect #%d: left:%d top:%d right:%d bottom:%d", i, window_state->visibilityRects[i].left, window_state->visibilityRects[i].top, window_state->visibilityRects[i].right, window_state->visibilityRects[i].bottom); } } } void rail_CreateWindow(rdpRail* rail, rdpWindow* window) { if (window->titleInfo.length > 0) { window->title = freerdp_uniconv_in(rail->uniconv, window->titleInfo.string, window->titleInfo.length); } else { window->title = (char*) xmalloc(sizeof("RAIL")); memcpy(window->title, "RAIL", sizeof("RAIL")); } IFCALL(rail->rail_CreateWindow, rail, window); if (window->fieldFlags & WINDOW_ORDER_FIELD_WND_RECTS) { IFCALL(rail->rail_SetWindowRects, rail, window); } if (window->fieldFlags & WINDOW_ORDER_FIELD_VISIBILITY) { IFCALL(rail->rail_SetWindowVisibilityRects, rail, window); } } void rail_UpdateWindow(rdpRail* rail, rdpWindow* window) { if (window->fieldFlags & WINDOW_ORDER_FIELD_OWNER) { } if (window->fieldFlags & WINDOW_ORDER_FIELD_STYLE) { } if (window->fieldFlags & WINDOW_ORDER_FIELD_SHOW) { IFCALL(rail->rail_ShowWindow, rail, window, window->showState); } if (window->fieldFlags & WINDOW_ORDER_FIELD_TITLE) { if (window->title != NULL) xfree(window->title); window->title = freerdp_uniconv_in(rail->uniconv, window->titleInfo.string, window->titleInfo.length); IFCALL(rail->rail_SetWindowText, rail, window); } if (window->fieldFlags & WINDOW_ORDER_FIELD_CLIENT_AREA_OFFSET) { } if (window->fieldFlags & WINDOW_ORDER_FIELD_CLIENT_AREA_SIZE) { } if (window->fieldFlags & WINDOW_ORDER_FIELD_RP_CONTENT) { } if (window->fieldFlags & WINDOW_ORDER_FIELD_ROOT_PARENT) { } if ((window->fieldFlags & WINDOW_ORDER_FIELD_WND_OFFSET) || (window->fieldFlags & WINDOW_ORDER_FIELD_WND_SIZE)) { IFCALL(rail->rail_MoveWindow, rail, window); } if (window->fieldFlags & WINDOW_ORDER_FIELD_WND_CLIENT_DELTA) { } if (window->fieldFlags & WINDOW_ORDER_FIELD_WND_RECTS) { IFCALL(rail->rail_SetWindowRects, rail, window); } if (window->fieldFlags & WINDOW_ORDER_FIELD_VIS_OFFSET) { } if (window->fieldFlags & WINDOW_ORDER_FIELD_VISIBILITY) { IFCALL(rail->rail_SetWindowVisibilityRects, rail, window); } } void rail_DestroyWindow(rdpRail* rail, rdpWindow* window) { IFCALL(rail->rail_DestroyWindow, rail, window); if (window != NULL) { xfree(window); } } FreeRDP-1.0.2/libfreerdp-rail/window_list.c000066400000000000000000000071461207112532300205160ustar00rootroot00000000000000/** * FreeRDP: A Remote Desktop Protocol Client * RAIL Window List * * Copyright 2011 Marc-Andre Moreau * * 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. */ #include #include #include "librail.h" #include void window_list_rewind(rdpWindowList* list) { list->iterator = list->head; } boolean window_list_has_next(rdpWindowList* list) { if (list->iterator != NULL) { if (list->iterator != NULL) return true; } return false; } rdpWindow* window_list_get_next(rdpWindowList* list) { rdpWindow* next = NULL; if (list->iterator != NULL) { next = list->iterator; list->iterator = list->iterator->next; } return next; } rdpWindow* window_list_get_by_extra_id(rdpWindowList* list, void* extraId) { rdpWindow* window; window = list->head; if (window == NULL) return NULL; while (window != NULL) { if (window->extraId == extraId) return window; window = window->next; } return NULL; } rdpWindow* window_list_get_by_id(rdpWindowList* list, uint32 windowId) { rdpWindow* window; window = list->head; if (window == NULL) return NULL; while (window != NULL) { if (window->windowId == windowId) return window; window = window->next; } return NULL; } void window_list_create(rdpWindowList* list, WINDOW_ORDER_INFO* orderInfo, WINDOW_STATE_ORDER* window_state) { rdpWindow* window; window = (rdpWindow*) xzalloc(sizeof(rdpWindow)); if (window == NULL) return; window->windowId = orderInfo->windowId; if (list->head == NULL) { list->head = list->tail = window; window->prev = NULL; window->next = NULL; } else { window->prev = list->tail; list->tail->next = window; window->next = NULL; list->tail = window; } window->windowId = orderInfo->windowId; window_state_update(window, orderInfo, window_state); rail_CreateWindow(list->rail, window); } void window_list_update(rdpWindowList* list, WINDOW_ORDER_INFO* orderInfo, WINDOW_STATE_ORDER* window_state) { rdpWindow* window; window = window_list_get_by_id(list, orderInfo->windowId); if (window == NULL) return; window_state_update(window, orderInfo, window_state); rail_UpdateWindow(list->rail, window); } void window_list_delete(rdpWindowList* list, WINDOW_ORDER_INFO* orderInfo) { rdpWindow* prev; rdpWindow* next; rdpWindow* window; window = window_list_get_by_id(list, orderInfo->windowId); if (window == NULL) return; prev = window->prev; next = window->next; if (prev != NULL) prev->next = next; if (next != NULL) next->prev = prev; if (list->head == list->tail) { list->head = list->tail = NULL; } else { if (list->head == window) list->head = next; if (list->tail == window) list->tail = prev; } rail_DestroyWindow(list->rail, window); } rdpWindowList* window_list_new(rdpRail* rail) { rdpWindowList* list; list = (rdpWindowList*) xzalloc(sizeof(rdpWindowList)); if (list != NULL) { list->head = NULL; list->tail = NULL; list->rail = rail; } return list; } void window_list_free(rdpWindowList* list) { if (list != NULL) { xfree(list); } } FreeRDP-1.0.2/libfreerdp-utils/000077500000000000000000000000001207112532300162115ustar00rootroot00000000000000FreeRDP-1.0.2/libfreerdp-utils/CMakeLists.txt000066400000000000000000000032401207112532300207500ustar00rootroot00000000000000# FreeRDP: A Remote Desktop Protocol Client # libfreerdp-utils cmake build script # # Copyright 2011 O.S. Systems Software Ltda. # Copyright 2011 Otavio Salvador # Copyright 2011 Marc-Andre Moreau # # 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(CMAKE_THREAD_PREFER_PTHREAD) find_required_package(Threads) set(FREERDP_UTILS_SRCS args.c blob.c dsp.c event.c bitmap.c hexdump.c list.c file.c load_plugin.c memory.c mutex.c passphrase.c pcap.c profiler.c rail.c rect.c registry.c semaphore.c signal.c sleep.c stopwatch.c stream.c string.c svc_plugin.c thread.c unicode.c wait_obj.c) add_definitions(-DPLUGIN_PATH="${FREERDP_PLUGIN_PATH}") add_library(freerdp-utils ${FREERDP_UTILS_SRCS}) set_target_properties(freerdp-utils PROPERTIES VERSION ${FREERDP_VERSION_FULL} SOVERSION ${FREERDP_VERSION} PREFIX "lib") target_link_libraries(freerdp-utils ${CMAKE_THREAD_LIBS_INIT} ${CMAKE_DL_LIBS}) if(WIN32) target_link_libraries(freerdp-utils ws2_32) endif() if(${CMAKE_SYSTEM_NAME} MATCHES SunOS) target_link_libraries(freerdp-utils rt) endif() install(TARGETS freerdp-utils DESTINATION ${CMAKE_INSTALL_LIBDIR}) FreeRDP-1.0.2/libfreerdp-utils/args.c000066400000000000000000000522011207112532300173110ustar00rootroot00000000000000/** * FreeRDP: A Remote Desktop Protocol client. * Arguments Parsing * * Copyright 2009-2011 Jay Sorg * Copyright 2011 Vic Lee * * 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. */ #include "config.h" #include #include #include #include #include #include #include #include #include void freerdp_parse_hostname(rdpSettings* settings, char* hostname) { char* p; if (hostname[0] == '[' && (p = strchr(hostname, ']')) && (p[1] == 0 || (p[1] == ':' && !strchr(p + 2, ':')))) { /* Either "[...]" or "[...]:..." with at most one : after the brackets */ settings->hostname = xstrdup(hostname + 1); if ((p = strchr((char*)settings->hostname, ']'))) { *p = 0; if (p[1] == ':') settings->port = atoi(p + 2); } } else { /* Port number is cut off and used if exactly one : in the string */ settings->hostname = xstrdup(hostname); if ((p = strchr((char*)settings->hostname, ':')) && !strchr(p + 1, ':')) { *p = 0; settings->port = atoi(p + 1); } } } /** * Parse command-line arguments and update rdpSettings members accordingly. * @param settings pointer to rdpSettings struct to be updated. * @param argc number of arguments available. * @param argv string array of the arguments. * @param plugin_callback function to be called when a plugin needs to be loaded. * @param plugin_user_data pointer to be passed to the plugin_callback function. * @param ui_callback function to be called when a UI-specific argument is being processed. * @param ui_user_data pointer to be passed to the ui_callback function. * @return number of arguments that were parsed, or FREERDP_ARGS_PARSE_RESULT on failure or --version/--help */ int freerdp_parse_args(rdpSettings* settings, int argc, char** argv, ProcessPluginArgs plugin_callback, void* plugin_user_data, ProcessUIArgs ui_callback, void* ui_user_data) { int t; char* p; int i, j; int index = 1; int num_extensions = 0; RDP_PLUGIN_DATA* plugin_data; while (index < argc) { if ((strcmp("-h", argv[index]) == 0 ) || (strcmp("--help", argv[index]) == 0 )) { printf("\n" "FreeRDP - A Free Remote Desktop Protocol Client\n" "See http://www.freerdp.com for more information\n" "\n" "Usage: %s [options] server:port\n" " -0: connect to console session\n" " -a: set color depth in bits, default is 16\n" " -c: shell working directory\n" " -D: hide window decorations\n" " -T: window title\n" " -d: domain\n" " -f: fullscreen mode\n" " -g: set geometry, using format WxH or X%% or 'workarea', default is 1024x768\n" " -h: print this help\n" " -k: set keyboard layout ID\n" " -K: do not interfere with window manager bindings (don't grab keyboard)\n" " -n: hostname\n" " -o: console audio\n" " -p: password\n" " -s: set startup-shell\n" " -t: alternative port number, default is 3389\n" " -u: username\n" " -x: performance flags (m[odem], b[roadband] l[an], or a bit-mask)\n" " -X: embed into another window with a given XID.\n" " -z: enable compression\n" " --app: RemoteApp connection. This implies -g workarea\n" " --ext: load an extension\n" " --no-auth: disable authentication\n" " --authonly: authentication only, no UI\n" " --from-stdin: unspecified username, password, domain and hostname params are prompted\n" " --help: print this help\n" " --no-fastpath: disable fast-path\n" " --gdi: graphics rendering (hw, sw)\n" " --no-motion: don't send mouse motion events\n" " --no-osb: disable offscreen bitmaps\n" " --no-bmp-cache: disable bitmap cache\n" " --plugin: load a virtual channel plugin\n" " --rfx: enable RemoteFX\n" " --rfx-mode: RemoteFX operational flags (v[ideo], i[mage]), default is video\n" " --nsc: enable NSCodec (experimental)\n" " --disable-wallpaper: disables wallpaper\n" " --composition: enable desktop composition\n" " --disable-full-window-drag: disables full window drag\n" " --disable-menu-animations: disables menu animations\n" " --disable-theming: disables theming\n" " --kbd-list: list all keyboard layout ids used by -k\n" " --no-rdp: disable Standard RDP encryption\n" " --no-tls: disable TLS encryption\n" " --no-nla: disable network level authentication\n" " --ntlm: force NTLM authentication protocol version (1 or 2)\n" " --certificate-name: use the argument as the logon certificate, instead of the server name\n" " --ignore-certificate: ignore verification of logon certificate\n" " --sec: force protocol security (rdp, tls or nla)\n" " --secure-checksum: use salted checksums with Standard RDP encryption\n" " --version: print version information\n" "\n", argv[0]); return FREERDP_ARGS_PARSE_HELP; //TODO: What is the correct return } else if (strcmp("-a", argv[index]) == 0) { index++; if (index == argc) { printf("missing color depth\n"); return FREERDP_ARGS_PARSE_FAILURE; } settings->color_depth = atoi(argv[index]); } else if (strcmp("-u", argv[index]) == 0) { index++; if (index == argc) { printf("missing username\n"); return FREERDP_ARGS_PARSE_FAILURE; } settings->username = xstrdup(argv[index]); } else if (strcmp("-p", argv[index]) == 0) { index++; if (index == argc) { printf("missing password\n"); return FREERDP_ARGS_PARSE_FAILURE; } settings->password = xstrdup(argv[index]); settings->autologon = 1; /* * Overwrite original password which could be revealed by a simple "ps aux" command. * This approach won't hide the password length, but it is better than nothing. */ memset(argv[index], '*', strlen(argv[index])); } else if (strcmp("-d", argv[index]) == 0) { index++; if (index == argc) { printf("missing domain\n"); return FREERDP_ARGS_PARSE_FAILURE; } settings->domain = xstrdup(argv[index]); } else if (strcmp("-s", argv[index]) == 0) { index++; if (index == argc) { printf("missing shell\n"); return FREERDP_ARGS_PARSE_FAILURE; } settings->shell = xstrdup(argv[index]); } else if (strcmp("-c", argv[index]) == 0) { index++; if (index == argc) { printf("missing directory\n"); return FREERDP_ARGS_PARSE_FAILURE; } settings->directory = xstrdup(argv[index]); } else if (strcmp("-g", argv[index]) == 0) { index++; if (index == argc) { printf("missing dimensions\n"); return FREERDP_ARGS_PARSE_FAILURE; } if (strncmp("workarea", argv[index], 1) == 0) { settings->workarea = true; } else { settings->width = (uint16) strtol(argv[index], &p, 10); if (*p == 'x') { settings->height = (uint16) strtol(p + 1, &p, 10); } if (*p == '%') { settings->percent_screen = settings->width; if (settings->percent_screen <= 0 || settings->percent_screen > 100) { printf("invalid geometry percentage\n"); return FREERDP_ARGS_PARSE_FAILURE; } } else { if (ui_callback != NULL) ui_callback(settings, "-g", p, ui_user_data); } } } else if (strcmp("-f", argv[index]) == 0) { settings->fullscreen = true; } else if (strcmp("-D", argv[index]) == 0) { settings->decorations = false; } else if (strcmp("-T", argv[index]) == 0) { index++; if (index == argc) { printf("missing window title\n"); return FREERDP_ARGS_PARSE_FAILURE; } settings->window_title = xstrdup(argv[index]); } else if (strcmp("-t", argv[index]) == 0) { index++; if (index == argc) { printf("missing port number\n"); return FREERDP_ARGS_PARSE_FAILURE; } settings->port = atoi(argv[index]); } else if (strcmp("-k", argv[index]) == 0) { index++; if (index == argc) { printf("missing keyboard layout id\n"); return FREERDP_ARGS_PARSE_FAILURE; } sscanf(argv[index], "%X", &(settings->kbd_layout)); } else if (strcmp("-K", argv[index]) == 0) { settings->grab_keyboard = false; } else if (strcmp("-n", argv[index]) == 0) { index++; if (index == argc) { printf("missing client hostname\n"); return FREERDP_ARGS_PARSE_FAILURE; } strncpy(settings->client_hostname, argv[index], sizeof(settings->client_hostname) - 1); settings->client_hostname[sizeof(settings->client_hostname) - 1] = 0; } else if (strcmp("-o", argv[index]) == 0) { settings->console_audio = true; } else if (strcmp("-0", argv[index]) == 0) { settings->console_session = true; } else if (strcmp("-z", argv[index]) == 0) { settings->compression = true; } else if (strcmp("--ntlm", argv[index]) == 0) { index++; settings->ntlm_version = atoi(argv[index]); if (settings->ntlm_version != 2) settings->ntlm_version = 1; } else if (strcmp("--no-glyph-cache", argv[index]) == 0) { settings->glyph_cache = false; } else if (strcmp("--no-osb", argv[index]) == 0) { settings->offscreen_bitmap_cache = false; } else if (strcmp("--no-bmp-cache", argv[index]) == 0) { settings->bitmap_cache = false; } else if (strcmp("--no-auth", argv[index]) == 0) { settings->authentication = false; } else if (strcmp("--authonly", argv[index]) == 0) { settings->authentication_only = true; } else if (strcmp("--from-stdin", argv[index]) == 0) { settings->from_stdin = true; } else if (strcmp("--ignore-certificate", argv[index]) == 0) { settings->ignore_certificate = true; } else if (strcmp("--certificate-name", argv[index]) == 0) { index++; if (index == argc) { printf("missing certificate name\n"); return FREERDP_ARGS_PARSE_FAILURE; } settings->certificate_name = xstrdup(argv[index]); } else if (strcmp("--no-fastpath", argv[index]) == 0) { settings->fastpath_input = false; settings->fastpath_output = false; } else if (strcmp("--gdi", argv[index]) == 0) { index++; if (index == argc) { printf("missing GDI backend\n"); return FREERDP_ARGS_PARSE_FAILURE; } if (strncmp("sw", argv[index], 1) == 0) /* software */ { settings->sw_gdi = true; } else if (strncmp("hw", argv[index], 1) == 0) /* hardware */ { settings->sw_gdi = false; } else { printf("unknown GDI backend\n"); return FREERDP_ARGS_PARSE_FAILURE; } } else if (strcmp("--rfx", argv[index]) == 0) { settings->rfx_codec = true; settings->fastpath_output = true; settings->color_depth = 32; settings->frame_acknowledge = false; settings->performance_flags = PERF_FLAG_NONE; settings->large_pointer = true; } else if (strcmp("--rfx-mode", argv[index]) == 0) { index++; if (index == argc) { printf("missing RemoteFX mode flag\n"); return FREERDP_ARGS_PARSE_FAILURE; } if (argv[index][0] == 'v') /* video */ { settings->rfx_codec_mode = 0x00; } else if (argv[index][0] == 'i') /* image */ { settings->rfx_codec_mode = 0x02; } else { printf("unknown RemoteFX mode flag\n"); return FREERDP_ARGS_PARSE_FAILURE; } } else if (strcmp("--nsc", argv[index]) == 0) { settings->ns_codec = true; } else if (strcmp("--dump-rfx", argv[index]) == 0) { index++; if (index == argc) { printf("missing file name\n"); return FREERDP_ARGS_PARSE_FAILURE; } settings->dump_rfx_file = xstrdup(argv[index]); settings->dump_rfx = true; } else if (strcmp("--play-rfx", argv[index]) == 0) { index++; if (index == argc) { printf("missing file name\n"); return FREERDP_ARGS_PARSE_FAILURE; } settings->play_rfx_file = xstrdup(argv[index]); settings->play_rfx = true; } else if (strcmp("--fonts", argv[index]) == 0) { settings->smooth_fonts = true; } else if (strcmp("--disable-wallpaper", argv[index]) == 0) { settings->disable_wallpaper = true; } else if (strcmp("--disable-full-window-drag", argv[index]) == 0) { settings->disable_full_window_drag = true; } else if (strcmp("--disable-menu-animations", argv[index]) == 0) { settings->disable_menu_animations = true; } else if (strcmp("--disable-theming", argv[index]) == 0) { settings->disable_theming = true; } else if (strcmp("--composition", argv[index]) == 0) { settings->desktop_composition = true; } else if (strcmp("--no-motion", argv[index]) == 0) { settings->mouse_motion = false; } else if (strcmp("--app", argv[index]) == 0) { settings->remote_app = true; settings->rail_langbar_supported = true; settings->workarea = true; settings->performance_flags = PERF_DISABLE_WALLPAPER | PERF_DISABLE_FULLWINDOWDRAG; } else if (strcmp("-x", argv[index]) == 0) { index++; if (index == argc) { printf("missing performance flag\n"); return FREERDP_ARGS_PARSE_FAILURE; } if (argv[index][0] == 'm') /* modem */ { settings->performance_flags = PERF_DISABLE_WALLPAPER | PERF_DISABLE_FULLWINDOWDRAG | PERF_DISABLE_MENUANIMATIONS | PERF_DISABLE_THEMING; settings->connection_type = CONNECTION_TYPE_MODEM; } else if (argv[index][0] == 'b') /* broadband */ { settings->performance_flags = PERF_DISABLE_WALLPAPER; settings->connection_type = CONNECTION_TYPE_BROADBAND_HIGH; } else if (argv[index][0] == 'l') /* lan */ { settings->performance_flags = PERF_FLAG_NONE; settings->connection_type = CONNECTION_TYPE_LAN; } else { settings->performance_flags = strtol(argv[index], 0, 16); } } else if (strcmp("-X", argv[index]) == 0) { index++; if (index == argc) { printf("missing parent window XID\n"); return FREERDP_ARGS_PARSE_FAILURE; } settings->parent_window_xid = strtol(argv[index], NULL, 0); if (settings->parent_window_xid == 0) { printf("invalid parent window XID\n"); return FREERDP_ARGS_PARSE_FAILURE; } } else if (strcmp("--no-rdp", argv[index]) == 0) { settings->rdp_security = false; } else if (strcmp("--no-tls", argv[index]) == 0) { settings->tls_security = false; } else if (strcmp("--no-nla", argv[index]) == 0) { settings->nla_security = false; } else if (strcmp("--sec", argv[index]) == 0) { index++; if (index == argc) { printf("missing protocol security\n"); return FREERDP_ARGS_PARSE_FAILURE; } if (strncmp("rdp", argv[index], 1) == 0) /* Standard RDP */ { settings->rdp_security = true; settings->tls_security = false; settings->nla_security = false; settings->encryption = true; settings->encryption_method = ENCRYPTION_METHOD_40BIT | ENCRYPTION_METHOD_128BIT | ENCRYPTION_METHOD_FIPS; settings->encryption_level = ENCRYPTION_LEVEL_CLIENT_COMPATIBLE; } else if (strncmp("tls", argv[index], 1) == 0) /* TLS */ { settings->rdp_security = false; settings->tls_security = true; settings->nla_security = false; } else if (strncmp("nla", argv[index], 1) == 0) /* NLA */ { settings->rdp_security = false; settings->tls_security = false; settings->nla_security = true; } else { printf("unknown protocol security\n"); return FREERDP_ARGS_PARSE_FAILURE; } } else if (strcmp("--plugin", argv[index]) == 0) { index++; t = index; if (index == argc) { printf("missing plugin name\n"); return FREERDP_ARGS_PARSE_FAILURE; } plugin_data = NULL; if (strstr(argv[t], "rdpsnd")) settings->audio_playback = true; if (index < argc - 1 && strcmp("--data", argv[index + 1]) == 0) { index += 2; i = 0; while (index < argc && strcmp("--", argv[index]) != 0) { if (plugin_data == NULL) plugin_data = (RDP_PLUGIN_DATA*) xmalloc(sizeof(RDP_PLUGIN_DATA) * (i + 2)); else plugin_data = (RDP_PLUGIN_DATA*) xrealloc(plugin_data, sizeof(RDP_PLUGIN_DATA) * (i + 2)); if (strstr(argv[t], "drdynvc") && strstr(argv[index], "audin")) settings->audio_capture = true; plugin_data[i].size = sizeof(RDP_PLUGIN_DATA); plugin_data[i].data[0] = NULL; plugin_data[i].data[1] = NULL; plugin_data[i].data[2] = NULL; plugin_data[i].data[3] = NULL; plugin_data[i + 1].size = 0; for (j = 0, p = argv[index]; j < 4 && p != NULL; j++) { if (*p == '\'') { plugin_data[i].data[j] = p + 1; p = strchr(p + 1, '\''); if (p) *p++ = 0; } else plugin_data[i].data[j] = p; p = strchr(p, ':'); if (p != NULL) *p++ = 0; } index++; i++; } } if (plugin_callback != NULL) { if (!plugin_callback(settings, argv[t], plugin_data, plugin_user_data)) return FREERDP_ARGS_PARSE_FAILURE; } } else if (strcmp("--ext", argv[index]) == 0) { index++; if (index == argc) { printf("missing extension name\n"); return FREERDP_ARGS_PARSE_FAILURE; } if (num_extensions >= sizeof(settings->extensions) / sizeof(struct rdp_ext_set)) { printf("maximum extensions reached\n"); return FREERDP_ARGS_PARSE_FAILURE; } snprintf(settings->extensions[num_extensions].name, sizeof(settings->extensions[num_extensions].name), "%s", argv[index]); settings->extensions[num_extensions].data = NULL; if (index < argc - 1 && strcmp("--data", argv[index + 1]) == 0) { index += 2; settings->extensions[num_extensions].data = argv[index]; i = 0; while (index < argc && strcmp("--", argv[index]) != 0) { index++; i++; } } num_extensions++; } else if (strcmp("--secure-checksum", argv[index]) == 0) { settings->secure_checksum = true; } else if (strcmp("--version", argv[index]) == 0) { if (strlen(FREERDP_VERSION_SUFFIX)) printf("This is FreeRDP version %s-%s\n", FREERDP_VERSION_FULL, FREERDP_VERSION_SUFFIX); else printf("This is FreeRDP version %s\n", FREERDP_VERSION_FULL); return FREERDP_ARGS_PARSE_VERSION; } else if (argv[index][0] != '-') { freerdp_parse_hostname(settings, argv[index]); /* server is the last argument for the current session. arguments followed will be parsed for the next session. */ index++; if (settings->smooth_fonts) settings->performance_flags |= PERF_ENABLE_FONT_SMOOTHING; if (settings->desktop_composition) settings->performance_flags |= PERF_ENABLE_DESKTOP_COMPOSITION; if (settings->disable_wallpaper) settings->performance_flags |= PERF_DISABLE_WALLPAPER; if (settings->disable_full_window_drag) settings->performance_flags |= PERF_DISABLE_FULLWINDOWDRAG; if (settings->disable_menu_animations) settings->performance_flags |= PERF_DISABLE_MENUANIMATIONS; if (settings->disable_theming) settings->performance_flags |= PERF_DISABLE_THEMING; break; /* post process missing arguments */ } else { if (ui_callback != NULL) { t = ui_callback(settings, argv[index], (index + 1 < argc && argv[index + 1][0] != '-' ? argv[index + 1] : NULL), ui_user_data); if (t == 0) { printf("invalid option: %s\n", argv[index]); return FREERDP_ARGS_PARSE_FAILURE; } index += t - 1; } } index++; } /* --from-stdin will prompt for missing arguments only. You can prompt for username, password, domain and hostname to avoid disclosing these settings to ps. */ if (settings->from_stdin) { /* username */ if (NULL == settings->username) { char input[512]; input[0] = '\0'; printf("username: "); if (scanf("%511s%*c", input) > 0) { settings->username = xstrdup(input); } } /* password */ if (NULL == settings->password) { settings->password = xmalloc(512 * sizeof(char)); if (isatty(STDIN_FILENO)) { freerdp_passphrase_read("password: ", settings->password, 512, settings->from_stdin); } else { printf("password: "); if (scanf("%511s%*c", settings->password) <= 0) { free(settings->password); settings->password = NULL; } } } /* domain */ if (NULL == settings->domain) { char input[512]; input[0] = '\0'; printf("domain (control-D to skip): "); if (scanf("%511s%*c", input) > 0) { /* Try to catch the cases where the string is NULL-ish right at the get go */ if (input[0] != '\0' && !(input[0] == '.' && input[1] == '\0')) { settings->domain = xstrdup(input); } } if (feof(stdin)) { printf("\n"); clearerr(stdin); } } /* hostname */ if (NULL == settings->hostname) { char input[512]; input[0] = '\0'; printf("hostname: "); if (scanf("%511s%*c", input) > 0) { freerdp_parse_hostname(settings, input); } } } /* Must have a hostname. Do you? */ if (NULL == settings->hostname) { printf("missing server name\n"); return FREERDP_ARGS_PARSE_FAILURE; } else { return index; } } FreeRDP-1.0.2/libfreerdp-utils/bitmap.c000066400000000000000000000045001207112532300176300ustar00rootroot00000000000000/** * FreeRDP: A Remote Desktop Protocol Client * Bitmap File Format Utils * * Copyright 2011 Marc-Andre Moreau * * 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. */ #include #include #include #include typedef struct { uint8 magic[2]; } bmpfile_magic; typedef struct { uint32 filesz; uint16 creator1; uint16 creator2; uint32 bmp_offset; } bmpfile_header; typedef struct { uint32 header_sz; sint32 width; sint32 height; uint16 nplanes; uint16 bitspp; uint32 compress_type; uint32 bmp_bytesz; sint32 hres; sint32 vres; uint32 ncolors; uint32 nimpcolors; } BITMAPINFOHEADER; void freerdp_bitmap_write(char* filename, void* data, int width, int height, int bpp) { FILE* fp; bmpfile_magic magic; bmpfile_header header; BITMAPINFOHEADER info_header; fp = fopen(filename, "w+b"); if (fp == NULL) { printf("failed to open file %s\n", filename); return; } magic.magic[0] = 'B'; magic.magic[1] = 'M'; header.creator1 = 0; header.creator2 = 0; header.bmp_offset = sizeof(bmpfile_magic) + sizeof(bmpfile_header) + sizeof(BITMAPINFOHEADER); info_header.bmp_bytesz = width * height * (bpp / 8); header.filesz = header.bmp_offset + info_header.bmp_bytesz; info_header.width = width; info_header.height = (-1) * height; info_header.nplanes = 1; info_header.bitspp = bpp; info_header.compress_type = 0; info_header.hres = width; info_header.vres = height; info_header.ncolors = 0; info_header.nimpcolors = 0; info_header.header_sz = sizeof(BITMAPINFOHEADER); fwrite((void*) &magic, sizeof(bmpfile_magic), 1, fp); fwrite((void*) &header, sizeof(bmpfile_header), 1, fp); fwrite((void*) &info_header, sizeof(BITMAPINFOHEADER), 1, fp); fwrite((void*) data, info_header.bmp_bytesz, 1, fp); fclose(fp); } FreeRDP-1.0.2/libfreerdp-utils/blob.c000066400000000000000000000021661207112532300173000ustar00rootroot00000000000000/** * FreeRDP: A Remote Desktop Protocol Client * BLOB Utils * * Copyright 2011 Marc-Andre Moreau * * 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. */ #include #include /** * Allocate memory for data blob. * @param blob blob structure * @param length memory length */ void freerdp_blob_alloc(rdpBlob* blob, int length) { blob->data = xmalloc(length); blob->length = length; } /** * Free memory allocated for data blob. * @param blob */ void freerdp_blob_free(rdpBlob* blob) { if (blob->data) xfree(blob->data); blob->length = 0; } FreeRDP-1.0.2/libfreerdp-utils/dsp.c000066400000000000000000000165411207112532300171520ustar00rootroot00000000000000/** * FreeRDP: A Remote Desktop Protocol client. * Digital Sound Processing * * Copyright 2010-2011 Vic Lee * * 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. */ #include #include #include #include #include #include uint8* dsp_resample(uint8* src, int bytes_per_sample, uint32 schan, uint32 srate, int sframes, uint32 rchan, uint32 rrate, int * prframes) { uint8* dst; uint8* p; int rframes; int rsize; int i, j; int n1, n2; int sbytes, rbytes; sbytes = bytes_per_sample * schan; rbytes = bytes_per_sample * rchan; rframes = sframes * rrate / srate; *prframes = rframes; rsize = rbytes * rframes; dst = (uint8*) xzalloc(rsize); p = dst; for (i = 0; i < rframes; i++) { n1 = i * srate / rrate; if (n1 >= sframes) n1 = sframes - 1; n2 = (n1 * rrate == i * srate || n1 == sframes - 1 ? n1 : n1 + 1); for (j = 0; j < rbytes; j++) { /* Nearest Interpolation, probably the easiest, but works */ *p++ = (i * srate - n1 * rrate > n2 * rrate - i * srate ? src[n2 * sbytes + (j % sbytes)] : src[n1 * sbytes + (j % sbytes)]); } } return dst; } /** * Microsoft IMA ADPCM specification: * * http://wiki.multimedia.cx/index.php?title=Microsoft_IMA_ADPCM * http://wiki.multimedia.cx/index.php?title=IMA_ADPCM */ static const sint16 ima_step_index_table[] = { -1, -1, -1, -1, 2, 4, 6, 8, -1, -1, -1, -1, 2, 4, 6, 8 }; static const sint16 ima_step_size_table[] = { 7, 8, 9, 10, 11, 12, 13, 14, 16, 17, 19, 21, 23, 25, 28, 31, 34, 37, 41, 45, 50, 55, 60, 66, 73, 80, 88, 97, 107, 118, 130, 143, 157, 173, 190, 209, 230, 253, 279, 307, 337, 371, 408, 449, 494, 544, 598, 658, 724, 796, 876, 963, 1060, 1166, 1282, 1411, 1552, 1707, 1878, 2066, 2272, 2499, 2749, 3024, 3327, 3660, 4026, 4428, 4871, 5358, 5894, 6484, 7132, 7845, 8630, 9493, 10442, 11487, 12635, 13899, 15289, 16818, 18500, 20350, 22385, 24623, 27086, 29794, 32767 }; static uint16 dsp_decode_ima_adpcm_sample(ADPCM* adpcm, int channel, uint8 sample) { sint32 ss; sint32 d; ss = ima_step_size_table[adpcm->last_step[channel]]; d = (ss >> 3); if (sample & 1) d += (ss >> 2); if (sample & 2) d += (ss >> 1); if (sample & 4) d += ss; if (sample & 8) d = -d; d += adpcm->last_sample[channel]; if (d < -32768) d = -32768; else if (d > 32767) d = 32767; adpcm->last_sample[channel] = (sint16) d; adpcm->last_step[channel] += ima_step_index_table[sample]; if (adpcm->last_step[channel] < 0) adpcm->last_step[channel] = 0; else if (adpcm->last_step[channel] > 88) adpcm->last_step[channel] = 88; return (uint16) d; } uint8* dsp_decode_ima_adpcm(ADPCM* adpcm, uint8* src, int size, int channels, int block_size, int* out_size) { uint8* out; uint8* dst; uint8 sample; uint16 decoded; int channel; int i; *out_size = size * 4; out = (uint8 *) xzalloc(*out_size); dst = out; while (size > 0) { if (size % block_size == 0) { adpcm->last_sample[0] = (sint16) (((uint16)(*src)) | (((uint16)(*(src + 1))) << 8)); adpcm->last_step[0] = (sint16) (*(src + 2)); src += 4; size -= 4; *out_size -= 16; if (channels > 1) { adpcm->last_sample[1] = (sint16) (((uint16)(*src)) | (((uint16)(*(src + 1))) << 8)); adpcm->last_step[1] = (sint16) (*(src + 2)); src += 4; size -= 4; *out_size -= 16; } } if (channels > 1) { for (i = 0; i < 8; i++) { channel = (i < 4 ? 0 : 1); sample = ((*src) & 0x0f); decoded = dsp_decode_ima_adpcm_sample(adpcm, channel, sample); dst[((i & 3) << 3) + (channel << 1)] = (decoded & 0xff); dst[((i & 3) << 3) + (channel << 1) + 1] = (decoded >> 8); sample = ((*src) >> 4); decoded = dsp_decode_ima_adpcm_sample(adpcm, channel, sample); dst[((i & 3) << 3) + (channel << 1) + 4] = (decoded & 0xff); dst[((i & 3) << 3) + (channel << 1) + 5] = (decoded >> 8); src++; } dst += 32; size -= 8; } else { sample = ((*src) & 0x0f); decoded = dsp_decode_ima_adpcm_sample(adpcm, 0, sample); *dst++ = (decoded & 0xff); *dst++ = (decoded >> 8); sample = ((*src) >> 4); decoded = dsp_decode_ima_adpcm_sample(adpcm, 0, sample); *dst++ = (decoded & 0xff); *dst++ = (decoded >> 8); src++; size--; } } return out; } /** * 0 1 2 3 * 2 0 6 4 10 8 14 12 * * 4 5 6 7 * 3 1 7 5 11 9 15 13 */ static const struct { uint8 byte_num; uint8 byte_shift; } ima_stereo_encode_map[] = { { 0, 0 }, { 4, 0 }, { 0, 4 }, { 4, 4 }, { 1, 0 }, { 5, 0 }, { 1, 4 }, { 5, 4 }, { 2, 0 }, { 6, 0 }, { 2, 4 }, { 6, 4 }, { 3, 0 }, { 7, 0 }, { 3, 4 }, { 7, 4 } }; static uint8 dsp_encode_ima_adpcm_sample(ADPCM* adpcm, int channel, sint16 sample) { sint32 e; sint32 d; sint32 ss; uint8 enc; sint32 diff; ss = ima_step_size_table[adpcm->last_step[channel]]; d = e = sample - adpcm->last_sample[channel]; diff = ss >> 3; enc = 0; if (e < 0) { enc = 8; e = -e; } if (e >= ss) { enc |= 4; e -= ss; } ss >>= 1; if (e >= ss) { enc |= 2; e -= ss; } ss >>= 1; if (e >= ss) { enc |= 1; e -= ss; } if (d < 0) diff = d + e - diff; else diff = d - e + diff; diff += adpcm->last_sample[channel]; if (diff < -32768) diff = -32768; else if (diff > 32767) diff = 32767; adpcm->last_sample[channel] = (sint16) diff; adpcm->last_step[channel] += ima_step_index_table[enc]; if (adpcm->last_step[channel] < 0) adpcm->last_step[channel] = 0; else if (adpcm->last_step[channel] > 88) adpcm->last_step[channel] = 88; return enc; } uint8* dsp_encode_ima_adpcm(ADPCM* adpcm, uint8* src, int size, int channels, int block_size, int* out_size) { uint8* out; uint8* dst; sint16 sample; uint8 encoded; int i; out = (uint8*) xzalloc(size / 2); dst = out; while (size > 0) { if ((dst - out) % block_size == 0) { *dst++ = adpcm->last_sample[0] & 0xff; *dst++ = (adpcm->last_sample[0] >> 8) & 0xff; *dst++ = (uint8) adpcm->last_step[0]; *dst++ = 0; if (channels > 1) { *dst++ = adpcm->last_sample[1] & 0xff; *dst++ = (adpcm->last_sample[1] >> 8) & 0xff; *dst++ = (uint8) adpcm->last_step[1]; *dst++ = 0; } } if (channels > 1) { memset(dst, 0, 8); for (i = 0; i < 16; i++) { sample = (sint16) (((uint16)(*src)) | (((uint16)(*(src + 1))) << 8)); src += 2; encoded = dsp_encode_ima_adpcm_sample(adpcm, i % 2, sample); dst[ima_stereo_encode_map[i].byte_num] |= encoded << ima_stereo_encode_map[i].byte_shift; } dst += 8; size -= 32; } else { sample = (sint16) (((uint16)(*src)) | (((uint16)(*(src + 1))) << 8)); src += 2; encoded = dsp_encode_ima_adpcm_sample(adpcm, 0, sample); sample = (sint16) (((uint16)(*src)) | (((uint16)(*(src + 1))) << 8)); src += 2; encoded |= dsp_encode_ima_adpcm_sample(adpcm, 0, sample) << 4; *dst++ = encoded; size -= 4; } } *out_size = dst - out; return out; } FreeRDP-1.0.2/libfreerdp-utils/event.c000066400000000000000000000074541207112532300175100ustar00rootroot00000000000000/** * FreeRDP: A Remote Desktop Protocol client. * Events * * Copyright 2011 Vic Lee * * 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. */ #include #include #include #include #include #include #include #include static RDP_EVENT* freerdp_cliprdr_event_new(uint16 event_type) { RDP_EVENT* event = NULL; switch (event_type) { case RDP_EVENT_TYPE_CB_MONITOR_READY: event = (RDP_EVENT*) xnew(RDP_CB_MONITOR_READY_EVENT); break; case RDP_EVENT_TYPE_CB_FORMAT_LIST: event = (RDP_EVENT*) xnew(RDP_CB_FORMAT_LIST_EVENT); break; case RDP_EVENT_TYPE_CB_DATA_REQUEST: event = (RDP_EVENT*) xnew(RDP_CB_DATA_REQUEST_EVENT); break; case RDP_EVENT_TYPE_CB_DATA_RESPONSE: event = (RDP_EVENT*) xnew(RDP_CB_DATA_RESPONSE_EVENT); break; } return event; } static RDP_EVENT* freerdp_tsmf_event_new(uint16 event_type) { RDP_EVENT* event = NULL; switch (event_type) { case RDP_EVENT_TYPE_TSMF_VIDEO_FRAME: event = (RDP_EVENT*) xnew(RDP_VIDEO_FRAME_EVENT); break; case RDP_EVENT_TYPE_TSMF_REDRAW: event = (RDP_EVENT*) xnew(RDP_REDRAW_EVENT); break; } return event; } static RDP_EVENT* freerdp_rail_event_new(uint16 event_type) { RDP_EVENT* event = NULL; event = xnew(RDP_EVENT); return event; } RDP_EVENT* freerdp_event_new(uint16 event_class, uint16 event_type, RDP_EVENT_CALLBACK on_event_free_callback, void* user_data) { RDP_EVENT* event = NULL; switch (event_class) { case RDP_EVENT_CLASS_DEBUG: event = xnew(RDP_EVENT); break; case RDP_EVENT_CLASS_CLIPRDR: event = freerdp_cliprdr_event_new(event_type); break; case RDP_EVENT_CLASS_TSMF: event = freerdp_tsmf_event_new(event_type); break; case RDP_EVENT_CLASS_RAIL: event = freerdp_rail_event_new(event_type); break; } if (event != NULL) { event->event_class = event_class; event->event_type = event_type; event->on_event_free_callback = on_event_free_callback; event->user_data = user_data; } return event; } static void freerdp_cliprdr_event_free(RDP_EVENT* event) { switch (event->event_type) { case RDP_EVENT_TYPE_CB_FORMAT_LIST: { RDP_CB_FORMAT_LIST_EVENT* cb_event = (RDP_CB_FORMAT_LIST_EVENT*)event; xfree(cb_event->formats); xfree(cb_event->raw_format_data); } break; case RDP_EVENT_TYPE_CB_DATA_RESPONSE: { RDP_CB_DATA_RESPONSE_EVENT* cb_event = (RDP_CB_DATA_RESPONSE_EVENT*)event; xfree(cb_event->data); } break; } } static void freerdp_tsmf_event_free(RDP_EVENT* event) { switch (event->event_type) { case RDP_EVENT_TYPE_TSMF_VIDEO_FRAME: { RDP_VIDEO_FRAME_EVENT* vevent = (RDP_VIDEO_FRAME_EVENT*)event; xfree(vevent->frame_data); xfree(vevent->visible_rects); } break; } } static void freerdp_rail_event_free(RDP_EVENT* event) { } void freerdp_event_free(RDP_EVENT* event) { if (event != NULL) { if (event->on_event_free_callback != NULL) event->on_event_free_callback(event); switch (event->event_class) { case RDP_EVENT_CLASS_CLIPRDR: freerdp_cliprdr_event_free(event); break; case RDP_EVENT_CLASS_TSMF: freerdp_tsmf_event_free(event); break; case RDP_EVENT_CLASS_RAIL: freerdp_rail_event_free(event); break; } xfree(event); } } FreeRDP-1.0.2/libfreerdp-utils/file.c000066400000000000000000000127411207112532300173010ustar00rootroot00000000000000/** * FreeRDP: A Remote Desktop Protocol Client * File Utils * * Copyright 2011 Marc-Andre Moreau * * 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. */ #include #include #include #include #include #include #include #include #ifndef _WIN32 #include #else #include #define getcwd _getcwd #endif #include #ifndef _WIN32 #define PATH_SEPARATOR_STR "/" #define PATH_SEPARATOR_CHR '/' #define HOME_ENV_VARIABLE "HOME" #else #include #define PATH_SEPARATOR_STR "\\" #define PATH_SEPARATOR_CHR '\\' #define HOME_ENV_VARIABLE "HOMEPATH" #endif #ifdef _WIN32 #define SHARED_LIB_SUFFIX ".dll" #elif __APPLE__ #define SHARED_LIB_SUFFIX ".dylib" #else #define SHARED_LIB_SUFFIX ".so" #endif #define FREERDP_CONFIG_DIR ".freerdp" #define PARENT_PATH ".." PATH_SEPARATOR_STR void freerdp_mkdir(char* path) { #ifndef _WIN32 mkdir(path, S_IRUSR | S_IWUSR | S_IXUSR); #else CreateDirectoryA(path, 0); #endif } boolean freerdp_check_file_exists(char* file) { struct stat stat_info; if (stat(file, &stat_info) != 0) return false; return true; } char* freerdp_get_home_path(rdpSettings* settings) { if (settings->home_path == NULL) settings->home_path = getenv(HOME_ENV_VARIABLE); if (settings->home_path == NULL) settings->home_path = xstrdup("/"); return settings->home_path; } char* freerdp_get_config_path(rdpSettings* settings) { char* path; path = (char*) xmalloc(strlen(settings->home_path) + sizeof(FREERDP_CONFIG_DIR) + 2); sprintf(path, "%s/%s", settings->home_path, FREERDP_CONFIG_DIR); if (!freerdp_check_file_exists(path)) freerdp_mkdir(path); settings->config_path = path; return path; } char* freerdp_get_current_path(rdpSettings* settings) { if (settings->current_path == NULL) settings->current_path = getcwd(NULL, 0); return settings->current_path; } char* freerdp_construct_path(char* base_path, char* relative_path) { char* path; int length; int base_path_length; int relative_path_length; base_path_length = strlen(base_path); relative_path_length = strlen(relative_path); length = base_path_length + relative_path_length + 1; path = xmalloc(length + 1); sprintf(path, "%s" PATH_SEPARATOR_STR "%s", base_path, relative_path); return path; } char* freerdp_append_shared_library_suffix(char* file_path) { char* p; char* path = NULL; int file_path_length; int shared_lib_suffix_length; if (file_path == NULL) return NULL; file_path_length = strlen(file_path); shared_lib_suffix_length = strlen(SHARED_LIB_SUFFIX); if (file_path_length >= shared_lib_suffix_length) { p = &file_path[file_path_length - shared_lib_suffix_length]; if (strcmp(p, SHARED_LIB_SUFFIX) != 0) { path = xmalloc(file_path_length + shared_lib_suffix_length + 1); sprintf(path, "%s%s", file_path, SHARED_LIB_SUFFIX); } else { path = xstrdup(file_path); } } else { path = xstrdup(file_path); } return path; } char* freerdp_get_parent_path(char* base_path, int depth) { int i; char* p; char* path; int length; int base_length; if (base_path == NULL) return NULL; if (depth <= 0) return xstrdup(base_path); base_length = strlen(base_path); p = &base_path[base_length]; for (i = base_length - 1; ((i >= 0) && (depth > 0)); i--) { if (base_path[i] == PATH_SEPARATOR_CHR) { p = &base_path[i]; depth--; } } length = (p - base_path); path = (char*) xmalloc(length + 1); memcpy(path, base_path, length); path[length] = '\0'; return path; } boolean freerdp_path_contains_separator(char* path) { if (path == NULL) return false; if (strchr(path, PATH_SEPARATOR_CHR) == NULL) return false; return true; } /* detects if we are running from the source tree */ boolean freerdp_detect_development_mode(rdpSettings* settings) { int depth = 0; char* current_path; char* development_path = NULL; boolean development_mode = false; if (freerdp_check_file_exists(".git")) { depth = 0; development_mode = true; } else if (freerdp_check_file_exists(PARENT_PATH ".git")) { depth = 1; development_mode = true; } else if (freerdp_check_file_exists(PARENT_PATH PARENT_PATH ".git")) { depth = 2; development_mode = true; } current_path = freerdp_get_current_path(settings); if (development_mode) development_path = freerdp_get_parent_path(current_path, depth); settings->development_mode = development_mode; settings->development_path = development_path; return settings->development_mode; } void freerdp_detect_paths(rdpSettings* settings) { freerdp_get_home_path(settings); freerdp_get_config_path(settings); freerdp_detect_development_mode(settings); #if 0 printf("home path: %s\n", settings->home_path); printf("config path: %s\n", settings->config_path); printf("current path: %s\n", settings->current_path); if (settings->development_mode) printf("development path: %s\n", settings->development_path); #endif } FreeRDP-1.0.2/libfreerdp-utils/hexdump.c000066400000000000000000000024571207112532300200370ustar00rootroot00000000000000/** * FreeRDP: A Remote Desktop Protocol Client * Hex Dump Utils * * Copyright 2011 Marc-Andre Moreau * * 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. */ #include #include #include #include void freerdp_hexdump(uint8* data, int length) { uint8* p = data; int i, line, offset = 0; while (offset < length) { printf("%04x ", offset); line = length - offset; if (line > FREERDP_HEXDUMP_LINE_LENGTH) line = FREERDP_HEXDUMP_LINE_LENGTH; for (i = 0; i < line; i++) printf("%02x ", p[i]); for (; i < FREERDP_HEXDUMP_LINE_LENGTH; i++) printf(" "); for (i = 0; i < line; i++) printf("%c", (p[i] >= 0x20 && p[i] < 0x7F) ? p[i] : '.'); printf("\n"); offset += line; p += line; } } FreeRDP-1.0.2/libfreerdp-utils/list.c000066400000000000000000000051321207112532300173310ustar00rootroot00000000000000/** * FreeRDP: A Remote Desktop Protocol Client * Double-linked List Utils * * Copyright 2011 Vic Lee * * 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. */ #include #include #include #include #include static LIST_ITEM* list_item_new(void* data) { LIST_ITEM* item; item = xnew(LIST_ITEM); item->data = data; return item; } static LIST_ITEM* list_item_find(LIST* list, void* data) { LIST_ITEM* item; for (item = list->head; item; item = item->next) { if (item->data == data) return item; } return NULL; } LIST* list_new(void) { LIST* list; list = xnew(LIST); list->count = 0; return list; } void list_free(LIST* list) { while (list->head) list_dequeue(list); xfree(list); } void list_enqueue(LIST* list, void* data) { LIST_ITEM* item; item = list_item_new(data); if (list->tail == NULL) { list->head = item; list->tail = item; } else { item->prev = list->tail; list->tail->next = item; list->tail = item; } list->count++; } void* list_dequeue(LIST* list) { LIST_ITEM* item; void* data = NULL; item = list->head; if (item != NULL) { list->head = item->next; if (list->head == NULL) list->tail = NULL; else list->head->prev = NULL; data = item->data; xfree(item); list->count--; } return data; } void* list_peek(LIST* list) { LIST_ITEM* item; item = list->head; return item ? item->data : NULL; } void* list_next(LIST* list, void* data) { LIST_ITEM* item; item = list_item_find(list, data); data = NULL; if (item != NULL) { if (item->next != NULL) data = item->next->data; } return data; } void* list_remove(LIST* list, void* data) { LIST_ITEM* item; item = list_item_find(list, data); if (item != NULL) { if (item->prev != NULL) item->prev->next = item->next; if (item->next != NULL) item->next->prev = item->prev; if (list->head == item) list->head = item->next; if (list->tail == item) list->tail = item->prev; xfree(item); list->count--; } else data = NULL; return data; } int list_size(LIST* list) { return list->count; } FreeRDP-1.0.2/libfreerdp-utils/load_plugin.c000066400000000000000000000106131207112532300206530ustar00rootroot00000000000000/** * FreeRDP: A Remote Desktop Protocol Client * Plugin Loading Utils * * Copyright 2011 Vic Lee * * 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. */ #include #include #include #include #include #include #include #ifdef _WIN32 #include #define DLOPEN(f) LoadLibraryA(f) #define DLSYM(f, n) GetProcAddress(f, n) #define DLCLOSE(f) FreeLibrary(f) #define DLERROR() "" #else #include #include #define DLOPEN(f) dlopen(f, RTLD_LOCAL | RTLD_LAZY) #define DLSYM(f, n) dlsym(f, n) #define DLCLOSE(f) dlclose(f) #define DLERROR() dlerror() #endif void* freerdp_open_library(const char* file) { void* library; library = DLOPEN(file); if (library == NULL) { printf("freerdp_load_library: failed to open %s: %s\n", file, DLERROR()); return NULL; } return library; } void* freerdp_get_library_symbol(void* library, const char* name) { void* symbol; symbol = DLSYM(library, name); if (symbol == NULL) { printf("freerdp_get_library_symbol: failed to load %s: %s\n", name, DLERROR()); return NULL; } return symbol; } boolean freerdp_close_library(void* library) { int status; status = DLCLOSE(library); #ifdef _WIN32 if (status != 0) #else if (status == 0) #endif { printf("freerdp_free_library: failed to close: %s\n", DLERROR()); return false; } return true; } void* freerdp_load_library_symbol(const char* file, const char* name) { void* library; void* symbol; library = DLOPEN(file); if (library == NULL) { printf("freerdp_load_library_symbol: failed to open %s: %s\n", file, DLERROR()); return NULL; } symbol = DLSYM(library, name); if (symbol == NULL) { printf("freerdp_load_library_symbol: failed to load %s: %s\n", file, DLERROR()); return NULL; } return symbol; } void* freerdp_load_plugin(const char* name, const char* entry_name) { char* path; void* entry; char* suffixed_name; suffixed_name = freerdp_append_shared_library_suffix((char*) name); if (!freerdp_path_contains_separator(suffixed_name)) { /* no explicit path given, use default path */ path = freerdp_construct_path(PLUGIN_PATH, suffixed_name); } else { /* explicit path given, use it instead of default path */ path = xstrdup(suffixed_name); } entry = freerdp_load_library_symbol(path, entry_name); xfree(suffixed_name); xfree(path); if (entry == NULL) { printf("freerdp_load_plugin: failed to load %s/%s\n", name, entry_name); return NULL; } return entry; } void* freerdp_load_channel_plugin(rdpSettings* settings, const char* name, const char* entry_name) { char* path; void* entry; char* suffixed_name; suffixed_name = freerdp_append_shared_library_suffix((char*) name); if (!freerdp_path_contains_separator(suffixed_name)) { /* no explicit path given, use default path */ if (!settings->development_mode) { path = freerdp_construct_path(PLUGIN_PATH, suffixed_name); } else { char* dot; char* plugin_name; char* channels_path; char* channel_subpath; dot = strrchr(suffixed_name, '.'); plugin_name = xmalloc((dot - suffixed_name) + 1); strncpy(plugin_name, suffixed_name, (dot - suffixed_name)); plugin_name[(dot - suffixed_name)] = '\0'; channels_path = freerdp_construct_path(settings->development_path, "channels"); channel_subpath = freerdp_construct_path(channels_path, plugin_name); path = freerdp_construct_path(channel_subpath, suffixed_name); xfree(plugin_name); xfree(channels_path); xfree(channel_subpath); } } else { /* explicit path given, use it instead of default path */ path = xstrdup(suffixed_name); } entry = freerdp_load_library_symbol(path, entry_name); xfree(suffixed_name); xfree(path); if (entry == NULL) { printf("freerdp_load_channel_plugin: failed to load %s/%s\n", name, entry_name); return NULL; } return entry; } FreeRDP-1.0.2/libfreerdp-utils/memory.c000066400000000000000000000037231207112532300176720ustar00rootroot00000000000000/** * FreeRDP: A Remote Desktop Protocol Client * Memory Utils * * Copyright 2009-2011 Jay Sorg * * 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. */ #include #include #include #include /** * Allocate memory. * @param size */ void* xmalloc(size_t size) { void* mem; if (size < 1) size = 1; mem = malloc(size); if (mem == NULL) { perror("xmalloc"); printf("xmalloc: failed to allocate memory of size: %d\n", (int) size); } return mem; } /** * Allocate memory initialized to zero. * @param size */ void* xzalloc(size_t size) { void* mem; if (size < 1) size = 1; mem = calloc(1, size); if (mem == NULL) { perror("xzalloc"); printf("xzalloc: failed to allocate memory of size: %d\n", (int) size); } return mem; } /** * Reallocate memory. * @param ptr * @param size */ void* xrealloc(void* ptr, size_t size) { void* mem; if (size < 1) size = 1; if (ptr == NULL) { printf("xrealloc: null pointer given\n"); return NULL; } mem = realloc(ptr, size); if (mem == NULL) perror("xrealloc"); return mem; } /** * Free memory. * @param mem */ void xfree(void* ptr) { if (ptr != NULL) free(ptr); } /** * Duplicate a string in memory. * @param str * @return */ char* xstrdup(const char* str) { char* mem; if (str == NULL) return NULL; #ifdef _WIN32 mem = _strdup(str); #else mem = strdup(str); #endif if (mem == NULL) perror("strdup"); return mem; } FreeRDP-1.0.2/libfreerdp-utils/mutex.c000066400000000000000000000031311207112532300175150ustar00rootroot00000000000000/** * FreeRDP: A Remote Desktop Protocol Client * Mutex Utils * * Copyright 2011 Vic Lee * * 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. */ #include #include #ifdef _WIN32 #include #define freerdp_mutex_t HANDLE #else #include #define freerdp_mutex_t pthread_mutex_t #endif freerdp_mutex freerdp_mutex_new(void) { #ifdef _WIN32 freerdp_mutex_t mutex; mutex = CreateMutex(NULL, FALSE, NULL); return (freerdp_mutex) mutex; #else freerdp_mutex_t* mutex; mutex = xnew(freerdp_mutex_t); pthread_mutex_init(mutex, 0); return mutex; #endif } void freerdp_mutex_free(freerdp_mutex mutex) { #ifdef _WIN32 CloseHandle((freerdp_mutex_t) mutex); #else pthread_mutex_destroy((freerdp_mutex_t*) mutex); xfree(mutex); #endif } void freerdp_mutex_lock(freerdp_mutex mutex) { #ifdef _WIN32 WaitForSingleObject((freerdp_mutex_t) mutex, INFINITE); #else pthread_mutex_lock(mutex); #endif } void freerdp_mutex_unlock(freerdp_mutex mutex) { #ifdef _WIN32 ReleaseMutex((freerdp_mutex_t) mutex); #else pthread_mutex_unlock(mutex); #endif } FreeRDP-1.0.2/libfreerdp-utils/passphrase.c000066400000000000000000000054071207112532300205340ustar00rootroot00000000000000/** * FreeRDP: A Remote Desktop Protocol Client * Passphrase Handling Utils * * Copyright 2011 Shea Levy * * 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. */ #include #include #ifdef _WIN32 char* freerdp_passphrase_read(const char* prompt, char* buf, size_t bufsiz, int from_stdin) { errno=ENOSYS; return NULL; } #else #include #include #include #include #include #include #include char* freerdp_passphrase_read(const char* prompt, char* buf, size_t bufsiz, int from_stdin) { char read_char; char* buf_iter; char term_name[L_ctermid]; int term_file, write_file; ssize_t nbytes; size_t read_bytes = 0; if (bufsiz == 0) { errno = EINVAL; return NULL; } ctermid(term_name); if(from_stdin || strcmp(term_name, "") == 0 || (term_file = open(term_name, O_RDWR)) == -1) { write_file = STDERR_FILENO; terminal_fildes = STDIN_FILENO; } else { write_file = term_file; terminal_fildes = term_file; } if (tcgetattr(terminal_fildes, &orig_flags) != -1) { new_flags = orig_flags; new_flags.c_lflag &= ~ECHO; new_flags.c_lflag |= ECHONL; terminal_needs_reset = 1; if (tcsetattr(terminal_fildes, TCSAFLUSH, &new_flags) == -1) terminal_needs_reset = 0; } if (write(write_file, prompt, strlen(prompt)) == (ssize_t) -1) goto error; buf_iter = buf; while ((nbytes = read(terminal_fildes, &read_char, sizeof read_char)) == (sizeof read_char)) { if (read_char == '\n') break; if (read_bytes < (bufsiz - (size_t) 1)) { read_bytes++; *buf_iter = read_char; buf_iter++; } } *buf_iter = '\0'; buf_iter = NULL; read_char = '\0'; if (nbytes == (ssize_t) -1) goto error; if (terminal_needs_reset) { if (tcsetattr(terminal_fildes, TCSAFLUSH, &orig_flags) == -1) goto error; terminal_needs_reset = 0; } if (terminal_fildes != STDIN_FILENO) { if (close(terminal_fildes) == -1) goto error; } return buf; error: { int saved_errno = errno; buf_iter = NULL; read_char = '\0'; if (terminal_needs_reset) tcsetattr(terminal_fildes, TCSAFLUSH, &orig_flags); if (terminal_fildes != STDIN_FILENO) close(terminal_fildes); errno = saved_errno; return NULL; } } #endif FreeRDP-1.0.2/libfreerdp-utils/pcap.c000066400000000000000000000112071207112532300173010ustar00rootroot00000000000000/** * FreeRDP: A Remote Desktop Protocol Client * pcap File Format Utils * * Copyright 2011 Marc-Andre Moreau * * 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. */ #include #include #ifndef _WIN32 #include #else #include #include #if !defined(__MINGW32__) && !defined(__MINGW64__) struct timeval { long tv_sec; long tv_usec; }; #endif int gettimeofday(struct timeval* tp, void* tz) { struct _timeb timebuffer; _ftime (&timebuffer); tp->tv_sec = (long) timebuffer.time; tp->tv_usec = timebuffer.millitm * 1000; return 0; } #endif #include #include #include #define PCAP_MAGIC 0xA1B2C3D4 void pcap_read_header(rdpPcap* pcap, pcap_header* header) { fread((void*) header, sizeof(pcap_header), 1, pcap->fp); } void pcap_write_header(rdpPcap* pcap, pcap_header* header) { fwrite((void*) header, sizeof(pcap_header), 1, pcap->fp); } void pcap_read_record_header(rdpPcap* pcap, pcap_record_header* record) { fread((void*) record, sizeof(pcap_record_header), 1, pcap->fp); } void pcap_write_record_header(rdpPcap* pcap, pcap_record_header* record) { fwrite((void*) record, sizeof(pcap_record_header), 1, pcap->fp); } void pcap_read_record(rdpPcap* pcap, pcap_record* record) { pcap_read_record_header(pcap, &record->header); record->length = record->header.incl_len; record->data = xmalloc(record->length); fread(record->data, record->length, 1, pcap->fp); } void pcap_write_record(rdpPcap* pcap, pcap_record* record) { pcap_write_record_header(pcap, &record->header); fwrite(record->data, record->length, 1, pcap->fp); } void pcap_add_record(rdpPcap* pcap, void* data, uint32 length) { pcap_record* record; struct timeval tp; if (pcap->tail == NULL) { pcap->tail = (pcap_record*) xzalloc(sizeof(pcap_record)); pcap->head = pcap->tail; pcap->record = pcap->head; record = pcap->tail; } else { record = (pcap_record*) xzalloc(sizeof(pcap_record)); pcap->tail->next = record; pcap->tail = record; } if (pcap->record == NULL) pcap->record = record; record->data = data; record->length = length; record->header.incl_len = length; record->header.orig_len = length; gettimeofday(&tp, 0); record->header.ts_sec = tp.tv_sec; record->header.ts_usec = tp.tv_usec; } boolean pcap_has_next_record(rdpPcap* pcap) { if (pcap->file_size - (ftell(pcap->fp)) <= 16) return false; return true; } boolean pcap_get_next_record_header(rdpPcap* pcap, pcap_record* record) { if (pcap_has_next_record(pcap) != true) return false; pcap_read_record_header(pcap, &record->header); record->length = record->header.incl_len; record->data = xmalloc(record->length); return true; } boolean pcap_get_next_record_content(rdpPcap* pcap, pcap_record* record) { fread(record->data, record->length, 1, pcap->fp); return true; } boolean pcap_get_next_record(rdpPcap* pcap, pcap_record* record) { if (pcap_has_next_record(pcap) != true) return false; pcap_read_record(pcap, record); return true; } rdpPcap* pcap_open(char* name, boolean write) { rdpPcap* pcap; FILE *pcap_fp = fopen(name, write ? "w+" : "r"); if (pcap_fp == NULL) { perror("opening pcap dump"); return NULL; } pcap = (rdpPcap*) xzalloc(sizeof(rdpPcap)); if (pcap != NULL) { pcap->name = name; pcap->write = write; pcap->record_count = 0; pcap->fp = pcap_fp; if (write) { pcap->header.magic_number = 0xA1B2C3D4; pcap->header.version_major = 2; pcap->header.version_minor = 4; pcap->header.thiszone = 0; pcap->header.sigfigs = 0; pcap->header.snaplen = 0xFFFFFFFF; pcap->header.network = 0; pcap_write_header(pcap, &pcap->header); } else { fseek(pcap->fp, 0, SEEK_END); pcap->file_size = (int) ftell(pcap->fp); fseek(pcap->fp, 0, SEEK_SET); pcap_read_header(pcap, &pcap->header); } } return pcap; } void pcap_flush(rdpPcap* pcap) { while (pcap->record != NULL) { pcap_write_record(pcap, pcap->record); pcap->record = pcap->record->next; } if (pcap->fp != NULL) fflush(pcap->fp); } void pcap_close(rdpPcap* pcap) { pcap_flush(pcap); if (pcap->fp != NULL) fclose(pcap->fp); } FreeRDP-1.0.2/libfreerdp-utils/profiler.c000066400000000000000000000040501207112532300201760ustar00rootroot00000000000000/** * FreeRDP: A Remote Desktop Protocol Client * Profiler Utils * * Copyright 2011 Stephen Erisman * * 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. */ #include PROFILER* profiler_create(char* name) { PROFILER* profiler; profiler = (PROFILER*) xmalloc(sizeof(PROFILER)); profiler->name = name; profiler->stopwatch = stopwatch_create(); return profiler; } void profiler_free(PROFILER* profiler) { stopwatch_free(profiler->stopwatch); xfree(profiler); } void profiler_enter(PROFILER* profiler) { stopwatch_start(profiler->stopwatch); } void profiler_exit(PROFILER* profiler) { stopwatch_stop(profiler->stopwatch); } void profiler_print_header() { printf("\n"); printf(" |-----------------------|\n" ); printf(" PROFILER | elapsed seconds |\n" ); printf("|--------------------------------------------|-----------------------|\n" ); printf("| code section | iterations | total | avg. |\n" ); printf("|-------------------------------|------------|-----------|-----------|\n" ); } void profiler_print(PROFILER* profiler) { double elapsed_sec = stopwatch_get_elapsed_time_in_seconds(profiler->stopwatch); double avg_sec = elapsed_sec / (double) profiler->stopwatch->count; printf("| %-30.30s| %'10lu | %'9f | %'9f |\n", profiler->name, profiler->stopwatch->count, elapsed_sec, avg_sec); } void profiler_print_footer() { printf("|--------------------------------------------------------------------|\n" ); } FreeRDP-1.0.2/libfreerdp-utils/rail.c000066400000000000000000000145741207112532300173170ustar00rootroot00000000000000/** * FreeRDP: A Remote Desktop Protocol Client * Remote Applications Integrated Locally (RAIL) Utils * * Copyright 2011 Marc-Andre Moreau * * 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. */ #include #include #include #include void rail_unicode_string_alloc(UNICODE_STRING* unicode_string, uint16 cbString) { unicode_string->length = cbString; unicode_string->string = xzalloc(cbString); } void rail_unicode_string_free(UNICODE_STRING* unicode_string) { unicode_string->length = 0; if (unicode_string->string != NULL) xfree(unicode_string->string); } void rail_read_unicode_string(STREAM* s, UNICODE_STRING* unicode_string) { stream_read_uint16(s, unicode_string->length); /* cbString (2 bytes) */ if (unicode_string->string == NULL) unicode_string->string = (uint8*) xmalloc(unicode_string->length); else unicode_string->string = (uint8*) xrealloc(unicode_string->string, unicode_string->length); stream_read(s, unicode_string->string, unicode_string->length); } void rail_write_unicode_string(STREAM* s, UNICODE_STRING* unicode_string) { stream_check_size(s, 2 + unicode_string->length); stream_write_uint16(s, unicode_string->length); /* cbString (2 bytes) */ stream_write(s, unicode_string->string, unicode_string->length); /* string */ } void rail_write_unicode_string_value(STREAM* s, UNICODE_STRING* unicode_string) { if (unicode_string->length > 0) { stream_check_size(s, unicode_string->length); stream_write(s, unicode_string->string, unicode_string->length); /* string */ } } void rail_read_rectangle_16(STREAM* s, RECTANGLE_16* rectangle_16) { stream_read_uint16(s, rectangle_16->left); /* left (2 bytes) */ stream_read_uint16(s, rectangle_16->top); /* top (2 bytes) */ stream_read_uint16(s, rectangle_16->right); /* right (2 bytes) */ stream_read_uint16(s, rectangle_16->bottom); /* bottom (2 bytes) */ } void rail_write_rectangle_16(STREAM* s, RECTANGLE_16* rectangle_16) { stream_write_uint16(s, rectangle_16->left); /* left (2 bytes) */ stream_write_uint16(s, rectangle_16->top); /* top (2 bytes) */ stream_write_uint16(s, rectangle_16->right); /* right (2 bytes) */ stream_write_uint16(s, rectangle_16->bottom); /* bottom (2 bytes) */ } void* rail_clone_order(uint32 event_type, void* order) { struct { uint32 type; uint32 size; } ordersize_table[] = { {RDP_EVENT_TYPE_RAIL_CHANNEL_GET_SYSPARAMS, sizeof(RAIL_SYSPARAM_ORDER)}, {RDP_EVENT_TYPE_RAIL_CHANNEL_EXEC_RESULTS, sizeof(RAIL_EXEC_RESULT_ORDER)}, {RDP_EVENT_TYPE_RAIL_CHANNEL_SERVER_SYSPARAM, sizeof(RAIL_SYSPARAM_ORDER)}, {RDP_EVENT_TYPE_RAIL_CHANNEL_SERVER_MINMAXINFO, sizeof(RAIL_MINMAXINFO_ORDER)}, {RDP_EVENT_TYPE_RAIL_CHANNEL_SERVER_LOCALMOVESIZE, sizeof(RAIL_LOCALMOVESIZE_ORDER)}, {RDP_EVENT_TYPE_RAIL_CHANNEL_APPID_RESP, sizeof(RAIL_GET_APPID_RESP_ORDER)}, {RDP_EVENT_TYPE_RAIL_CHANNEL_LANGBARINFO, sizeof(RAIL_LANGBAR_INFO_ORDER)}, {RDP_EVENT_TYPE_RAIL_CLIENT_SET_SYSPARAMS, sizeof(RAIL_SYSPARAM_ORDER)}, {RDP_EVENT_TYPE_RAIL_CLIENT_EXEC_REMOTE_APP, sizeof(RDP_PLUGIN_DATA)}, {RDP_EVENT_TYPE_RAIL_CLIENT_ACTIVATE, sizeof(RAIL_ACTIVATE_ORDER)}, {RDP_EVENT_TYPE_RAIL_CLIENT_SYSMENU, sizeof(RAIL_SYSMENU_ORDER)}, {RDP_EVENT_TYPE_RAIL_CLIENT_SYSCOMMAND, sizeof(RAIL_SYSCOMMAND_ORDER)}, {RDP_EVENT_TYPE_RAIL_CLIENT_NOTIFY_EVENT, sizeof(RAIL_NOTIFY_EVENT_ORDER)}, {RDP_EVENT_TYPE_RAIL_CLIENT_WINDOW_MOVE, sizeof(RAIL_WINDOW_MOVE_ORDER)}, {RDP_EVENT_TYPE_RAIL_CLIENT_APPID_REQ, sizeof(RAIL_GET_APPID_REQ_ORDER)}, {RDP_EVENT_TYPE_RAIL_CLIENT_LANGBARINFO, sizeof(RAIL_LANGBAR_INFO_ORDER)}, }; size_t i = 0; size_t order_size = 0; void* new_order = NULL; for (i = 0; i < RAIL_ARRAY_SIZE(ordersize_table); i++) { if (event_type == ordersize_table[i].type) { order_size = ordersize_table[i].size; break; } } // Event type not found. if (order_size == 0) return NULL; new_order = xmalloc(order_size); memcpy(new_order, order, order_size); //printf("rail_clone_order: type=%d order=%p\n", event_type, new_order); // Create copy of variable data for some orders if ((event_type == RDP_EVENT_TYPE_RAIL_CHANNEL_GET_SYSPARAMS) || (event_type == RDP_EVENT_TYPE_RAIL_CLIENT_SET_SYSPARAMS)) { RAIL_SYSPARAM_ORDER* new_sysparam = (RAIL_SYSPARAM_ORDER*)new_order; RAIL_SYSPARAM_ORDER* old_sysparam = (RAIL_SYSPARAM_ORDER*)order; rail_unicode_string_alloc(&new_sysparam->highContrast.colorScheme, old_sysparam->highContrast.colorScheme.length); memcpy(new_sysparam->highContrast.colorScheme.string, old_sysparam->highContrast.colorScheme.string, old_sysparam->highContrast.colorScheme.length); } if (event_type == RDP_EVENT_TYPE_RAIL_CHANNEL_EXEC_RESULTS) { RAIL_EXEC_RESULT_ORDER* new_exec_result = (RAIL_EXEC_RESULT_ORDER*)new_order; RAIL_EXEC_RESULT_ORDER* old_exec_result = (RAIL_EXEC_RESULT_ORDER*)order; rail_unicode_string_alloc(&new_exec_result->exeOrFile, old_exec_result->exeOrFile.length); memcpy(new_exec_result->exeOrFile.string, old_exec_result->exeOrFile.string, old_exec_result->exeOrFile.length); } if (event_type == RDP_EVENT_TYPE_RAIL_CHANNEL_APPID_RESP) { RAIL_GET_APPID_RESP_ORDER* new_app_resp = (RAIL_GET_APPID_RESP_ORDER*)new_order; new_app_resp->applicationId.string = &new_app_resp->applicationIdBuffer[0]; } return new_order; } void rail_free_cloned_order(uint32 event_type, void* order) { //printf("rail_free_cloned_order: type=%d order=%p\n", event_type, order); if ((event_type == RDP_EVENT_TYPE_RAIL_CHANNEL_GET_SYSPARAMS) || (event_type == RDP_EVENT_TYPE_RAIL_CLIENT_SET_SYSPARAMS)) { RAIL_SYSPARAM_ORDER* sysparam = (RAIL_SYSPARAM_ORDER*)order; rail_unicode_string_free(&sysparam->highContrast.colorScheme); } if (event_type == RDP_EVENT_TYPE_RAIL_CHANNEL_EXEC_RESULTS) { RAIL_EXEC_RESULT_ORDER* exec_result = (RAIL_EXEC_RESULT_ORDER*)order; rail_unicode_string_free(&exec_result->exeOrFile); } xfree(order); } FreeRDP-1.0.2/libfreerdp-utils/rect.c000066400000000000000000000034721207112532300173200ustar00rootroot00000000000000/** * FreeRDP: A Remote Desktop Protocol Client * Rectangle Utils * * Copyright 2011 Marc-Andre Moreau * * 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. */ #include #include #include void freerdp_read_rectangle_16(STREAM* s, RECTANGLE_16* rectangle_16) { stream_read_uint16(s, rectangle_16->left); /* left (2 bytes) */ stream_read_uint16(s, rectangle_16->top); /* top (2 bytes) */ stream_read_uint16(s, rectangle_16->right); /* right (2 bytes) */ stream_read_uint16(s, rectangle_16->bottom); /* bottom (2 bytes) */ } void freerdp_write_rectangle_16(STREAM* s, RECTANGLE_16* rectangle_16) { stream_write_uint16(s, rectangle_16->left); /* left (2 bytes) */ stream_write_uint16(s, rectangle_16->top); /* top (2 bytes) */ stream_write_uint16(s, rectangle_16->right); /* right (2 bytes) */ stream_write_uint16(s, rectangle_16->bottom); /* bottom (2 bytes) */ } RECTANGLE_16* freerdp_rectangle_16_new(uint16 left, uint16 top, uint16 right, uint16 bottom) { RECTANGLE_16* rectangle_16 = xnew(RECTANGLE_16); rectangle_16->left = left; rectangle_16->top = top; rectangle_16->right = right; rectangle_16->bottom = bottom; return rectangle_16; } void freerdp_rectangle_16_free(RECTANGLE_16* rectangle_16) { xfree(rectangle_16); } FreeRDP-1.0.2/libfreerdp-utils/registry.c000066400000000000000000000104221207112532300202240ustar00rootroot00000000000000/** * FreeRDP: A Remote Desktop Protocol Client * Registry Utils * * Copyright 2011 Marc-Andre Moreau * * 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. */ #include #include static const char registry_dir[] = "freerdp"; static const char registry_file[] = "config.txt"; static REG_SECTION global[] = { { REG_TYPE_SECTION, "global", 0, NULL }, { REG_TYPE_BOOLEAN, "fast_path", 1, "1" }, { REG_TYPE_STRING, "resolution", 8, "1024x768" }, { REG_TYPE_INTEGER, "performance_flags", 4, "0xFFFF" }, { REG_TYPE_NONE, "", 0, NULL } }; static REG_SECTION licensing[] = { { REG_TYPE_SECTION, "licensing", 0, NULL }, { REG_TYPE_STRING, "platform_id", 1, "0x000201" }, { REG_TYPE_STRING, "hardware_id", 16, "0xe107d9d372bb6826bd81d3542a419d6" }, { REG_TYPE_NONE, "", 0, NULL } }; static REG_SECTION* sections[] = { (REG_SECTION*) &global, (REG_SECTION*) &licensing, (REG_SECTION*) NULL }; void registry_print_entry(REG_ENTRY* entry, FILE* fp) { uint8* value; value = (uint8*) entry->value; fprintf(fp, "%s = %s\n", entry->name, value); } void registry_print_section(REG_SECTION* section, FILE* fp) { int i = 0; REG_ENTRY* entries = (REG_ENTRY*) §ion[1]; fprintf(fp, "\n"); fprintf(fp, "[%s]\n", section->name); while (entries[i].type != REG_TYPE_NONE) { registry_print_entry(&entries[i], fp); i++; } } void registry_print(rdpRegistry* registry, FILE* fp) { int i = 0; fprintf(fp, "# FreeRDP Configuration Registry\n"); while (sections[i] != NULL) { registry_print_section(sections[i], fp); i++; } fprintf(fp, "\n"); } void registry_create(rdpRegistry* registry) { registry->fp = fopen((char*)registry->file, "w+"); if (registry->fp == NULL) { printf("registry_create: error opening [%s] for writing\n", registry->file); return; } registry_print(registry, registry->fp); fflush(registry->fp); } void registry_load(rdpRegistry* registry) { registry->fp = fopen((char*) registry->file, "r+"); } void registry_open(rdpRegistry* registry) { struct stat stat_info; if (stat((char*)registry->file, &stat_info) != 0) registry_create(registry); else registry_load(registry); } void registry_close(rdpRegistry* registry) { if (registry->fp != NULL) fclose(registry->fp); } void registry_init(rdpRegistry* registry) { int length; char* home_path; struct stat stat_info; if (registry->settings->home_path == NULL) home_path = getenv("HOME"); else home_path = registry->settings->home_path; if (home_path == NULL) { printf("could not get home path\n"); registry->available = false; return; } registry->available = true; registry->home = (char*) xstrdup(home_path); printf("home path: %s\n", registry->home); registry->path = (char*) xmalloc(strlen(registry->home) + strlen("/.") + strlen(registry_dir) + 1); sprintf(registry->path, "%s/.%s", registry->home, registry_dir); printf("registry path: %s\n", registry->path); if (stat(registry->path, &stat_info) != 0) { freerdp_mkdir(registry->path); printf("creating directory %s\n", registry->path); } length = strlen(registry->path); registry->file = (char*) xmalloc(strlen(registry->path) + strlen("/") + strlen(registry_file) + 1); sprintf(registry->file, "%s/%s", registry->path, registry_file); printf("registry file: %s\n", registry->file); registry_open(registry); } rdpRegistry* registry_new(rdpSettings* settings) { rdpRegistry* registry = (rdpRegistry*) xzalloc(sizeof(rdpRegistry)); if (registry != NULL) { registry->settings = settings; registry_init(registry); } return registry; } void registry_free(rdpRegistry* registry) { if (registry != NULL) { registry_close(registry); xfree(registry->path); xfree(registry->file); xfree(registry->home); xfree(registry); } } FreeRDP-1.0.2/libfreerdp-utils/semaphore.c000066400000000000000000000040741207112532300203450ustar00rootroot00000000000000/** * FreeRDP: A Remote Desktop Protocol Client * Semaphore Utils * * Copyright 2011 Marc-Andre Moreau * * 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. */ #include #include #if defined __APPLE__ #include #include #include #include #include #define freerdp_sem_t semaphore_t #elif defined _WIN32 #include #define freerdp_sem_t HANDLE #else #include #include #define freerdp_sem_t sem_t #endif freerdp_sem freerdp_sem_new(int iv) { freerdp_sem_t* sem; sem = xnew(freerdp_sem_t); #if defined __APPLE__ semaphore_create(mach_task_self(), sem, SYNC_POLICY_FIFO, iv); #elif defined _WIN32 *sem = CreateSemaphore(NULL, 0, iv, NULL); #else sem_init(sem, 0, iv); #endif return sem; } void freerdp_sem_free(freerdp_sem sem) { #if defined __APPLE__ semaphore_destroy(mach_task_self(), *((freerdp_sem_t*)sem)); #elif defined _WIN32 CloseHandle(*((freerdp_sem_t*)sem)); #else sem_destroy((freerdp_sem_t*)sem); #endif xfree(sem); } void freerdp_sem_signal(freerdp_sem sem) { #if defined __APPLE__ semaphore_signal(*((freerdp_sem_t*)sem)); #elif defined _WIN32 ReleaseSemaphore(*((freerdp_sem_t*)sem), 1, NULL); #else sem_post((freerdp_sem_t*)sem); #endif } void freerdp_sem_wait(freerdp_sem sem) { #if defined __APPLE__ semaphore_wait(*((freerdp_sem_t*)sem)); #elif defined _WIN32 WaitForSingleObject(*((freerdp_sem_t*)sem), INFINITE); #else sem_wait((freerdp_sem_t*)sem); #endif } FreeRDP-1.0.2/libfreerdp-utils/signal.c000066400000000000000000000050131207112532300176310ustar00rootroot00000000000000/** * FreeRDP: A Remote Desktop Protocol Client * Signal handling * * Copyright 2011 Shea Levy * * 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. */ #include #include #ifdef _WIN32 #include int freerdp_handle_signals(void) { errno = ENOSYS; return -1; } #else volatile sig_atomic_t terminal_needs_reset = 0; int terminal_fildes = 0; struct termios orig_flags; struct termios new_flags; static void fatal_handler(int signum) { struct sigaction default_sigaction; sigset_t this_mask; if (terminal_needs_reset) tcsetattr(terminal_fildes, TCSAFLUSH, &orig_flags); default_sigaction.sa_handler = SIG_DFL; sigfillset(&(default_sigaction.sa_mask)); default_sigaction.sa_flags = 0; sigaction(signum, &default_sigaction, NULL); sigemptyset(&this_mask); sigaddset(&this_mask, signum); pthread_sigmask(SIG_UNBLOCK, &this_mask, NULL); raise(signum); } int freerdp_handle_signals(void) { const int fatal_signals[] = { SIGABRT, SIGALRM, SIGBUS, SIGFPE, SIGHUP, SIGILL, SIGINT, SIGKILL, SIGPIPE, SIGQUIT, SIGSEGV, SIGSTOP, SIGTERM, SIGTSTP, SIGTTIN, SIGTTOU, SIGUSR1, SIGUSR2, #ifdef SIGPOLL SIGPOLL, #endif #ifdef SIGPROF SIGPROF, #endif #ifdef SIGSYS SIGSYS, #endif SIGTRAP, #ifdef SIGVTALRM SIGVTALRM, #endif SIGXCPU, SIGXFSZ }; int signal_index; sigset_t orig_set; struct sigaction orig_sigaction, fatal_sigaction; sigfillset(&(fatal_sigaction.sa_mask)); sigdelset(&(fatal_sigaction.sa_mask), SIGCONT); pthread_sigmask(SIG_BLOCK, &(fatal_sigaction.sa_mask), &orig_set); fatal_sigaction.sa_handler = fatal_handler; fatal_sigaction.sa_flags = 0; for (signal_index = 0; signal_index < (sizeof fatal_signals / sizeof fatal_signals[0]); signal_index++) if (sigaction(fatal_signals[signal_index], NULL, &orig_sigaction) == 0) if (orig_sigaction.sa_handler != SIG_IGN) sigaction(fatal_signals[signal_index], &fatal_sigaction, NULL); pthread_sigmask(SIG_SETMASK, &orig_set, NULL); return 0; } #endif FreeRDP-1.0.2/libfreerdp-utils/sleep.c000066400000000000000000000023651207112532300174730ustar00rootroot00000000000000/** * FreeRDP: A Remote Desktop Protocol Client * Sleep Utils * * Copyright 2011 Marc-Andre Moreau * * 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. */ #include #include #ifndef _WIN32 #define _XOPEN_SOURCE 500 #include #else #include #endif void freerdp_sleep(uint32 seconds) { #ifndef _WIN32 sleep(seconds); #else Sleep(seconds * 1000); #endif } void freerdp_usleep(uint32 useconds) { #ifndef _WIN32 usleep(useconds); #else uint64 t1; uint64 t2; uint64 freq; QueryPerformanceCounter((LARGE_INTEGER*) &t1); QueryPerformanceCounter((LARGE_INTEGER*) &freq); do { QueryPerformanceCounter((LARGE_INTEGER*) &t2); } while ((t2 - t1) < useconds); #endif } FreeRDP-1.0.2/libfreerdp-utils/stopwatch.c000066400000000000000000000034301207112532300203710ustar00rootroot00000000000000/** * FreeRDP: A Remote Desktop Protocol Client * Stopwatch Utils * * Copyright 2011 Stephen Erisman * * 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. */ #include STOPWATCH* stopwatch_create() { STOPWATCH* sw; sw = (STOPWATCH*) xmalloc(sizeof(STOPWATCH)); stopwatch_reset(sw); return sw; } void stopwatch_free(STOPWATCH* stopwatch) { xfree(stopwatch); } void stopwatch_start(STOPWATCH* stopwatch) { stopwatch->start = clock(); stopwatch->count++; } void stopwatch_stop(STOPWATCH* stopwatch) { stopwatch->end = clock(); stopwatch->elapsed += (stopwatch->end - stopwatch->start); } void stopwatch_reset(STOPWATCH* stopwatch) { stopwatch->start = 0; stopwatch->end = 0; stopwatch->elapsed = 0; stopwatch->count = 0; } double stopwatch_get_elapsed_time_in_seconds(STOPWATCH* stopwatch) { return ((double) stopwatch->elapsed) / CLOCKS_PER_SEC; } void stopwatch_get_elapsed_time_in_useconds(STOPWATCH* stopwatch, uint32* sec, uint32* usec) { double uelapsed; double clocks_per_usec; *sec = ((uint32) stopwatch->elapsed) / CLOCKS_PER_SEC; uelapsed = stopwatch->elapsed - ((double)(*sec) * CLOCKS_PER_SEC); clocks_per_usec = (CLOCKS_PER_SEC / 1000000); if (clocks_per_usec > 0.0) *usec = (uint32)(uelapsed / clocks_per_usec); else *usec = 0; } FreeRDP-1.0.2/libfreerdp-utils/stream.c000066400000000000000000000032641207112532300176550ustar00rootroot00000000000000/** * FreeRDP: A Remote Desktop Protocol Client * Stream Utils * * Copyright 2011 Vic Lee * * 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. */ #include #include #include #include #include STREAM* stream_new(int size) { STREAM* stream; stream = xnew(STREAM); if (stream != NULL) { if (size != 0) { size = size > 0 ? size : 0x400; stream->data = (uint8*) xzalloc(size); stream->p = stream->data; stream->size = size; } } return stream; } void stream_free(STREAM* stream) { if (stream != NULL) { if (stream->data != NULL) xfree(stream->data); xfree(stream); } } void stream_extend(STREAM* stream, int request_size) { int pos; int original_size; int increased_size; pos = stream_get_pos(stream); original_size = stream->size; increased_size = (request_size > original_size ? request_size : original_size); stream->size += increased_size; if (original_size == 0) stream->data = (uint8*) xmalloc(stream->size); else stream->data = (uint8*) xrealloc(stream->data, stream->size); memset(stream->data + original_size, 0, increased_size); stream_set_pos(stream, pos); } FreeRDP-1.0.2/libfreerdp-utils/string.c000066400000000000000000000023301207112532300176610ustar00rootroot00000000000000/** * FreeRDP: A Remote Desktop Protocol Client * String Utils * * Copyright 2011 Marc-Andre Moreau * * 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. */ #include #include void freerdp_string_read_length32(STREAM* s, rdpString* string, UNICONV* uniconv) { stream_read_uint32(s, string->length); string->unicode = (char*) xmalloc(string->length); stream_read(s, string->unicode, string->length); string->ascii = freerdp_uniconv_in(uniconv, (uint8*) string->unicode, string->length); } void freerdp_string_free(rdpString* string) { if (string->unicode != NULL) xfree(string->unicode); if (string->ascii != NULL) xfree(string->ascii); } FreeRDP-1.0.2/libfreerdp-utils/svc_plugin.c000066400000000000000000000242231207112532300205310ustar00rootroot00000000000000/** * FreeRDP: A Remote Desktop Protocol client. * Static Virtual Channel Interface * * Copyright 2009-2011 Jay Sorg * Copyright 2010-2011 Vic Lee * * 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. */ #include "config.h" #include #include #include #include #include #include #include #include #include #include #include #include /* The list of all plugin instances. */ typedef struct rdp_svc_plugin_list rdpSvcPluginList; struct rdp_svc_plugin_list { rdpSvcPlugin* plugin; rdpSvcPluginList* next; }; static rdpSvcPluginList* g_svc_plugin_list = NULL; /* For locking the global resources */ static freerdp_mutex g_mutex = NULL; /* Queue for receiving packets */ struct _svc_data_in_item { STREAM* data_in; RDP_EVENT* event_in; }; typedef struct _svc_data_in_item svc_data_in_item; static void svc_data_in_item_free(svc_data_in_item* item) { if (item->data_in) { stream_free(item->data_in); item->data_in = NULL; } if (item->event_in) { freerdp_event_free(item->event_in); item->event_in = NULL; } xfree(item); } struct rdp_svc_plugin_private { void* init_handle; uint32 open_handle; STREAM* data_in; LIST* data_in_list; freerdp_thread* thread; }; static rdpSvcPlugin* svc_plugin_find_by_init_handle(void* init_handle) { rdpSvcPluginList * list; rdpSvcPlugin * plugin; freerdp_mutex_lock(g_mutex); for (list = g_svc_plugin_list; list; list = list->next) { plugin = list->plugin; if (plugin->priv->init_handle == init_handle) { freerdp_mutex_unlock(g_mutex); return plugin; } } freerdp_mutex_unlock(g_mutex); return NULL; } static rdpSvcPlugin* svc_plugin_find_by_open_handle(uint32 open_handle) { rdpSvcPluginList * list; rdpSvcPlugin * plugin; freerdp_mutex_lock(g_mutex); for (list = g_svc_plugin_list; list; list = list->next) { plugin = list->plugin; if (plugin->priv->open_handle == open_handle) { freerdp_mutex_unlock(g_mutex); return plugin; } } freerdp_mutex_unlock(g_mutex); return NULL; } static void svc_plugin_remove(rdpSvcPlugin* plugin) { rdpSvcPluginList* list; rdpSvcPluginList* prev; /* Remove from global list */ freerdp_mutex_lock(g_mutex); for (prev = NULL, list = g_svc_plugin_list; list; prev = list, list = list->next) { if (list->plugin == plugin) break; } if (list) { if (prev) prev->next = list->next; else g_svc_plugin_list = list->next; xfree(list); } freerdp_mutex_unlock(g_mutex); } static void svc_plugin_process_received(rdpSvcPlugin* plugin, void* pData, uint32 dataLength, uint32 totalLength, uint32 dataFlags) { STREAM* data_in; svc_data_in_item* item; if ( (dataFlags & CHANNEL_FLAG_SUSPEND) || (dataFlags & CHANNEL_FLAG_RESUME)) { /* According to MS-RDPBCGR 2.2.6.1, "All virtual channel traffic MUST be suspended. This flag is only valid in server-to-client virtual channel traffic. It MUST be ignored in client-to-server data." Thus it would be best practice to cease data transmission. However, simply returing here avoids a crash. */ return; } if (dataFlags & CHANNEL_FLAG_FIRST) { if (plugin->priv->data_in != NULL) stream_free(plugin->priv->data_in); plugin->priv->data_in = stream_new(totalLength); } data_in = plugin->priv->data_in; stream_check_size(data_in, (int) dataLength); stream_write(data_in, pData, dataLength); if (dataFlags & CHANNEL_FLAG_LAST) { if (stream_get_size(data_in) != stream_get_length(data_in)) { printf("svc_plugin_process_received: read error\n"); } plugin->priv->data_in = NULL; stream_set_pos(data_in, 0); item = xnew(svc_data_in_item); item->data_in = data_in; freerdp_thread_lock(plugin->priv->thread); list_enqueue(plugin->priv->data_in_list, item); freerdp_thread_unlock(plugin->priv->thread); freerdp_thread_signal(plugin->priv->thread); } } static void svc_plugin_process_event(rdpSvcPlugin* plugin, RDP_EVENT* event_in) { svc_data_in_item* item; item = xnew(svc_data_in_item); item->event_in = event_in; freerdp_thread_lock(plugin->priv->thread); list_enqueue(plugin->priv->data_in_list, item); freerdp_thread_unlock(plugin->priv->thread); freerdp_thread_signal(plugin->priv->thread); } static void svc_plugin_open_event(uint32 openHandle, uint32 event, void* pData, uint32 dataLength, uint32 totalLength, uint32 dataFlags) { rdpSvcPlugin* plugin; DEBUG_SVC("openHandle %d event %d dataLength %d totalLength %d dataFlags %d", openHandle, event, dataLength, totalLength, dataFlags); plugin = (rdpSvcPlugin*)svc_plugin_find_by_open_handle(openHandle); if (plugin == NULL) { printf("svc_plugin_open_event: error no match\n"); return; } switch (event) { case CHANNEL_EVENT_DATA_RECEIVED: svc_plugin_process_received(plugin, pData, dataLength, totalLength, dataFlags); break; case CHANNEL_EVENT_WRITE_COMPLETE: stream_free((STREAM*)pData); break; case CHANNEL_EVENT_USER: svc_plugin_process_event(plugin, (RDP_EVENT*)pData); break; } } static void svc_plugin_process_data_in(rdpSvcPlugin* plugin) { svc_data_in_item* item; while (1) { /* terminate signal */ if (freerdp_thread_is_stopped(plugin->priv->thread)) break; freerdp_thread_lock(plugin->priv->thread); item = list_dequeue(plugin->priv->data_in_list); freerdp_thread_unlock(plugin->priv->thread); if (item != NULL) { /* the ownership of the data is passed to the callback */ if (item->data_in) IFCALL(plugin->receive_callback, plugin, item->data_in); if (item->event_in) IFCALL(plugin->event_callback, plugin, item->event_in); xfree(item); } else break; } } static void* svc_plugin_thread_func(void* arg) { rdpSvcPlugin* plugin = (rdpSvcPlugin*)arg; DEBUG_SVC("in"); IFCALL(plugin->connect_callback, plugin); while (1) { if (plugin->interval_ms > 0) freerdp_thread_wait_timeout(plugin->priv->thread, plugin->interval_ms); else freerdp_thread_wait(plugin->priv->thread); if (freerdp_thread_is_stopped(plugin->priv->thread)) break; freerdp_thread_reset(plugin->priv->thread); svc_plugin_process_data_in(plugin); if (plugin->interval_ms > 0) IFCALL(plugin->interval_callback, plugin); } freerdp_thread_quit(plugin->priv->thread); DEBUG_SVC("out"); return 0; } static void svc_plugin_process_connected(rdpSvcPlugin* plugin, void* pData, uint32 dataLength) { uint32 error; error = plugin->channel_entry_points.pVirtualChannelOpen(plugin->priv->init_handle, &plugin->priv->open_handle, plugin->channel_def.name, svc_plugin_open_event); if (error != CHANNEL_RC_OK) { printf("svc_plugin_process_connected: open failed\n"); return; } plugin->priv->data_in_list = list_new(); plugin->priv->thread = freerdp_thread_new(); freerdp_thread_start(plugin->priv->thread, svc_plugin_thread_func, plugin); } static void svc_plugin_process_terminated(rdpSvcPlugin* plugin) { svc_data_in_item* item; freerdp_thread_stop(plugin->priv->thread); freerdp_thread_free(plugin->priv->thread); plugin->channel_entry_points.pVirtualChannelClose(plugin->priv->open_handle); xfree(plugin->channel_entry_points.pExtendedData); svc_plugin_remove(plugin); while ((item = list_dequeue(plugin->priv->data_in_list)) != NULL) svc_data_in_item_free(item); list_free(plugin->priv->data_in_list); if (plugin->priv->data_in != NULL) { stream_free(plugin->priv->data_in); plugin->priv->data_in = NULL; } xfree(plugin->priv); plugin->priv = NULL; IFCALL(plugin->terminate_callback, plugin); } static void svc_plugin_init_event(void* pInitHandle, uint32 event, void* pData, uint32 dataLength) { rdpSvcPlugin* plugin; DEBUG_SVC("event %d", event); plugin = (rdpSvcPlugin*)svc_plugin_find_by_init_handle(pInitHandle); if (plugin == NULL) { printf("svc_plugin_init_event: error no match\n"); return; } switch (event) { case CHANNEL_EVENT_CONNECTED: svc_plugin_process_connected(plugin, pData, dataLength); break; case CHANNEL_EVENT_DISCONNECTED: break; case CHANNEL_EVENT_TERMINATED: svc_plugin_process_terminated(plugin); break; } } void svc_plugin_init(rdpSvcPlugin* plugin, CHANNEL_ENTRY_POINTS* pEntryPoints) { rdpSvcPluginList* list; /** * The channel manager will guarantee only one thread can call * VirtualChannelInit at a time. So this should be safe. */ if (g_mutex == NULL) g_mutex = freerdp_mutex_new(); memcpy(&plugin->channel_entry_points, pEntryPoints, pEntryPoints->cbSize); plugin->priv = xnew(rdpSvcPluginPrivate); /* Add it to the global list */ list = xnew(rdpSvcPluginList); list->plugin = plugin; freerdp_mutex_lock(g_mutex); list->next = g_svc_plugin_list; g_svc_plugin_list = list; freerdp_mutex_unlock(g_mutex); plugin->channel_entry_points.pVirtualChannelInit(&plugin->priv->init_handle, &plugin->channel_def, 1, VIRTUAL_CHANNEL_VERSION_WIN2000, svc_plugin_init_event); } int svc_plugin_send(rdpSvcPlugin* plugin, STREAM* data_out) { uint32 error = 0; DEBUG_SVC("length %d", stream_get_length(data_out)); error = plugin->channel_entry_points.pVirtualChannelWrite(plugin->priv->open_handle, stream_get_data(data_out), stream_get_length(data_out), data_out); if (error != CHANNEL_RC_OK) { stream_free(data_out); printf("svc_plugin_send: VirtualChannelWrite failed %d\n", error); } return error; } int svc_plugin_send_event(rdpSvcPlugin* plugin, RDP_EVENT* event) { uint32 error = 0; DEBUG_SVC("event_type %d", event->event_type); error = plugin->channel_entry_points.pVirtualChannelEventPush(plugin->priv->open_handle, event); if (error != CHANNEL_RC_OK) printf("svc_plugin_send_event: VirtualChannelEventPush failed %d\n", error); return error; } FreeRDP-1.0.2/libfreerdp-utils/thread.c000066400000000000000000000037271207112532300176350ustar00rootroot00000000000000/** * FreeRDP: A Remote Desktop Protocol client. * Thread Utils * * Copyright 2011 Vic Lee * * 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. */ #include #include #include #include #ifdef _WIN32 #include #ifdef _MSC_VER #include #endif #endif #include #include #include freerdp_thread* freerdp_thread_new(void) { freerdp_thread* thread; thread = xnew(freerdp_thread); thread->mutex = freerdp_mutex_new(); thread->signals[0] = wait_obj_new(); thread->signals[1] = wait_obj_new(); thread->num_signals = 2; return thread; } void freerdp_thread_start(freerdp_thread* thread, void* func, void* arg) { thread->status = 1; #ifdef _WIN32 { # ifdef _MSC_VER CloseHandle((HANDLE)_beginthreadex(NULL, 0, func, arg, 0, NULL)); #else CloseHandle(CreateThread(NULL, 0, (LPTHREAD_START_ROUTINE)func, arg, 0, NULL)); #endif } #else { pthread_t th; pthread_create(&th, 0, func, arg); pthread_detach(th); } #endif } void freerdp_thread_stop(freerdp_thread* thread) { int i = 0; wait_obj_set(thread->signals[0]); while (thread->status > 0 && i < 1000) { i++; freerdp_usleep(100000); } } void freerdp_thread_free(freerdp_thread* thread) { int i; for (i = 0; i < thread->num_signals; i++) wait_obj_free(thread->signals[i]); thread->num_signals = 0; freerdp_mutex_free(thread->mutex); thread->mutex = NULL; xfree(thread); } FreeRDP-1.0.2/libfreerdp-utils/unicode.c000066400000000000000000000131621207112532300200060ustar00rootroot00000000000000/** * FreeRDP: A Remote Desktop Protocol Client * Unicode Utils * * Copyright 2011 Marc-Andre Moreau * * 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. */ #include #include #include #include /* Convert pin/in_len from WINDOWS_CODEPAGE - return like xstrdup, 0-terminated */ char* freerdp_uniconv_in(UNICONV* uniconv, unsigned char* pin, size_t in_len) { unsigned char *conv_pin = pin; size_t conv_in_len = in_len; char *pout = xmalloc(in_len * 2 + 1), *conv_pout = pout; size_t conv_out_len = in_len * 2; #ifdef HAVE_ICONV if (iconv(uniconv->in_iconv_h, (ICONV_CONST char **) &conv_pin, &conv_in_len, &conv_pout, &conv_out_len) == (size_t) - 1) { /* TODO: xrealloc if conv_out_len == 0 - it shouldn't be needed, but would allow a smaller initial alloc ... */ printf("freerdp_uniconv_in: iconv failure\n"); return 0; } #else while (conv_in_len >= 2) { unsigned int wc; wc = (unsigned int)(unsigned char)(*conv_pin++); wc += ((unsigned int)(unsigned char)(*conv_pin++)) << 8; conv_in_len -= 2; if (wc >= 0xD800 && wc <= 0xDFFF && conv_in_len >= 2) { /* Code points U+10000 to U+10FFFF using surrogate pair */ wc = ((wc - 0xD800) << 10) + 0x10000; wc += (unsigned int)(unsigned char)(*conv_pin++); wc += ((unsigned int)(unsigned char)(*conv_pin++) - 0xDC) << 8; conv_in_len -= 2; } if (wc <= 0x7F) { *conv_pout++ = (char)wc; conv_out_len--; } else if (wc <= 0x07FF) { *conv_pout++ = (char)(0xC0 + (wc >> 6)); *conv_pout++ = (char)(0x80 + (wc & 0x3F)); conv_out_len -= 2; } else if (wc <= 0xFFFF) { *conv_pout++ = (char)(0xE0 + (wc >> 12)); *conv_pout++ = (char)(0x80 + ((wc >> 6) & 0x3F)); *conv_pout++ = (char)(0x80 + (wc & 0x3F)); conv_out_len -= 3; } else { *conv_pout++ = (char)(0xF0 + (wc >> 18)); *conv_pout++ = (char)(0x80 + ((wc >> 12) & 0x3F)); *conv_pout++ = (char)(0x80 + ((wc >> 6) & 0x3F)); *conv_pout++ = (char)(0x80 + (wc & 0x3F)); conv_out_len -= 4; } } #endif if (conv_in_len > 0) { printf("freerdp_uniconv_in: conversion failure - %d chars left\n", (int) conv_in_len); } *conv_pout = 0; return pout; } /* Convert str from DEFAULT_CODEPAGE to WINDOWS_CODEPAGE and return buffer like xstrdup. * Buffer is 0-terminated but that is not included in the returned length. */ char* freerdp_uniconv_out(UNICONV *uniconv, char *str, size_t *pout_len) { size_t ibl; size_t obl; char* pin; char* pout; char* pout0; if (str == NULL) { *pout_len = 0; return NULL; } ibl = strlen(str); obl = 2 * ibl; pin = str; pout0 = xmalloc(obl + 2); pout = pout0; #ifdef HAVE_ICONV if (iconv(uniconv->out_iconv_h, (ICONV_CONST char **) &pin, &ibl, &pout, &obl) == (size_t) - 1) { printf("freerdp_uniconv_out: iconv() error\n"); return NULL; } #else while ((ibl > 0) && (obl > 0)) { unsigned int wc; wc = (unsigned int)(unsigned char)(*pin++); ibl--; if (wc >= 0xF0) { wc = (wc - 0xF0) << 18; wc += ((unsigned int)(unsigned char)(*pin++) - 0x80) << 12; wc += ((unsigned int)(unsigned char)(*pin++) - 0x80) << 6; wc += ((unsigned int)(unsigned char)(*pin++) - 0x80); ibl -= 3; } else if (wc >= 0xE0) { wc = (wc - 0xE0) << 12; wc += ((unsigned int)(unsigned char)(*pin++) - 0x80) << 6; wc += ((unsigned int)(unsigned char)(*pin++) - 0x80); ibl -= 2; } else if (wc >= 0xC0) { wc = (wc - 0xC0) << 6; wc += ((unsigned int)(unsigned char)(*pin++) - 0x80); ibl -= 1; } if (wc <= 0xFFFF) { *pout++ = (char)(wc & 0xFF); *pout++ = (char)(wc >> 8); obl -= 2; } else { wc -= 0x10000; *pout++ = (char)((wc >> 10) & 0xFF); *pout++ = (char)((wc >> 18) + 0xD8); *pout++ = (char)(wc & 0xFF); *pout++ = (char)(((wc >> 8) & 0x03) + 0xDC); obl -= 4; } } #endif if (ibl > 0) { printf("freerdp_uniconv_out: string not fully converted - %d chars left\n", (int) ibl); } *pout_len = pout - pout0; *pout++ = 0; /* Add extra double zero termination */ *pout = 0; return pout0; } /* Uppercase a unicode string */ void freerdp_uniconv_uppercase(UNICONV *uniconv, char *wstr, int length) { int i; unsigned char* p; unsigned int wc, uwc; p = (unsigned char*)wstr; for (i = 0; i < length; i++) { wc = (unsigned int)(*p); wc += (unsigned int)(*(p + 1)) << 8; uwc = towupper(wc); if (uwc != wc) { *p = uwc & 0xFF; *(p + 1) = (uwc >> 8) & 0xFF; } p += 2; } } UNICONV* freerdp_uniconv_new() { UNICONV *uniconv = xnew(UNICONV); #ifdef HAVE_ICONV uniconv->iconv = 1; uniconv->in_iconv_h = iconv_open(DEFAULT_CODEPAGE, WINDOWS_CODEPAGE); if (errno == EINVAL) { printf("Error opening iconv converter to %s from %s\n", DEFAULT_CODEPAGE, WINDOWS_CODEPAGE); } uniconv->out_iconv_h = iconv_open(WINDOWS_CODEPAGE, DEFAULT_CODEPAGE); if (errno == EINVAL) { printf("Error opening iconv converter to %s from %s\n", WINDOWS_CODEPAGE, DEFAULT_CODEPAGE); } #endif return uniconv; } void freerdp_uniconv_free(UNICONV *uniconv) { if (uniconv != NULL) { #ifdef HAVE_ICONV iconv_close(uniconv->in_iconv_h); iconv_close(uniconv->out_iconv_h); #endif xfree(uniconv); } } FreeRDP-1.0.2/libfreerdp-utils/wait_obj.c000066400000000000000000000073021207112532300201550ustar00rootroot00000000000000/** * FreeRDP: A Remote Desktop Protocol client. * Virtual Channel Manager * * Copyright 2009-2011 Jay Sorg * * 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. */ #include "config.h" #include #include #include #include #include #ifndef _WIN32 #include #else #include #endif #ifdef HAVE_UNISTD_H #include #endif struct wait_obj { #ifdef _WIN32 HANDLE event; #else int pipe_fd[2]; #endif int attached; }; struct wait_obj* wait_obj_new(void) { struct wait_obj* obj; obj = xnew(struct wait_obj); obj->attached = 0; #ifdef _WIN32 obj->event = CreateEvent(NULL, TRUE, FALSE, NULL); #else obj->pipe_fd[0] = -1; obj->pipe_fd[1] = -1; if (pipe(obj->pipe_fd) < 0) { printf("wait_obj_new: pipe failed\n"); xfree(obj); return NULL; } #endif return obj; } struct wait_obj* wait_obj_new_with_fd(void* fd) { struct wait_obj* obj; obj = xnew(struct wait_obj); obj->attached = 1; #ifdef _WIN32 obj->event = fd; #else obj->pipe_fd[0] = (int)(long)fd; obj->pipe_fd[1] = -1; #endif return obj; } void wait_obj_free(struct wait_obj* obj) { if (obj) { if (obj->attached == 0) { #ifdef _WIN32 if (obj->event) { CloseHandle(obj->event); obj->event = NULL; } #else if (obj->pipe_fd[0] != -1) { close(obj->pipe_fd[0]); obj->pipe_fd[0] = -1; } if (obj->pipe_fd[1] != -1) { close(obj->pipe_fd[1]); obj->pipe_fd[1] = -1; } #endif } xfree(obj); } } int wait_obj_is_set(struct wait_obj* obj) { #ifdef _WIN32 return (WaitForSingleObject(obj->event, 0) == WAIT_OBJECT_0); #else fd_set rfds; int num_set; struct timeval time; FD_ZERO(&rfds); FD_SET(obj->pipe_fd[0], &rfds); memset(&time, 0, sizeof(time)); num_set = select(obj->pipe_fd[0] + 1, &rfds, 0, 0, &time); return (num_set == 1); #endif } void wait_obj_set(struct wait_obj* obj) { #ifdef _WIN32 SetEvent(obj->event); #else int len; if (wait_obj_is_set(obj)) return; len = write(obj->pipe_fd[1], "sig", 4); if (len != 4) printf("wait_obj_set: error\n"); #endif } void wait_obj_clear(struct wait_obj* obj) { #ifdef _WIN32 ResetEvent(obj->event); #else int len; while (wait_obj_is_set(obj)) { len = read(obj->pipe_fd[0], &len, 4); if (len != 4) printf("wait_obj_clear: error\n"); } #endif } int wait_obj_select(struct wait_obj** listobj, int numobj, int timeout) { #ifndef _WIN32 int max; int sock; int index; #endif fd_set fds; int status; struct timeval time; struct timeval* ptime; ptime = 0; if (timeout >= 0) { time.tv_sec = timeout / 1000; time.tv_usec = (timeout * 1000) % 1000000; ptime = &time; } #ifndef _WIN32 max = 0; FD_ZERO(&fds); if (listobj) { for (index = 0; index < numobj; index++) { sock = listobj[index]->pipe_fd[0]; FD_SET(sock, &fds); if (sock > max) max = sock; } } status = select(max + 1, &fds, 0, 0, ptime); #else status = select(0, &fds, 0, 0, ptime); #endif return status; } void wait_obj_get_fds(struct wait_obj* obj, void** fds, int* count) { #ifdef _WIN32 fds[*count] = (void*) obj->event; #else if (obj->pipe_fd[0] == -1) return; fds[*count] = (void*)(long) obj->pipe_fd[0]; #endif (*count)++; } FreeRDP-1.0.2/resources/000077500000000000000000000000001207112532300147475ustar00rootroot00000000000000FreeRDP-1.0.2/resources/FreeRDP-fav.ico000066400000000000000000000021761207112532300174520ustar00rootroot00000000000000 h(  ȷmȷme]ȷmȷmy`'iR&\ڳȷmijiS6S6dȷmñhthȷmƵlkS6ijiȷmȷmȷm̼wȷmȷmUxJuHRȷmȷmȷmfϞȷmȷmȷmȷmȷmȷmȷmȷm]fȷmȷmȷmȷmȷmȷmȷmĉK]ƵlȷmȷmȷmȷmȑJJLUXo3UJJJJz;S6XXJJJv8kPСžJJJx9`UJJPJJQ{JJdJĶvvFreeRDP-1.0.2/resources/FreeRDP.ico000066400000000000000000000727201207112532300167020ustar00rootroot00000000000000 (~00 Nh ^!00 %;  ` hhq( @gtFOgH~o玎xhoFx~ot~wd~x~hwN玈wlx~P燇x~v`xȎxx~~~xh~~~xxxgȎ~g~hgv~w`hvgDhgvwvFh~~vFwhgFfhghgxh~xhgwggghnvpgphp??????????( ~opwxpxu~|w玀臇 ~~w~vggh~vpvwg???(0`R5T7T7U8W; Z> ^C_D[AcGeIhNkPoUdL!kR)nV.pV sZ"tZ"qX$u[$w]$mX1qY1u^8zb)|d*xa<~iEg,i/m2k6o4p4s6t7u8{=mJnLpM~@BBDGHZJILMNOOQTRRWSTTYWYY\^ejvw~`bf{daacddhmptyf±hIJiŴjǶlȷnɹrʺuο´ƹ˾ż„ŋǏßȒ͚ѣӦ֬ĶʶƹȻ֮װذٴ/P"p0>M[iy1Qqұ/Pp  >1\Qzq/Pp!+6@IZ1pQq/ P6pLbx1Qq,/KPip1Qq/-P?pRcv1Qqϑܱ/Pp!&,>X1qQqa```````\+~~+ F```````G!%``````````_feS``````$(`````````,*)``````S  KJ@```````` }{U`a````_0"k|2C```````\P7````````````````````Gj1````````````````````^pIi?`````````````c```````pgL^`````````````sa``````8Hp*'``````````````xq```````'jh_``````````````````````.#^```````````````a````````]4'&/T``````````````' y``````````a````````````````Vca``````````a``````````````_@<`````````a``````````````````vRa`````````a````````````````7S```````a`````````````````65G````````a``````````````v744D`a```a```````````````t64449V`a```a````````````x:44446?V`a````````````q;4444444=F]````````^``M44444444467?DE8$ V`Y44444444444444\`zl44444444444444``u45455464646454``56464646464645 5`c45454646464645 _`W5454646464645 -`d4554646464645  _`8454546464645 @`wn455545464645 `b745546464645\`n45455464545E`r;5464555454G`4454545464QO555554645[544544644>n545464554N4554645474544544[45554545m4555444oZ454544BX545444Y44444m4444Z;X?????????( @S6T7X; _DaFdHdJkQjPlRdM#pV tZ#v\%x^%w^+qZ2p[5s\5y`'zb(}d*}e0w`:yb9h.k0k0n3k6q5v8}?kHqOtSACEJLRQPT[ZY[^id`cdimsv~f°gòiųjŴjƵlȷmȸoɹr˻v˼w̼yõƸȻćƍœɒĢСԪȻɽڳڵ1Qq&/@PZpt1Qq/&PAp[tϩ1Qq/P"p0>M[iy1Qqұ/Pp  >1\Qzq/Pp!+6@IZ1pQq/ P6pLbx1Qq,/KPip1Qq/-P?pRcv1Qqϑܱ/Pp!&,>X1qQqUCCCC@MedM=CCCC&>CFCCCC]oooo\CCCC% $CCCCCBooob`o6CCCC1.V/CCCDC7"ooaJ"-CCCCCCCCCECCCAgoN#5CCCCCCCCGUCCCC3hfLc CCCCCCCCCU^CCCC> II5CCCCCCCCC[CCCCCA'!>CCCCCCCC-ZCCCCCCCCCCCCCCCCCC HCCCCCCCCCCCCCCCCCC[SBCCCCCCCCCCCCCCCCFK-BCCCCCCCCCCCCCCCO(,>CCCCCCCCCCCCDP()(1?CCCCCCCCCTR)()()-2=AC>1-CW()()()()( C()()()()(C(()()()(),E))()()()(B[<(()()()((H)()()()( C8(()()()5X)()()()-D;(()()(0_))()()4Y(()()(9())()*((()O)((()(((()((Q:*??????????( S6kPiR&s[0y`'o3v8x9z;uHxJJKL]QPRUUXX\]]kkqed`dhv{tfñhijiƵlȷm̼wĶĉžȑϞСڳ1Qq/Pp",6@J[1qQq/Pp  =1[Qyq/"P0p=LYgx1Qq&/@PZpt1Qq/&PAp[tϩ1Qq/P"p0>M[iy1Qqұ/Pp  >1\Qzq/Pp!+6@IZ1pQq/ P6pLbx1Qq,/KPip1Qq/-P?pRcv1Qqϑܱ/Pp!&,>X1qQq))55))4)',7+ )&$!)(6')))*)) )))%-2))))))))%)))))))/ ())))1   30   #  .""???PNG  IHDR\rfIDATx yǏFEK I'iN550N5ID3aI6,6Fk5ˤ16)[ڴ2-$Ȋrj5F1 =w_={w˞9ysqG]>t<^ ?5xF~ 3+Mq@cȏkXBM~%Et~(XWePJk!z K\ x̨tӯ1(zUHJ`&šg|?$`(G Qd'P";?FM<p`eBxu~!P3R ,Bv~x!-Ƕ/ƶwn`1v~V t#(K^)A@Xŝ0eXGd_dDEXAXv0ݎ 3(K7ABX=YC(қN=0Xo4ݎ p)! J/ "<.0jD?m7@<}*Dv~L# yPwKpP0~I'.D PXЯjM7 P20@8T S@c~Ͱ?(p`$xO@P%0f^a/ (8odPvnӍ Ah|#RAЄ#z`PpοN(xopw_ YY_B_ )FxPH i`/P(<+ ȉgSP9l NCdéȈSsȀG?Ͱ?p(0A KpÐDŽ,`~`%@MCࠏXbIPO UA (=%8V̤)>A*i]Œ-SMT=$(?;/D`Nxc(~9Y#XG0C^6}cY! +XBK@E f!F "XӃ' Qf!?I PD,d1^u("dm"Ve Tr"4 nU_y!XBZA Ap]PL 0]iA-ip>t ,Ap]n+ jAkp]޴2q Z`/':32l 5t @:p`. Gpnt @q,\hX7 >)ߓqY/4@@( xa\amp2zo&! Wt ҂ @*i⾟jRM/Hv/ʬP4pZ z)} 7U(d @So8w/& \mRR`P΍ǓN>U)*Ax1N YA)^,SN'M٘xDM.ɏO#Q( W5xY'MtT% HKn)r%!':BpO`t#B x| 0CP%S 9o23]>3ݎL2Yv)#IC$NaF ͘u|NsQcYg̚MI!j" HM5Q| 1 nP Wz1v_ v|#2HX. G>3Ʒ$~QYtp6 Osyvk4A4?7N:~F؍\h`Ƭbiԟ8:?$0b!BM:Ng@},R#x`Qyz)+t9ڸ *I@AϜmApty}20n;Á@`?Xxp av ;V X1ϭ hw`' &;? 5[F$ Ę8/v~O $g"|)F/m\tH L7. Sv`'28%% Ytڧݻ c~犤b)g +,<MgfDώ3 B]xzNIxSQd.sSELw-嬠Z?|W`Reo">)SpoD6>f7P,\j)3(m:1%ׅ?txt|e?n:\.o>MbԏL7Wp7ۃM/yO!q[m˯5f -xsdxepD9p_hgY;/_ȥ«7\S/k% Jg B>yeQ7o<$?DK>>xR0@i9Λ9H*;~\l(d<@ R^l R֧;>:G_'lO8n(x鍫2KޫE[2`%Xɋpe2:?~~(ʿ}g'L|?(G`)@ #,o2kw3ŞInޱW\zW)(`}?_5\ҧwĭw=}^M2.5H+VKnDQՇduGtrbBoH ~#o f0P/2U DAo?/|]C\.?~'[ ,Ql'I9$߂>L"P\bO:]AW @|-S \S PË@|*}{k~uuqcH?`:>@?g1uz^%,ˀB8 BVTNΤNrsؐtǵ>O`eQAV}9Qud]Y҂$q-*8s2`@SU`ҁe@hnURtH$IG>/e .:{G@ r!2 q#:KW_~%:ܳeo_9f ǥC>-YV-;r*I m1L|>(V~QO"V:9oOy7`SXiNƿ-\p IJiǶlǶlǶlǶlǶlǶlǶlǶlǶlǶlǶlǶlǶlǶlǶl!ǶlǶlǶlǶlǶlǶlǶlPS6eżnKR5w:ǶlǶlǶlǶlǶlǶlǶlǶlǶlǶlǶlǶlǶlǶlǶlǶlǶlǶlǶlǶlǶlǶlǶlǶlt7S6qY1mX1R5sZ"ŴjǶlǶlǶlǶlǶlǶlǶlǶlǶlǶlǶlǶlǶlǶlǶloǶlǶlǶlǶlǶlǶlǶlǶlǶlB[? R5R5R5R5V9 o4òiǶlǶlǶlǶlǶlǶlǶlǶlǶlǶlǶlǶlǶlǶlǶlǶl6ǶlǶlǶlǶlǶlǶlǶlǶlǶlǶlgJt8s7DaǶlǶlǶlǶlǶlǶlǶlǶlǶlǶlǶlǶlǶlǶlu8hNlRt7 ǶlǶlǶlǶlǶlǶlǶlǶlǶlǶlǶlǶlǶlǶlǶlǶlǶlǶlǶlǶlǶlǶlǶlǶlǶlǶlǶlǶldU8R5R5R5ǶlǶlǶlǶlǶlǶlǶlǶlǶlǶlǶlǶlǶlǶlǶlǶlǶlǶlǶlǶlǶlǶlǶlǶlǶlǶlǶlǶlƵkTQC;ǶlZǶlǶlǶlǶlǶlǶlǶlǶlǶlǶlǶlǶlǶlǶlǶlǶlǶlǶlǶlǶlǶlǶlǶlǶlǶlǶlǶlǶlǶlǶlI ]ǶlǶlǶlǶlǶlǶlǶlǶlǶlǶlǶlǶlǶlǶlǶlǶlǶlǶlǶlǶlǶlǶlǶlǶlǶlǶlǶlǶl3IJ`ǶlǶlǶlǶlǶlǶlǶlǶlǶlǶlǶlǶlǶlǶlǶlǶlǶlǶlǶlǶlǶlǶlǶlǶlǶlǶlIIJ^ǶlǶlǶlǶlǶlǶlǶlǶlǶlǶlǶlǶlǶlǶlǶlǶlǶlǶlǶlǶlǶlǶlǶlǶlǶlIIIJWƵkǶlǶlǶlǶlǶlǶlǶlǶlǶlǶlǶlǶlǶlǶlǶlǶlǶlǶlǶlǶlǶlǶlIIIIIOcǶlǶlǶlǶlǶlǶlǶlǶlǶlǶlǶlǶlǶlǶlǶlǶlǶlǶlǶlǶl IIIIIIJSdǶlǶlǶlǶlǶlǶlǶlǶlǶlǶlǶlǶlǶlǶlǶlǶlNǶlIIIIIIIIIO\fǶlǶlǶlǶlǶlǶlǶlǶl°hǶlǶlǶlZIޢIIIIIIIIIJLRWYOo3|d*kPZ> dǶlǶlIȢIIIIIIIIIIIIIIg,R5R5R5V9 fǶlǶlIIIIIIIIIIIIIIIw]$R5R5R5_DǶlǶlǶlJJJJJJJJJJJJJJJoUR5R5R5{b)ǶlǶlǶlNJXJJJJJJJJJJJJJJiNR5R5R5KǶlǶlǶl JJJJJJJJJJJJJJJeJR5R5_CŴjǶlǶlJԣJJJJJJJJJJJJJcGR5R5BǶlǶlǶl JyJJJJJJJJJJJJJcGR5hMŴjǶlǶlOJJJJJJJJJJJJJJcGT7TǶlǶlJJJJJJJJJJJJJeIi/ǶlǶlǶlJ%JJJJJJJJJJJJtZ"fǶlǶlvJJJJJJJJJJJJYǶlǶlǶlJJJJJJJJJJJJ\ǶlǶlKJ|JJJJJJJJJJVǶlǶlJ JףJJJJJJJJJIIDJJIJJIJJIIꢌIJJJJJJJJJII%J JܣJJJJJJJIIhJ9IJJIJJIIIJsJJJJJJIII%JJJJJJJIIIJ JãJJJJIII袌IJJͣJJJIIIIAJJɣJJIIIItJ JJIIIIuJJOI¢II̢I?????( @ ȷmȷmȷmȷmȷmųjk6w^+eȷmȷmȷmȷmC`ES6kQ°gȷmȷm3ȷmȷmȷmȷmȷms7ɽȻy`'ȷmȷmȷmȷmAT7dM#tS}e0ȷmȷm2ȷmȷmȷmȷmȷmƵkyb9qZ2cȷmȷmȷmȷm[[œZȷmȷm$ȷmȷmȷmȷmȷmdkHX; S6kHUȷmȷmȷmȷmȷmȷmȷmȷmȷmȷm ȷmȷmȷmȷmŴkdJS6_EqO_D`ȷmȷmȷmȷmȷmȷmȷmȷmȷmȷmȷmȷmȷmȷmi/iw`:pV ȷmȷmȷmȷmȷmȷmȷmȷmȷmȷmȷmȷmȷmȷmȷmglRs\5p[5bG`ȷmȷmȷmȷmȷmȷmȷmȷmȷmȷmȷm%ȷmȷmȷmȷmȷmŴjE{c)za(}?°gȷmȷmȷmȷmȷmȷmȷmȷmUp4@^ȷmȷmȷmȷmȷmȷmȷmȷmȷmȷmȷmȷmȷmȷmȷmȷmȷmȷmȷmk0eJS6"ȷmȷmȷmȷmȷmȷmȷmȷmȷmȷmȷmȷmȷmȷmȷmȷmȷmȷmȷmȷmȷmUƵlȷmȷmȷmȷmȷmȷmȷmȷmȷmȷmȷmȷmȷmȷmȷmȷmȷmȷmJTƵkȷmȷmȷmȷmȷmȷmȷmȷmȷmȷmȷmȷmȷmȷmȷmȷmOJJPfȷmȷmȷmȷmȷmȷmȷmȷmȷmȷmȷmȷmȷmȷmaJJJJYòiȷmȷmȷmȷmȷmȷmȷmȷmȷmȷmȷm7JJJJJJT^fŴjǶl°g[TȷmȷmDJJJJJJJJJJv8S6S6v\%ȷmȷm`JlJJJJJJJJJk0S6S6n3ȷmȷmNJCJJJJJJJJJ}d*S6S6PȷmȷmJJJJJJJJJJy_&S6dHƵlȷmJJJJJJJJJx^%S6KȷmȷmJLJJJJJJJJx^%tZ#ȷmȷm[JJңJJJJJJJh-_ȷmJPJJJJJJJUȷmȷm*JJJJJJJSȷmJ,JJJJJJJJJJJJJJJJJͣJJJJJJRJ%JJJJJJJNJJJJJJJiJJJJJtJhJJJJJ;JţJJj???????????(  ȷmlȷmȷme]ȷmȷmy`'iR&\ȷmȷmȷmųjqdȷmñhthȷm ȷmoȷmǶlkks[0ijiȷmȷmȷmȷmȷm*ȷmȷmVxJuHRȷmȷmȷmgTȷmȷmȷmȷmȷmȷmȷmȷmȷm]m2kOWfȷmȷmȷmȷmȷmȷmȷmȷmȷmJVK]ƵlȷmȷmȷmȷmȷmȷmJIJJLVVo3Tȷm)J,JJJJz;S6WȷmJJ룍JJJv8kPǶlJJJJx9VȷmJJJJOȷmiJjJJJJJJJJJ@JJ٣JJJJJAAAAAAAAA?A?AAAAAAFreeRDP-1.0.2/resources/FreeRDP_Icon_256px.h000066400000000000000000022303251207112532300202720ustar00rootroot00000000000000static unsigned long FreeRDP_Icon_256px_prop [] = { 256, 256 , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 541756835u , 1615498659u , 2152369571u , 2940898723u , 3209334179u , 3209334179u , 3209334179u , 2940898723u , 2152369571u , 1078627747u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 541756835u , 2152369571u , 3746205091u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 3746205091u , 1883934115u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 541756835u , 2672463267u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 2940898723u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 541756835u , 2672463267u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 2672463267u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 2152369571u , 4014640547u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 1078627747u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 810192291u , 3477769635u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 2940898723u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 2152369571u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4014640547u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 273321379u , 3209334179u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 810192291u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 810192291u , 4014640547u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 1078627747u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 1615498659u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 1078627747u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 2404027811u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 1078627747u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 2672463267u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 1078627747u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 273321379u , 3477769635u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 1078627747u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 273321379u , 3477769635u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 541756835u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 273321379u , 3477769635u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 273321379u , 3477769635u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 3209334179u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 273321379u , 3477769635u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 2404027811u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 273321379u , 3477769635u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 1615498659u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 273321379u , 3477769635u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 541756835u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 273321379u , 3477769635u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 3477769635u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 273321379u , 3477769635u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 2404027811u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 2940898723u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 810192291u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 2672463267u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 3746205091u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 2404027811u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 2404027811u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 1615498659u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 810192291u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 1347063203u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 3746205091u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 810192291u , 4014640547u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 1883934115u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 273321379u , 3746205091u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 273321379u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 3477769635u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 2672463267u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 2672463267u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 1078627747u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 1883934115u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 3746205091u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 1078627747u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 1615498659u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 541756835u , 4014640547u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4014640547u , 273321379u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 3477769635u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 2152369571u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 2672463267u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 273321379u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 1615498659u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 2672463267u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 810192291u , 4014640547u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 810192291u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 273321379u , 3477769635u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 3477769635u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 2672463267u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 1615498659u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 1615498659u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 273321379u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 541756835u , 4014640547u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 2940898723u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 3477769635u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 1347063203u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 2404027811u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 273321379u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 1078627747u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 2940898723u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 273321379u , 4014640547u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 1615498659u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 2940898723u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 541756835u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 1615498659u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 3477769635u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 541756835u , 4014640547u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 2404027811u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 3209334179u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 1347063203u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 1883934115u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 273321379u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 541756835u , 4014640547u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 3477769635u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 3209334179u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 2404027811u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 1883934115u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 1347063203u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 541756835u , 4014640547u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 541756835u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 3209334179u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 3746205091u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 1615498659u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 2940898723u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 273321379u , 4014640547u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 2152369571u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 2940898723u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 1078627747u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 1078627747u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 273321379u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 273321379u , 3746205091u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4014640547u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 2152369571u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 3209334179u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 810192291u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 2404027811u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 3209334179u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 1883934115u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 1615498659u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 1078627747u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 273321379u , 4014640547u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 273321379u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 2404027811u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 3211638728u , 3211638728u , 3211638728u , 2154674120u , 275625928u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 810192291u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283668652u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4016945096u , 1617803208u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 3209334179u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283800239u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 1349367752u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 1347063203u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4284261046u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4016945096u , 275625928u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 3746205091u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4284392888u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 2154674120u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 2152369571u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4284788159u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4016945096u , 544061384u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 273321379u , 4014640547u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4284919745u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 2674767816u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 2672463267u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 544061384u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 541756835u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 3211638728u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 3209334179u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283536810u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 1080932296u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 1078627747u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283668652u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 3748509640u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 3209334179u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283800239u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 2154674120u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 1347063203u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283800238u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4016945096u , 275625928u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 3746205091u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4280836731u , 4284524473u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 2674767816u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 1615498659u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4280573046u , 4280309360u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 1080932296u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 3746205091u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4279716967u , 4278597203u , 4282417045u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 3480074184u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 1615498659u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4279716967u , 4278597203u , 4278992474u , 4284524473u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 1886238664u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 3746205091u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4279716967u , 4278597203u , 4278597203u , 4280309360u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4016945096u , 275625928u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 1615498659u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4278860632u , 4278597203u , 4278597203u , 4278597203u , 4283273123u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 2674767816u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 3746205091u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4278597203u , 4278597203u , 4278597203u , 4278597203u , 4278992474u , 4284985281u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 1080932296u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 1615498659u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4278597203u , 4278597203u , 4278597203u , 4278597203u , 4278597203u , 4281165439u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 3748509640u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 3746205091u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4278597203u , 4278597203u , 4278597203u , 4278597203u , 4278597203u , 4278597203u , 4283668395u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 2154674120u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 1615498659u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4278597203u , 4278597203u , 4278597203u , 4278597203u , 4278597203u , 4278597203u , 4279453282u , 4284985281u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4016945096u , 544061384u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 3746205091u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4282219924u , 4278597203u , 4278597203u , 4278597203u , 4278597203u , 4278597203u , 4278597203u , 4278597203u , 4282021774u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 2943203272u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 1078627747u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4281956239u , 4278597203u , 4278597203u , 4278597203u , 4278597203u , 4278597203u , 4278597203u , 4278597203u , 4278597203u , 4284129202u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 1349367752u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 3209334179u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4281956239u , 4278597203u , 4278597203u , 4278597203u , 4278597203u , 4278597203u , 4278597203u , 4278597203u , 4278597203u , 4280309360u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 3748509640u , 275625928u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 810192291u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4281956239u , 4278597203u , 4278597203u , 4278597203u , 4278597203u , 4278597203u , 4278597203u , 4278597203u , 4278597203u , 4278597203u , 4282417045u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 2154674120u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 2672463267u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4281956239u , 4278597203u , 4278597203u , 4278597203u , 4278597203u , 4278597203u , 4278597203u , 4278597203u , 4278597203u , 4278597203u , 4278992474u , 4284985281u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 812496840u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 541756835u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4281956239u , 4278597203u , 4278597203u , 4278597203u , 4278597203u , 4278597203u , 4278597203u , 4278597203u , 4278597203u , 4278597203u , 4278597203u , 4280704632u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 3211638728u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 2152369571u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4281956239u , 4278597203u , 4278597203u , 4278597203u , 4278597203u , 4278597203u , 4278597203u , 4278597203u , 4278597203u , 4278597203u , 4278597203u , 4278597203u , 4283668395u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 1617803208u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 3746205091u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4281956239u , 4278597203u , 4278597203u , 4278597203u , 4278597203u , 4278597203u , 4278597203u , 4278597203u , 4278597203u , 4278597203u , 4278597203u , 4278597203u , 4279453282u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4016945096u , 275625928u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 1615498659u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4281956239u , 4278597203u , 4278597203u , 4278597203u , 4278597203u , 4278597203u , 4278597203u , 4278597203u , 4278597203u , 4278597203u , 4278597203u , 4278597203u , 4278597203u , 4282021774u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 2674767816u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 3209334179u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4281956239u , 4278597203u , 4278597203u , 4278597203u , 4278597203u , 4278597203u , 4278597203u , 4278597203u , 4278597203u , 4278597203u , 4278597203u , 4278597203u , 4278597203u , 4278992474u , 4284524473u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 1080932296u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 541756835u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4281956239u , 4278597203u , 4278597203u , 4278597203u , 4278597203u , 4278597203u , 4278597203u , 4278597203u , 4278597203u , 4278597203u , 4278597203u , 4278597203u , 4278597203u , 4278597203u , 4280309360u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 3480074184u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 2152369571u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4281956239u , 4278597203u , 4278597203u , 4278597203u , 4278597203u , 4278597203u , 4278597203u , 4278597203u , 4278597203u , 4278597203u , 4278597203u , 4278597203u , 4278597203u , 4278597203u , 4278597203u , 4283668395u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 2154674120u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 3746205091u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4281956239u , 4278597203u , 4278597203u , 4278597203u , 4278597203u , 4278597203u , 4278597203u , 4278597203u , 4278597203u , 4278597203u , 4278597203u , 4278597203u , 4278597203u , 4278597203u , 4278597203u , 4279453282u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4016945096u , 544061384u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 1078627747u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4281956239u , 4278597203u , 4278597203u , 4278597203u , 4278597203u , 4278597203u , 4278597203u , 4278597203u , 4278597203u , 4278597203u , 4278597203u , 4278597203u , 4278597203u , 4278597203u , 4278597203u , 4278597203u , 4282021774u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 3211638728u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 2672463267u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4281956239u , 4278597203u , 4278597203u , 4278597203u , 4278597203u , 4278597203u , 4278597203u , 4278597203u , 4278597203u , 4278597203u , 4278597203u , 4278597203u , 4278597203u , 4278597203u , 4278597203u , 4278597203u , 4278992474u , 4284985281u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 1349367752u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 4014640547u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4281956239u , 4278597203u , 4278597203u , 4278597203u , 4278597203u , 4278597203u , 4278597203u , 4278597203u , 4278597203u , 4278597203u , 4278597203u , 4278597203u , 4278597203u , 4278597203u , 4278597203u , 4278597203u , 4278597203u , 4281165439u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 3748509640u , 275625928u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 1347063203u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4281956239u , 4278597203u , 4278597203u , 4278597203u , 4278597203u , 4278597203u , 4278597203u , 4278597203u , 4278597203u , 4278597203u , 4278597203u , 4278597203u , 4278597203u , 4278597203u , 4278597203u , 4278597203u , 4278597203u , 4278597203u , 4284524473u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 2154674120u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 2404027811u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4281956239u , 4278597203u , 4278597203u , 4278597203u , 4278597203u , 4278597203u , 4278597203u , 4278597203u , 4278597203u , 4278597203u , 4278597203u , 4278597203u , 4278597203u , 4278597203u , 4278597203u , 4278597203u , 4278597203u , 4278597203u , 4280309360u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 544061384u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 3746205091u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4281956239u , 4278597203u , 4278597203u , 4278597203u , 4278597203u , 4278597203u , 4278597203u , 4278597203u , 4278597203u , 4278597203u , 4278597203u , 4278597203u , 4278597203u , 4278597203u , 4278597203u , 4278597203u , 4278597203u , 4278597203u , 4278597203u , 4283668395u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 3211638728u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 810192291u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4281956239u , 4278597203u , 4278597203u , 4278597203u , 4278597203u , 4278597203u , 4278597203u , 4278597203u , 4278597203u , 4278597203u , 4278597203u , 4278597203u , 4278597203u , 4278597203u , 4278597203u , 4278597203u , 4278597203u , 4278597203u , 4278597203u , 4280309360u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 1349367752u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 1883934115u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4282219924u , 4278597203u , 4278597203u , 4278597203u , 4278597203u , 4278597203u , 4278597203u , 4278597203u , 4278597203u , 4278597203u , 4278597203u , 4278597203u , 4278597203u , 4278597203u , 4278597203u , 4278597203u , 4278597203u , 4278597203u , 4278597203u , 4278597203u , 4284129202u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 3748509640u , 275625928u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 2940898723u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4278597203u , 4278597203u , 4278597203u , 4278597203u , 4278597203u , 4278597203u , 4278597203u , 4278597203u , 4278597203u , 4278597203u , 4278597203u , 4278597203u , 4278597203u , 4278597203u , 4278597203u , 4278597203u , 4278597203u , 4278597203u , 4278597203u , 4281165439u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 2154674120u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 4014640547u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4278597203u , 4278597203u , 4278597203u , 4278597203u , 4278597203u , 4278597203u , 4278597203u , 4278597203u , 4278597203u , 4278597203u , 4278597203u , 4278597203u , 4278597203u , 4278597203u , 4278597203u , 4278597203u , 4278597203u , 4278597203u , 4278597203u , 4278597203u , 4284524473u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4016945096u , 275625928u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 810192291u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4278597203u , 4278597203u , 4278597203u , 4278597203u , 4278597203u , 4278597203u , 4278597203u , 4278597203u , 4278597203u , 4278597203u , 4278597203u , 4278597203u , 4278597203u , 4278597203u , 4278597203u , 4278597203u , 4278597203u , 4278597203u , 4278597203u , 4278597203u , 4282021774u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 2154674120u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 1615498659u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4278597203u , 4278597203u , 4278597203u , 4278597203u , 4278597203u , 4278597203u , 4278597203u , 4278597203u , 4278597203u , 4278597203u , 4278597203u , 4278597203u , 4278597203u , 4278597203u , 4278597203u , 4278597203u , 4278597203u , 4278597203u , 4278597203u , 4278597203u , 4279453282u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4016945096u , 275625928u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 2672463267u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4278860632u , 4278597203u , 4278597203u , 4278597203u , 4278597203u , 4278597203u , 4278597203u , 4278597203u , 4278597203u , 4278597203u , 4278597203u , 4278597203u , 4278597203u , 4278597203u , 4278597203u , 4278597203u , 4278597203u , 4278597203u , 4278597203u , 4278597203u , 4278597203u , 4283273123u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 1886238664u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 3477769635u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4279716967u , 4278597203u , 4278597203u , 4278597203u , 4278597203u , 4278597203u , 4278597203u , 4278597203u , 4278597203u , 4278597203u , 4278597203u , 4278597203u , 4278597203u , 4278597203u , 4278597203u , 4278597203u , 4278597203u , 4278597203u , 4278597203u , 4278597203u , 4278597203u , 4280704632u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 3748509640u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4279716967u , 4278597203u , 4278597203u , 4278597203u , 4278597203u , 4278597203u , 4278597203u , 4278597203u , 4278597203u , 4278597203u , 4278597203u , 4278597203u , 4278597203u , 4278597203u , 4278597203u , 4278597203u , 4278597203u , 4278597203u , 4278597203u , 4278597203u , 4278597203u , 4278597203u , 4284985281u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 1080932296u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 1078627747u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4279716967u , 4278597203u , 4278597203u , 4278597203u , 4278597203u , 4278597203u , 4278597203u , 4278597203u , 4278597203u , 4278597203u , 4278597203u , 4278597203u , 4278597203u , 4278597203u , 4278597203u , 4278597203u , 4278597203u , 4278597203u , 4278597203u , 4278597203u , 4278597203u , 4278597203u , 4282812316u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 2674767816u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 1615498659u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4280309617u , 4278597203u , 4278597203u , 4278597203u , 4278597203u , 4278597203u , 4278597203u , 4278597203u , 4278597203u , 4278597203u , 4278597203u , 4278597203u , 4278597203u , 4278597203u , 4278597203u , 4278597203u , 4278597203u , 4278597203u , 4278597203u , 4278597203u , 4278597203u , 4278597203u , 4280704632u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4016945096u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 2404027811u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4280836731u , 4278597203u , 4278597203u , 4278597203u , 4278597203u , 4278597203u , 4278597203u , 4278597203u , 4278597203u , 4278597203u , 4278597203u , 4278597203u , 4278597203u , 4278597203u , 4278597203u , 4278597203u , 4278597203u , 4278597203u , 4278597203u , 4278597203u , 4278597203u , 4278597203u , 4278597203u , 4284985281u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 1080932296u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 3209334179u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4280836731u , 4278597203u , 4278597203u , 4278597203u , 4278597203u , 4278597203u , 4278597203u , 4278597203u , 4278597203u , 4278597203u , 4278597203u , 4278597203u , 4278597203u , 4278597203u , 4278597203u , 4278597203u , 4278597203u , 4278597203u , 4278597203u , 4278597203u , 4278597203u , 4278597203u , 4278597203u , 4282812316u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 2406332360u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 3746205091u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4281429125u , 4278597203u , 4278597203u , 4278597203u , 4278597203u , 4278597203u , 4278597203u , 4278597203u , 4278597203u , 4278597203u , 4278597203u , 4278597203u , 4278597203u , 4278597203u , 4278597203u , 4278597203u , 4278597203u , 4278597203u , 4278597203u , 4278597203u , 4278597203u , 4278597203u , 4278597203u , 4281165439u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 3480074184u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4281956239u , 4278597203u , 4278597203u , 4278597203u , 4278597203u , 4278597203u , 4278597203u , 4278597203u , 4278597203u , 4278597203u , 4278597203u , 4278597203u , 4278597203u , 4278597203u , 4278597203u , 4278597203u , 4278597203u , 4278597203u , 4278597203u , 4278597203u , 4278597203u , 4278597203u , 4278597203u , 4278992474u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 1078627747u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4281956239u , 4278597203u , 4278597203u , 4278597203u , 4278597203u , 4278597203u , 4278597203u , 4278597203u , 4278597203u , 4278597203u , 4278597203u , 4278597203u , 4278597203u , 4278597203u , 4278597203u , 4278597203u , 4278597203u , 4278597203u , 4278597203u , 4278597203u , 4278597203u , 4278597203u , 4278597203u , 4278597203u , 4284129202u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 1080932296u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 1347063203u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4282812574u , 4278597203u , 4278597203u , 4278597203u , 4278597203u , 4278597203u , 4278597203u , 4278597203u , 4278597203u , 4278597203u , 4278597203u , 4278597203u , 4278597203u , 4278597203u , 4278597203u , 4278597203u , 4278597203u , 4278597203u , 4278597203u , 4278597203u , 4278597203u , 4278597203u , 4278597203u , 4278597203u , 4282417045u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 1886238664u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 2152369571u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4278597203u , 4278597203u , 4278597203u , 4278597203u , 4278597203u , 4278597203u , 4278597203u , 4278597203u , 4278597203u , 4278597203u , 4278597203u , 4278597203u , 4278597203u , 4278597203u , 4278597203u , 4278597203u , 4278597203u , 4278597203u , 4278597203u , 4278597203u , 4278597203u , 4278597203u , 4278597203u , 4281165439u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 2406332360u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 2404027811u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4278860632u , 4278597203u , 4278597203u , 4278597203u , 4278597203u , 4278597203u , 4278597203u , 4278597203u , 4278597203u , 4278597203u , 4278597203u , 4278597203u , 4278597203u , 4278597203u , 4278597203u , 4278597203u , 4278597203u , 4278597203u , 4278597203u , 4278597203u , 4278597203u , 4278597203u , 4278597203u , 4279848553u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 3211638728u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 3209334179u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4279716967u , 4278597203u , 4278597203u , 4278597203u , 4278597203u , 4278597203u , 4278597203u , 4278597203u , 4278597203u , 4278597203u , 4278597203u , 4278597203u , 4278597203u , 4278597203u , 4278597203u , 4278597203u , 4278597203u , 4278597203u , 4278597203u , 4278597203u , 4278597203u , 4278597203u , 4278597203u , 4278597203u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 3480074184u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 3477769635u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4279716967u , 4278597203u , 4278597203u , 4278597203u , 4278597203u , 4278597203u , 4278597203u , 4278597203u , 4278597203u , 4278597203u , 4278597203u , 4278597203u , 4278597203u , 4278597203u , 4278597203u , 4278597203u , 4278597203u , 4278597203u , 4278597203u , 4278597203u , 4278597203u , 4278597203u , 4278597203u , 4278597203u , 4284129202u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4280836731u , 4278597203u , 4278597203u , 4278597203u , 4278597203u , 4278597203u , 4278597203u , 4278597203u , 4278597203u , 4278597203u , 4278597203u , 4278597203u , 4278597203u , 4278597203u , 4278597203u , 4278597203u , 4278597203u , 4278597203u , 4278597203u , 4278597203u , 4278597203u , 4278597203u , 4278597203u , 4278597203u , 4283668395u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4280836731u , 4278597203u , 4278597203u , 4278597203u , 4278597203u , 4278597203u , 4278597203u , 4278597203u , 4278597203u , 4278597203u , 4278597203u , 4278597203u , 4278597203u , 4278597203u , 4278597203u , 4278597203u , 4278597203u , 4278597203u , 4278597203u , 4278597203u , 4278597203u , 4278597203u , 4278597203u , 4278597203u , 4282021774u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 1078627747u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4281956239u , 4278597203u , 4278597203u , 4278597203u , 4278597203u , 4278597203u , 4278597203u , 4278597203u , 4278597203u , 4278597203u , 4278597203u , 4278597203u , 4278597203u , 4278597203u , 4278597203u , 4278597203u , 4278597203u , 4278597203u , 4278597203u , 4278597203u , 4278597203u , 4278597203u , 4278597203u , 4278597203u , 4282021774u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 1078627747u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4281956239u , 4278597203u , 4278597203u , 4278597203u , 4278597203u , 4278597203u , 4278597203u , 4278597203u , 4278597203u , 4278597203u , 4278597203u , 4278597203u , 4278597203u , 4278597203u , 4278597203u , 4278597203u , 4278597203u , 4278597203u , 4278597203u , 4278597203u , 4278597203u , 4278597203u , 4278597203u , 4278597203u , 4282021774u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 1347063203u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4278597203u , 4278597203u , 4278597203u , 4278597203u , 4278597203u , 4278597203u , 4278597203u , 4278597203u , 4278597203u , 4278597203u , 4278597203u , 4278597203u , 4278597203u , 4278597203u , 4278597203u , 4278597203u , 4278597203u , 4278597203u , 4278597203u , 4278597203u , 4278597203u , 4278597203u , 4278597203u , 4280309360u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 2152369571u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4278860632u , 4278597203u , 4278597203u , 4278597203u , 4278597203u , 4278597203u , 4278597203u , 4278597203u , 4278597203u , 4278597203u , 4278597203u , 4278597203u , 4278597203u , 4278597203u , 4278597203u , 4278597203u , 4278597203u , 4278597203u , 4278597203u , 4278597203u , 4278597203u , 4278597203u , 4278597203u , 4280309360u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 2152369571u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4279716967u , 4278597203u , 4278597203u , 4278597203u , 4278597203u , 4278597203u , 4278597203u , 4278597203u , 4278597203u , 4278597203u , 4278597203u , 4278597203u , 4278597203u , 4278597203u , 4278597203u , 4278597203u , 4278597203u , 4278597203u , 4278597203u , 4278597203u , 4278597203u , 4278597203u , 4278597203u , 4280309360u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 2404027811u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4280309617u , 4278597203u , 4278597203u , 4278597203u , 4278597203u , 4278597203u , 4278597203u , 4278597203u , 4278597203u , 4278597203u , 4278597203u , 4278597203u , 4278597203u , 4278597203u , 4278597203u , 4278597203u , 4278597203u , 4278597203u , 4278597203u , 4278597203u , 4278597203u , 4278597203u , 4278597203u , 4280309360u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 3209334179u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283207845u , 4283668652u , 4283800239u , 4284261046u , 4284261046u , 4284524474u , 4284788159u , 4284788159u , 4284788159u , 4284788159u , 4285117123u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4284524473u , 4283668395u , 4283668395u , 4283668395u , 4283668395u , 4282417045u , 4282021774u , 4282021774u , 4280309360u , 4280309360u , 4278597203u , 4278597203u , 4278597203u , 4278597203u , 4278597203u , 4278597203u , 4278597203u , 4278597203u , 4278597203u , 4278597203u , 4278597203u , 4278597203u , 4281165439u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 3211638728u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 3209334179u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283536810u , 4283800239u , 4284261046u , 4284656316u , 4284919745u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4284985281u , 4283668395u , 4282417045u , 4281560710u , 4280309360u , 4278597203u , 4278597203u , 4278597203u , 4278597203u , 4278597203u , 4278597203u , 4282021774u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 2943203272u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 3209334179u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283207845u , 4283800239u , 4284392888u , 4284788159u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4284129202u , 4282417045u , 4280704632u , 4278992474u , 4278597203u , 4282021774u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 2154674120u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283207845u , 4283800239u , 4284392888u , 4285117123u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4284129202u , 4284524473u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 1349367752u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283339432u , 4284063667u , 4284788159u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 544061384u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283536810u , 4284392888u , 4285117123u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 3748509640u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283339432u , 4284063667u , 4284919745u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 2674767816u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 541756835u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283800239u , 4284656316u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 1349367752u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 1078627747u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283207845u , 4284261046u , 4285117123u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 3748509640u , 1617803208u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 1078627747u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283339432u , 4284524474u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 3748509640u , 1617803208u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 1078627747u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283668652u , 4284788159u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 3211638728u , 1080932296u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 1078627747u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283668652u , 4284788159u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 2674767816u , 275625928u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 1078627747u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283668652u , 4284788159u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4016945096u , 1349367752u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 1615498659u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283339432u , 4284524474u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 2943203272u , 275625928u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 2152369571u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283207845u , 4284261046u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4016945096u , 1349367752u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 2152369571u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283800239u , 4285117123u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 2406332360u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 2152369571u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283339432u , 4284788159u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 3480074184u , 275625928u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 2152369571u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4284261046u , 4285248710u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4016945096u , 812496840u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 2152369571u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283536810u , 4284919745u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4016945096u , 1617803208u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 2152369571u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4284063667u , 4285248710u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 1617803208u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 2152369571u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283207845u , 4284788159u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 2674767816u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 2152369571u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283668652u , 4285248710u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 2674767816u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 2152369571u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4284261046u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 2674767816u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 2152369571u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283207845u , 4284656316u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 2674767816u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 2152369571u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283536810u , 4284919745u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 2154674120u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 2152369571u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283668652u , 4285248710u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 1617803208u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 2152369571u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283932081u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 1080932296u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 2152369571u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4284261046u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4016945096u , 812496840u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 2152369571u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4284524474u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 3480074184u , 275625928u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 2152369571u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4284524474u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 2943203272u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 2152369571u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4284524474u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 1886238664u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 2152369571u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4284524474u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 812496840u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 2152369571u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4284524474u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 3748509640u , 275625928u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 2152369571u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4284524474u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 2406332360u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 2152369571u , 4283076003u , 4283076003u , 4283076003u , 4283076003u , 4284524474u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 1080932296u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 2152369571u , 4283076003u , 4283076003u , 4283076003u , 4283932081u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 3748509640u , 275625928u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 2152369571u , 4283076003u , 4283076003u , 4283932081u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 2154674120u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 2152369571u , 4283076003u , 4283536810u , 4285248710u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 544061384u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 1078627747u , 4283207845u , 4285248710u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 3211638728u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 1078627747u , 4284919745u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 1080932296u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 2406332360u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 3748509640u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 1617803208u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 1617803208u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 544061384u , 4016945096u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 3748509640u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 3480074184u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 1617803208u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 2154674120u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 3748509640u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 812496840u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 1617803208u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 3480074184u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 3480074184u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 2154674120u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 1080932296u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 544061384u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 2674767816u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 3211638728u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4284985281u , 4282021774u , 4281560710u , 4280309360u , 4280309360u , 4280309360u , 4280309360u , 4280309360u , 4280309360u , 4280309360u , 4280309360u , 4282021774u , 4282417045u , 540702606u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 1349367752u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4280704632u , 4278597203u , 4278597203u , 4278597203u , 4278597203u , 4278597203u , 4278597203u , 4278597203u , 4278597203u , 4278597203u , 4278597203u , 4278597203u , 4278597203u , 4010161747u , 805713491u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 3748509640u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4280309360u , 4278597203u , 4278597203u , 4278597203u , 4278597203u , 4278597203u , 4278597203u , 4278597203u , 4278597203u , 4278597203u , 4278597203u , 4278597203u , 4278597203u , 4278597203u , 3473290835u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 2154674120u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4280309360u , 4278597203u , 4278597203u , 4278597203u , 4278597203u , 4278597203u , 4278597203u , 4278597203u , 4278597203u , 4278597203u , 4278597203u , 4278597203u , 4278597203u , 4278597203u , 4278597203u , 1611019859u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 275625928u , 4016945096u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4280309360u , 4278597203u , 4278597203u , 4278597203u , 4278597203u , 4278597203u , 4278597203u , 4278597203u , 4278597203u , 4278597203u , 4278597203u , 4278597203u , 4278597203u , 4278597203u , 4278597203u , 3204855379u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 2154674120u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4281165439u , 4278597203u , 4278597203u , 4278597203u , 4278597203u , 4278597203u , 4278597203u , 4278597203u , 4278597203u , 4278597203u , 4278597203u , 4278597203u , 4278597203u , 4278597203u , 4278597203u , 4278597203u , 268842579u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 275625928u , 4016945096u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4282812316u , 4278597203u , 4278597203u , 4278597203u , 4278597203u , 4278597203u , 4278597203u , 4278597203u , 4278597203u , 4278597203u , 4278597203u , 4278597203u , 4278597203u , 4278597203u , 4278597203u , 4278597203u , 1342584403u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 2154674120u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4278992474u , 4278597203u , 4278597203u , 4278597203u , 4278597203u , 4278597203u , 4278597203u , 4278597203u , 4278597203u , 4278597203u , 4278597203u , 4278597203u , 4278597203u , 4278597203u , 4278597203u , 2147890771u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 275625928u , 4016945096u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4283273123u , 4278597203u , 4278597203u , 4278597203u , 4278597203u , 4278597203u , 4278597203u , 4278597203u , 4278597203u , 4278597203u , 4278597203u , 4278597203u , 4278597203u , 4278597203u , 4278597203u , 2667984467u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 2154674120u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4284985281u , 4283668395u , 4282812316u , 4282021774u , 4282021774u , 4282021774u , 4282021774u , 4282021774u , 4282021774u , 4282021774u , 4282812316u , 4283668395u , 4284985281u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4282021774u , 4278597203u , 4278597203u , 4278597203u , 4278597203u , 4278597203u , 4278597203u , 4278597203u , 4278597203u , 4278597203u , 4278597203u , 4278597203u , 4278597203u , 4278597203u , 3204855379u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 3748509640u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4284985281u , 4282812316u , 4281165439u , 4279453282u , 4278597203u , 4278597203u , 4278597203u , 4278597203u , 4278597203u , 4278597203u , 4278597203u , 4278597203u , 4278597203u , 4278597203u , 4278597203u , 4278597203u , 4278597203u , 4278992474u , 4280704632u , 4282417045u , 4284524473u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4284524473u , 4281165439u , 4279453282u , 4278597203u , 4278597203u , 4278597203u , 4278597203u , 4278597203u , 4278597203u , 4278597203u , 4278597203u , 4278597203u , 4278992474u , 2402578311u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 1617803208u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4284985281u , 4282812316u , 4280309360u , 4278597203u , 4278597203u , 4278597203u , 4278597203u , 4278597203u , 4278597203u , 4278597203u , 4278597203u , 4278597203u , 4278597203u , 4278597203u , 4278597203u , 4278597203u , 4278597203u , 4278597203u , 4278597203u , 4278597203u , 4278597203u , 4278597203u , 4278597203u , 4278597203u , 4279848553u , 4282417045u , 4284985281u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4284985281u , 4283668395u , 4283273123u , 4282021774u , 4282021774u , 4282021774u , 4282021774u , 4283668395u , 4284129202u , 4285380552u , 3748509640u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 3211638728u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4284524473u , 4282021774u , 4278992474u , 4278597203u , 4278597203u , 4278597203u , 4278597203u , 4278597203u , 4278597203u , 4278597203u , 4278597203u , 4278597203u , 4278597203u , 4278597203u , 4278597203u , 4278597203u , 4278597203u , 4278597203u , 4278597203u , 4278597203u , 4278597203u , 4278597203u , 4278597203u , 4278597203u , 4278597203u , 4278597203u , 4278597203u , 4278597203u , 4278597203u , 4281165439u , 4284524473u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 544061384u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 544061384u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4284985281u , 4282021774u , 4278992474u , 4278597203u , 4278597203u , 4278597203u , 4278597203u , 4278597203u , 4278597203u , 4278597203u , 4278597203u , 4278597203u , 4278597203u , 4278597203u , 4278597203u , 4278597203u , 4278597203u , 4278597203u , 4278597203u , 4278597203u , 4278597203u , 4278597203u , 4278597203u , 4278597203u , 4278597203u , 4278597203u , 4278597203u , 4278597203u , 4278597203u , 4278597203u , 4278597203u , 4278597203u , 4278597203u , 4281165439u , 4284524473u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 1886238664u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 2406332360u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4283273123u , 4278992474u , 4278597203u , 4278597203u , 4278597203u , 4278597203u , 4278597203u , 4278597203u , 4278597203u , 4278597203u , 4278597203u , 4278597203u , 4278597203u , 4278597203u , 4278597203u , 4278597203u , 4278597203u , 4278597203u , 4278597203u , 4278597203u , 4278597203u , 4278597203u , 4278597203u , 4278597203u , 4278597203u , 4278597203u , 4278597203u , 4278597203u , 4278597203u , 4278597203u , 4278597203u , 4278597203u , 4278597203u , 4278597203u , 4278597203u , 4278992474u , 4282021774u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 2943203272u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 4016945096u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4284985281u , 4280704632u , 4278597203u , 4278597203u , 4278597203u , 4278597203u , 4278597203u , 4278597203u , 4278597203u , 4278597203u , 4278597203u , 4278597203u , 4278597203u , 4278597203u , 4278597203u , 4278597203u , 4278597203u , 4278597203u , 4278597203u , 4278597203u , 4278597203u , 4278597203u , 4278597203u , 4278597203u , 4278597203u , 4278597203u , 4278597203u , 4278597203u , 4278597203u , 4278597203u , 4278597203u , 4278597203u , 4278597203u , 4278597203u , 4278597203u , 4278597203u , 4278597203u , 4278597203u , 4278597203u , 4279848553u , 4284524473u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4016945096u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 1349367752u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4284129202u , 4278992474u , 4278597203u , 4278597203u , 4278597203u , 4278597203u , 4278597203u , 4278597203u , 4278597203u , 4278597203u , 4278597203u , 4278597203u , 4278597203u , 4278597203u , 4278597203u , 4278597203u , 4278597203u , 4278597203u , 4278597203u , 4278597203u , 4278597203u , 4278597203u , 4278597203u , 4278597203u , 4278597203u , 4278597203u , 4278597203u , 4278597203u , 4278597203u , 4278597203u , 4278597203u , 4278597203u , 4278597203u , 4278597203u , 4278597203u , 4278597203u , 4278597203u , 4278597203u , 4278597203u , 4278597203u , 4278597203u , 4278992474u , 4283273123u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 812496840u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 2674767816u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4282812316u , 4278597203u , 4278597203u , 4278597203u , 4278597203u , 4278597203u , 4278597203u , 4278597203u , 4278597203u , 4278597203u , 4278597203u , 4278597203u , 4278597203u , 4278597203u , 4278597203u , 4278597203u , 4278597203u , 4278597203u , 4278597203u , 4278597203u , 4278597203u , 4278597203u , 4278597203u , 4278597203u , 4278597203u , 4278597203u , 4278597203u , 4278597203u , 4278597203u , 4278597203u , 4278597203u , 4278597203u , 4278597203u , 4278597203u , 4278597203u , 4278597203u , 4278597203u , 4278597203u , 4278597203u , 4278597203u , 4278597203u , 4278597203u , 4278597203u , 4278597203u , 4282021774u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 1617803208u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 4016945096u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4282812316u , 4278597203u , 4278597203u , 4278597203u , 4278597203u , 4278597203u , 4278597203u , 4278597203u , 4278597203u , 4278597203u , 4278597203u , 4278597203u , 4278597203u , 4278597203u , 4278597203u , 4278597203u , 4278597203u , 4278597203u , 4278597203u , 4282673278u , 4282673278u , 4284711316u , 4286815145u , 4286815145u , 4283725193u , 4282673278u , 4282673278u , 4278597203u , 4278597203u , 4278597203u , 4278597203u , 4278597203u , 4278597203u , 4278597203u , 4278597203u , 4278597203u , 4278597203u , 4278597203u , 4278597203u , 4278597203u , 4278597203u , 4278597203u , 4278597203u , 4278597203u , 4278597203u , 4278597203u , 4281165439u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 2674767816u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 1349367752u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4282812316u , 4278597203u , 4278597203u , 4278597203u , 4278597203u , 4278597203u , 4278597203u , 4278597203u , 4278597203u , 4278597203u , 4278597203u , 4278597203u , 4278597203u , 4278597203u , 4278597203u , 4279649118u , 4284711316u , 4288853183u , 4292929258u , 4294967295u , 4294967295u , 4294967295u , 4294967295u , 4294967295u , 4294967295u , 4294967295u , 4294967295u , 4294967295u , 4294967295u , 4292929258u , 4288853183u , 4284711316u , 4279649118u , 4278597203u , 4278597203u , 4278597203u , 4278597203u , 4278597203u , 4278597203u , 4278597203u , 4278597203u , 4278597203u , 4278597203u , 4278597203u , 4278597203u , 4278597203u , 4278597203u , 4278597203u , 4281165439u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 3480074184u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 2674767816u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4282812316u , 4278597203u , 4278597203u , 4278597203u , 4278597203u , 4278597203u , 4278597203u , 4278597203u , 4278597203u , 4278597203u , 4278597203u , 4278597203u , 4278597203u , 4278597203u , 4283725193u , 4289839305u , 4294967295u , 4294967295u , 4294967295u , 4294967295u , 4294967295u , 4294967295u , 4294967295u , 4294967295u , 4294967295u , 4294967295u , 4294967295u , 4294967295u , 4294967295u , 4294967295u , 4294967295u , 4294967295u , 4294967295u , 4294967295u , 4289839305u , 4282673278u , 4278597203u , 4278597203u , 4278597203u , 4278597203u , 4278597203u , 4278597203u , 4278597203u , 4278597203u , 4278597203u , 4278597203u , 4278597203u , 4278597203u , 4278597203u , 4278597203u , 4281560710u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 3748509640u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4283668395u , 4278597203u , 4278597203u , 4278597203u , 4278597203u , 4278597203u , 4278597203u , 4278597203u , 4278597203u , 4278597203u , 4278597203u , 4278597203u , 4278597203u , 4284711316u , 4292929258u , 4294967295u , 4294967295u , 4294967295u , 4294967295u , 4294967295u , 4294967295u , 4294967295u , 4294967295u , 4294967295u , 4294967295u , 4294967295u , 4294967295u , 4294967295u , 4294967295u , 4294967295u , 4294967295u , 4294967295u , 4294967295u , 4294967033u , 4294901234u , 4294900973u , 4294900972u , 4292863195u , 4284711052u , 4278597203u , 4278597203u , 4278597203u , 4278597203u , 4278597203u , 4278597203u , 4278597203u , 4278597203u , 4278597203u , 4278597203u , 4278597203u , 4278597203u , 4278597203u , 4282812316u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 1080932296u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 812496840u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4284985281u , 4278992474u , 4278597203u , 4278597203u , 4278597203u , 4278597203u , 4278597203u , 4278597203u , 4278597203u , 4278597203u , 4278597203u , 4278597203u , 4281687155u , 4290891220u , 4294967295u , 4294967295u , 4294967295u , 4294967295u , 4294967295u , 4294967295u , 4294967295u , 4294967295u , 4294967295u , 4294967295u , 4294967295u , 4294967295u , 4294967295u , 4294967295u , 4294967295u , 4294967295u , 4294967295u , 4294967295u , 4294967295u , 4294901235u , 4294900972u , 4294900972u , 4294900972u , 4294900972u , 4294900972u , 4294900972u , 4291876815u , 4280635239u , 4278597203u , 4278597203u , 4278597203u , 4278597203u , 4278597203u , 4278597203u , 4278597203u , 4278597203u , 4278597203u , 4278597203u , 4278597203u , 4278597203u , 4284129202u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 1886238664u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 1886238664u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4280309360u , 4278597203u , 4278597203u , 4278597203u , 4278597203u , 4278597203u , 4278597203u , 4278597203u , 4278597203u , 4278597203u , 4278597203u , 4285763230u , 4294967295u , 4294967295u , 4294967295u , 4294967295u , 4294967295u , 4294967295u , 4294967295u , 4294967295u , 4294967295u , 4294967295u , 4294967295u , 4294967295u , 4294967295u , 4294967295u , 4294967295u , 4294967295u , 4294967295u , 4294967295u , 4294967295u , 4294967295u , 4294967031u , 4294900972u , 4294900972u , 4294900972u , 4294900972u , 4294900972u , 4294900972u , 4294900972u , 4294900972u , 4293914854u , 4285763230u , 4278597203u , 4278597203u , 4278597203u , 4278597203u , 4278597203u , 4278597203u , 4278597203u , 4278597203u , 4278597203u , 4278597203u , 4278597203u , 4279453282u , 4284985281u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 2674767816u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 2943203272u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4282417045u , 4278597203u , 4278597203u , 4278597203u , 4278597203u , 4278597203u , 4278597203u , 4278597203u , 4278597203u , 4278597203u , 4279649118u , 4289839305u , 4294967295u , 4294967295u , 4294967295u , 4294967295u , 4294967295u , 4294967295u , 4294967295u , 4294967295u , 4294967295u , 4294967295u , 4294967295u , 4294967295u , 4294967295u , 4294967295u , 4294967295u , 4294967295u , 4294967295u , 4294967295u , 4294967295u , 4294967295u , 4294967295u , 4294900974u , 4294900972u , 4294900972u , 4294900972u , 4294900972u , 4294900972u , 4294900972u , 4294900972u , 4294900972u , 4294900972u , 4294967033u , 4288853183u , 4279649118u , 4278597203u , 4278597203u , 4278597203u , 4278597203u , 4278597203u , 4278597203u , 4278597203u , 4278597203u , 4278597203u , 4278597203u , 4281560710u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 3211638728u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 4016945096u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4284524473u , 4278992474u , 4278597203u , 4278597203u , 4278597203u , 4278597203u , 4278597203u , 4278597203u , 4278597203u , 4278597203u , 4279649118u , 4291877343u , 4294967295u , 4294967295u , 4294967295u , 4294967295u , 4294967295u , 4294967295u , 4294967295u , 4294967295u , 4294967295u , 4294967295u , 4294967295u , 4294967295u , 4294967295u , 4294967295u , 4294967295u , 4294967295u , 4294967295u , 4294967295u , 4294967295u , 4294967295u , 4288853183u , 4283724934u , 4294900972u , 4294900972u , 4294900972u , 4294900972u , 4294900972u , 4294900972u , 4294900972u , 4294900972u , 4294900972u , 4294900972u , 4294901235u , 4294967295u , 4291877343u , 4279649118u , 4278597203u , 4278597203u , 4278597203u , 4278597203u , 4278597203u , 4278597203u , 4278597203u , 4278597203u , 4278597203u , 4278597203u , 4283668395u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 812496840u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4281165439u , 4278597203u , 4278597203u , 4278597203u , 4278597203u , 4278597203u , 4278597203u , 4278597203u , 4278597203u , 4279649118u , 4291877343u , 4294967295u , 4294967295u , 4294967295u , 4294967295u , 4294967295u , 4294967295u , 4294967295u , 4294967295u , 4294967295u , 4294967295u , 4294967295u , 4294967295u , 4294967295u , 4294967295u , 4294967295u , 4294967295u , 4294967295u , 4294967295u , 4294967295u , 4292929258u , 4282673278u , 4278597203u , 4282673273u , 4294900972u , 4294900972u , 4294900972u , 4294900972u , 4294900972u , 4294900972u , 4294900972u , 4294900972u , 4294900972u , 4294900972u , 4291876817u , 4288853183u , 4294967295u , 4291877343u , 4279649118u , 4278597203u , 4278597203u , 4278597203u , 4278597203u , 4278597203u , 4278597203u , 4278597203u , 4278597203u , 4278597203u , 4279848553u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 544061384u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 1617803208u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4284524473u , 4278597203u , 4278597203u , 4278597203u , 4278597203u , 4278597203u , 4278597203u , 4278597203u , 4278597203u , 4279649118u , 4291877343u , 4294967295u , 4294967295u , 4294967295u , 4294967295u , 4294967295u , 4294967295u , 4294967295u , 4294967295u , 4294967295u , 4294967295u , 4294967295u , 4294967295u , 4294967295u , 4294967295u , 4294967295u , 4294967295u , 4294967295u , 4294967295u , 4294967295u , 4291877343u , 4279649118u , 4278597203u , 4278597203u , 4280635238u , 4294900972u , 4294900972u , 4294900972u , 4294900972u , 4294900972u , 4294900972u , 4294900972u , 4294900972u , 4294900972u , 4294900972u , 4290825158u , 4278597203u , 4284711316u , 4294967295u , 4291877343u , 4279649118u , 4278597203u , 4278597203u , 4278597203u , 4278597203u , 4278597203u , 4278597203u , 4278597203u , 4278597203u , 4278597203u , 4282812316u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 1080932296u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 2674767816u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4281165439u , 4278597203u , 4278597203u , 4278597203u , 4278597203u , 4278597203u , 4278597203u , 4278597203u , 4278597203u , 4289839305u , 4294967295u , 4294967295u , 4294967295u , 4294967295u , 4294967295u , 4294967295u , 4294967295u , 4294967295u , 4294967295u , 4294967295u , 4294967295u , 4294967295u , 4294967295u , 4294967295u , 4294967295u , 4294967295u , 4294967295u , 4294967295u , 4294967295u , 4291877343u , 4279649118u , 4278597203u , 4278597203u , 4278597203u , 4278597203u , 4291876815u , 4294900972u , 4294900972u , 4294900972u , 4294900972u , 4294900972u , 4294900972u , 4294900972u , 4294900972u , 4294900972u , 4287800745u , 4278597203u , 4278597203u , 4284711316u , 4294967295u , 4288853183u , 4278597203u , 4278597203u , 4278597203u , 4278597203u , 4278597203u , 4278597203u , 4278597203u , 4278597203u , 4278597203u , 4279453282u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 2154674120u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 3211638728u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4284524473u , 4278597203u , 4278597203u , 4278597203u , 4278597203u , 4278597203u , 4278597203u , 4278597203u , 4278597203u , 4285763230u , 4294967295u , 4294967295u , 4294967295u , 4294967295u , 4294967295u , 4294967295u , 4294967295u , 4294967295u , 4294967295u , 4294967295u , 4294967295u , 4294967295u , 4294967295u , 4294967295u , 4294967295u , 4294967295u , 4294967295u , 4294967295u , 4294967295u , 4293915380u , 4279649118u , 4278597203u , 4278597203u , 4278597203u , 4278597203u , 4278597203u , 4283724931u , 4294900972u , 4294900972u , 4294900972u , 4294900972u , 4294900972u , 4294900972u , 4294900972u , 4294900972u , 4294900972u , 4280635238u , 4278597203u , 4278597203u , 4278597203u , 4288853183u , 4294967295u , 4285763230u , 4278597203u , 4278597203u , 4278597203u , 4278597203u , 4278597203u , 4278597203u , 4278597203u , 4278597203u , 4278597203u , 4283668395u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 2674767816u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4282021774u , 4278597203u , 4278597203u , 4278597203u , 4278597203u , 4278597203u , 4278597203u , 4278597203u , 4281687155u , 4294967295u , 4294967295u , 4294967295u , 4294967295u , 4294967295u , 4294967295u , 4294967295u , 4294967295u , 4294967295u , 4294967295u , 4294967295u , 4294967295u , 4294967295u , 4294967295u , 4294967295u , 4294967295u , 4294967295u , 4294967295u , 4294967295u , 4294967295u , 4284711316u , 4278597203u , 4278597203u , 4278597203u , 4278597203u , 4278597203u , 4278597203u , 4278597203u , 4286749088u , 4294900972u , 4294900972u , 4294900972u , 4294900972u , 4294900972u , 4294900972u , 4294900972u , 4284711052u , 4278597203u , 4278597203u , 4278597203u , 4278597203u , 4279649118u , 4293915380u , 4293915380u , 4280635241u , 4278597203u , 4278597203u , 4278597203u , 4278597203u , 4278597203u , 4278597203u , 4278597203u , 4278597203u , 4280704632u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 3211638728u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 812496840u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4279453282u , 4278597203u , 4278597203u , 4278597203u , 4278597203u , 4278597203u , 4278597203u , 4278597203u , 4290891220u , 4294967295u , 4294967295u , 4294967295u , 4294967295u , 4294967295u , 4294967295u , 4294967295u , 4294967295u , 4294967295u , 4294967295u , 4294967295u , 4294967295u , 4294967295u , 4294967295u , 4294967295u , 4294967295u , 4294967295u , 4294967295u , 4294967295u , 4292929258u , 4278597203u , 4278597203u , 4278597203u , 4278597203u , 4278597203u , 4278597203u , 4278597203u , 4278597203u , 4278597203u , 4283724931u , 4291876815u , 4294900972u , 4294900972u , 4294900972u , 4290825158u , 4282673273u , 4278597203u , 4278597203u , 4278597203u , 4278597203u , 4278597203u , 4278597203u , 4285763230u , 4294967295u , 4290891220u , 4278597203u , 4278597203u , 4278597203u , 4278597203u , 4278597203u , 4278597203u , 4278597203u , 4278597203u , 4278597203u , 4284985281u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4016945096u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 1080932296u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4284129202u , 4278597203u , 4278597203u , 4278597203u , 4278597203u , 4278597203u , 4278597203u , 4278597203u , 4283725193u , 4294967295u , 4294967295u , 4294967295u , 4294967295u , 4294967295u , 4294967295u , 4294967295u , 4294967295u , 4294967295u , 4294967295u , 4294967295u , 4294967295u , 4294967295u , 4294967295u , 4294967295u , 4294967295u , 4294967295u , 4294967295u , 4294967295u , 4294967295u , 4285763230u , 4278597203u , 4278597203u , 4278597203u , 4278597203u , 4278597203u , 4278597203u , 4278597203u , 4278597203u , 4278597203u , 4278597203u , 4278597203u , 4278597203u , 4282673273u , 4278597203u , 4278597203u , 4278597203u , 4278597203u , 4278597203u , 4278597203u , 4278597203u , 4278597203u , 4278597203u , 4279649118u , 4294967295u , 4294967295u , 4282673278u , 4278597203u , 4278597203u , 4278597203u , 4278597203u , 4278597203u , 4278597203u , 4278597203u , 4278597203u , 4282812316u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 2154674120u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4282021774u , 4278597203u , 4278597203u , 4278597203u , 4278597203u , 4278597203u , 4278597203u , 4278597203u , 4291877343u , 4294967295u , 4294967295u , 4294967295u , 4294967295u , 4294967295u , 4294967295u , 4294967295u , 4294967295u , 4294967295u , 4294967295u , 4294967295u , 4294967295u , 4294967295u , 4294967295u , 4294967295u , 4294967295u , 4294967295u , 4294967295u , 4294967295u , 4294967295u , 4280635241u , 4278597203u , 4278597203u , 4278597203u , 4278597203u , 4278597203u , 4278597203u , 4278597203u , 4278597203u , 4278597203u , 4278597203u , 4278597203u , 4278597203u , 4278597203u , 4278597203u , 4278597203u , 4278597203u , 4278597203u , 4278597203u , 4278597203u , 4278597203u , 4278597203u , 4278597203u , 4278597203u , 4290891220u , 4294967295u , 4290891220u , 4278597203u , 4278597203u , 4278597203u , 4278597203u , 4278597203u , 4278597203u , 4278597203u , 4278597203u , 4280704632u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 1080932296u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 2406332360u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4280309360u , 4278597203u , 4278597203u , 4278597203u , 4278597203u , 4278597203u , 4278597203u , 4282673278u , 4294967295u , 4294967295u , 4294967295u , 4294967295u , 4294967295u , 4294967295u , 4294967295u , 4294967295u , 4294967295u , 4294967295u , 4294967295u , 4294967295u , 4294967295u , 4294967295u , 4294967295u , 4294967295u , 4294967295u , 4294967295u , 4294967295u , 4294967295u , 4293915380u , 4278597203u , 4278597203u , 4278597203u , 4278597203u , 4278597203u , 4278597203u , 4278597203u , 4278597203u , 4278597203u , 4278597203u , 4278597203u , 4278597203u , 4278597203u , 4278597203u , 4278597203u , 4278597203u , 4278597203u , 4278597203u , 4278597203u , 4278597203u , 4278597203u , 4278597203u , 4278597203u , 4278597203u , 4286815145u , 4294967295u , 4294967295u , 4282673278u , 4278597203u , 4278597203u , 4278597203u , 4278597203u , 4278597203u , 4278597203u , 4278597203u , 4278992474u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 1617803208u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 3211638728u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4278597203u , 4278597203u , 4278597203u , 4278597203u , 4278597203u , 4278597203u , 4278597203u , 4288853183u , 4294967295u , 4294967295u , 4294967295u , 4294967295u , 4294967295u , 4294967295u , 4294967295u , 4294967295u , 4294967295u , 4294967295u , 4294967295u , 4294967295u , 4294967295u , 4294967295u , 4294967295u , 4294967295u , 4294967295u , 4294967295u , 4294967295u , 4294967295u , 4290891220u , 4278597203u , 4278597203u , 4278597203u , 4278597203u , 4278597203u , 4278597203u , 4278597203u , 4278597203u , 4278597203u , 4278597203u , 4278597203u , 4278597203u , 4278597203u , 4278597203u , 4278597203u , 4278597203u , 4278597203u , 4278597203u , 4278597203u , 4278597203u , 4278597203u , 4278597203u , 4278597203u , 4278597203u , 4284711316u , 4294967295u , 4294967295u , 4288853183u , 4278597203u , 4278597203u , 4278597203u , 4278597203u , 4278597203u , 4278597203u , 4278597203u , 4278597203u , 4284129202u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 2154674120u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 3211638728u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4283668395u , 4278597203u , 4278597203u , 4278597203u , 4278597203u , 4278597203u , 4278597203u , 4279649118u , 4294967295u , 4294967295u , 4294967295u , 4294967295u , 4294967295u , 4294967295u , 4294967295u , 4294967295u , 4294967295u , 4294967295u , 4294967295u , 4294967295u , 4294967295u , 4294967295u , 4294967295u , 4294967295u , 4294967295u , 4294967295u , 4294967295u , 4294967295u , 4294967295u , 4290891220u , 4278597203u , 4278597203u , 4278597203u , 4278597203u , 4278597203u , 4278597203u , 4278597203u , 4278597203u , 4278597203u , 4278597203u , 4278597203u , 4278597203u , 4278597203u , 4278597203u , 4278597203u , 4278597203u , 4278597203u , 4278597203u , 4278597203u , 4278597203u , 4278597203u , 4278597203u , 4278597203u , 4278597203u , 4282673278u , 4294967295u , 4294967295u , 4293915380u , 4278597203u , 4278597203u , 4278597203u , 4278597203u , 4278597203u , 4278597203u , 4278597203u , 4278597203u , 4282812316u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 2674767816u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4282812316u , 4278597203u , 4278597203u , 4278597203u , 4278597203u , 4278597203u , 4278597203u , 4283725193u , 4294967295u , 4294967295u , 4294967295u , 4294967295u , 4294967295u , 4294967295u , 4294967295u , 4294967295u , 4294967295u , 4294967295u , 4294967295u , 4294967295u , 4294967295u , 4294967295u , 4294967295u , 4294967295u , 4294967295u , 4294967295u , 4294967295u , 4294967295u , 4294967295u , 4290891220u , 4278597203u , 4278597203u , 4278597203u , 4278597203u , 4278597203u , 4278597203u , 4278597203u , 4278597203u , 4278597203u , 4278597203u , 4278597203u , 4278597203u , 4278597203u , 4278597203u , 4278597203u , 4278597203u , 4278597203u , 4278597203u , 4278597203u , 4278597203u , 4278597203u , 4278597203u , 4278597203u , 4278597203u , 4283725193u , 4294967295u , 4294967295u , 4294967295u , 4283725193u , 4278597203u , 4278597203u , 4278597203u , 4278597203u , 4278597203u , 4278597203u , 4278597203u , 4282021774u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 3211638728u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4282021774u , 4278597203u , 4278597203u , 4278597203u , 4278597203u , 4278597203u , 4278597203u , 4287801268u , 4294967295u , 4294967295u , 4294967295u , 4294967295u , 4294967295u , 4294967295u , 4294967295u , 4294967295u , 4294967295u , 4294967295u , 4294967295u , 4294967295u , 4294967295u , 4294967295u , 4294967295u , 4294967295u , 4294967295u , 4294967295u , 4294967295u , 4294967295u , 4294967295u , 4291877343u , 4278597203u , 4278597203u , 4278597203u , 4278597203u , 4278597203u , 4278597203u , 4278597203u , 4278597203u , 4278597203u , 4278597203u , 4278597203u , 4278597203u , 4278597203u , 4278597203u , 4278597203u , 4278597203u , 4278597203u , 4278597203u , 4278597203u , 4278597203u , 4278597203u , 4278597203u , 4278597203u , 4278597203u , 4286815145u , 4294967295u , 4294967295u , 4294967295u , 4287801268u , 4278597203u , 4278597203u , 4278597203u , 4278597203u , 4278597203u , 4278597203u , 4278597203u , 4280309360u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4016945096u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4281560710u , 4278597203u , 4278597203u , 4278597203u , 4278597203u , 4278597203u , 4278597203u , 4291877343u , 4294967295u , 4294967295u , 4294967295u , 4294967295u , 4294967295u , 4294967295u , 4294967295u , 4294967295u , 4294967295u , 4294967295u , 4294967295u , 4294967295u , 4294967295u , 4294967295u , 4294967295u , 4294967295u , 4294967295u , 4294967295u , 4294967295u , 4294967295u , 4294967295u , 4294967295u , 4279649118u , 4278597203u , 4278597203u , 4278597203u , 4278597203u , 4278597203u , 4278597203u , 4278597203u , 4278597203u , 4278597203u , 4278597203u , 4278597203u , 4278597203u , 4278597203u , 4278597203u , 4278597203u , 4278597203u , 4278597203u , 4278597203u , 4278597203u , 4278597203u , 4278597203u , 4278597203u , 4278597203u , 4288853183u , 4294967295u , 4294967295u , 4294967295u , 4290891220u , 4278597203u , 4278597203u , 4278597203u , 4278597203u , 4278597203u , 4278597203u , 4278597203u , 4280309360u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 1080932296u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4280309360u , 4278597203u , 4278597203u , 4278597203u , 4278597203u , 4278597203u , 4278597203u , 4294967295u , 4294967295u , 4294967295u , 4294967295u , 4294967295u , 4294967295u , 4294967295u , 4294967295u , 4294967295u , 4294967295u , 4294967295u , 4294967295u , 4294967295u , 4294967295u , 4294967295u , 4294967295u , 4294967295u , 4294967295u , 4294967295u , 4294967295u , 4294967295u , 4294967295u , 4294967295u , 4283725193u , 4278597203u , 4278597203u , 4278597203u , 4278597203u , 4278597203u , 4278597203u , 4278597203u , 4278597203u , 4278597203u , 4278597203u , 4278597203u , 4278597203u , 4278597203u , 4278597203u , 4278597203u , 4278597203u , 4278597203u , 4278597203u , 4278597203u , 4278597203u , 4278597203u , 4278597203u , 4278597203u , 4292929258u , 4294967295u , 4294967295u , 4294967295u , 4294967295u , 4278597203u , 4278597203u , 4278597203u , 4278597203u , 4278597203u , 4278597203u , 4278597203u , 4280309360u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 812496840u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 1080932296u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4280309360u , 4278597203u , 4278597203u , 4278597203u , 4278597203u , 4278597203u , 4280635241u , 4294967295u , 4294967295u , 4294967295u , 4294967295u , 4294967295u , 4294967295u , 4294967295u , 4294967295u , 4294967295u , 4294967295u , 4294967295u , 4294967295u , 4294967295u , 4294967295u , 4294967295u , 4294967295u , 4294967295u , 4294967295u , 4294967295u , 4294967295u , 4294967295u , 4294967295u , 4294967295u , 4288853183u , 4278597203u , 4278597203u , 4278597203u , 4278597203u , 4278597203u , 4278597203u , 4278597203u , 4278597203u , 4278597203u , 4278597203u , 4278597203u , 4278597203u , 4278597203u , 4278597203u , 4278597203u , 4278597203u , 4278597203u , 4278597203u , 4278597203u , 4278597203u , 4278597203u , 4278597203u , 4282673278u , 4294967295u , 4294967295u , 4294967295u , 4294967295u , 4294967295u , 4278597203u , 4278597203u , 4278597203u , 4278597203u , 4278597203u , 4278597203u , 4278597203u , 4278992474u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 1080932296u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 1080932296u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4280309360u , 4278597203u , 4278597203u , 4278597203u , 4278597203u , 4278597203u , 4282673278u , 4294967295u , 4294967295u , 4294967295u , 4294967295u , 4294967295u , 4294967295u , 4294967295u , 4294967295u , 4294967295u , 4294967295u , 4294967295u , 4294967295u , 4294967295u , 4294967295u , 4294967295u , 4294967295u , 4294967295u , 4294967295u , 4294967295u , 4294967295u , 4294967295u , 4294967295u , 4294967295u , 4294967295u , 4280635241u , 4278597203u , 4278597203u , 4278597203u , 4278597203u , 4278597203u , 4278597203u , 4278597203u , 4278597203u , 4278597203u , 4278597203u , 4278597203u , 4278597203u , 4278597203u , 4278597203u , 4278597203u , 4278597203u , 4278597203u , 4278597203u , 4278597203u , 4278597203u , 4278597203u , 4290891220u , 4294967295u , 4294967295u , 4294967295u , 4294967295u , 4294967295u , 4282673278u , 4278597203u , 4278597203u , 4278597203u , 4278597203u , 4278597203u , 4278597203u , 4278597203u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 1617803208u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 1080932296u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4280309360u , 4278597203u , 4278597203u , 4278597203u , 4278597203u , 4278597203u , 4282673278u , 4294967295u , 4294967295u , 4294967295u , 4294967295u , 4294967295u , 4294967295u , 4294967295u , 4294967295u , 4294967295u , 4294967295u , 4294967295u , 4294967295u , 4294967295u , 4294967295u , 4294967295u , 4294967295u , 4294967295u , 4294967295u , 4294967295u , 4294967295u , 4294967295u , 4294967295u , 4294967295u , 4294967295u , 4290891220u , 4278597203u , 4278597203u , 4278597203u , 4278597203u , 4278597203u , 4278597203u , 4278597203u , 4278597203u , 4278597203u , 4278597203u , 4278597203u , 4278597203u , 4278597203u , 4278597203u , 4278597203u , 4278597203u , 4278597203u , 4278597203u , 4278597203u , 4278597203u , 4283725193u , 4294967295u , 4294967295u , 4294967295u , 4294967295u , 4294967295u , 4294967295u , 4282673278u , 4278597203u , 4278597203u , 4278597203u , 4278597203u , 4278597203u , 4278597203u , 4278992474u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 2154674120u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 1080932296u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4280309360u , 4278597203u , 4278597203u , 4278597203u , 4278597203u , 4278597203u , 4282673278u , 4294967295u , 4294967295u , 4294967295u , 4294967295u , 4294967295u , 4294967295u , 4294967295u , 4294967295u , 4294967295u , 4294967295u , 4294967295u , 4294967295u , 4294967295u , 4294967295u , 4294967295u , 4294967295u , 4294967295u , 4294967295u , 4294967295u , 4294967295u , 4294967295u , 4294967295u , 4294967295u , 4294967295u , 4294967295u , 4285763230u , 4278597203u , 4278597203u , 4278597203u , 4278597203u , 4278597203u , 4278597203u , 4278597203u , 4278597203u , 4278597203u , 4278597203u , 4278597203u , 4278597203u , 4278597203u , 4278597203u , 4278597203u , 4278597203u , 4278597203u , 4278597203u , 4280635241u , 4293915380u , 4294967295u , 4294967295u , 4294967295u , 4294967295u , 4294967295u , 4294967295u , 4282673278u , 4278597203u , 4278597203u , 4278597203u , 4278597203u , 4278597203u , 4278597203u , 4280309360u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 2154674120u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 1080932296u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4281560710u , 4278597203u , 4278597203u , 4278597203u , 4278597203u , 4278597203u , 4282673278u , 4294967295u , 4294967295u , 4294967295u , 4294967295u , 4294967295u , 4294967295u , 4294967295u , 4294967295u , 4294967295u , 4294967295u , 4294967295u , 4294967295u , 4294967295u , 4294967295u , 4294967295u , 4294967295u , 4294967295u , 4294967295u , 4294967295u , 4294967295u , 4294967295u , 4294967295u , 4294967295u , 4294967295u , 4294967295u , 4294967295u , 4284711316u , 4278597203u , 4278597203u , 4278597203u , 4278597203u , 4278597203u , 4278597203u , 4278597203u , 4278597203u , 4278597203u , 4278597203u , 4278597203u , 4278597203u , 4278597203u , 4278597203u , 4278597203u , 4278597203u , 4279649118u , 4291877343u , 4294967295u , 4294967295u , 4294967295u , 4294967295u , 4294967295u , 4294967295u , 4294967295u , 4282673278u , 4278597203u , 4278597203u , 4278597203u , 4278597203u , 4278597203u , 4278597203u , 4280309360u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 3211638728u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 1080932296u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4282021774u , 4278597203u , 4278597203u , 4278597203u , 4278597203u , 4278597203u , 4282673278u , 4294967295u , 4294967295u , 4294967295u , 4294967295u , 4294967295u , 4294967295u , 4294967295u , 4294967295u , 4294967295u , 4294967295u , 4294967295u , 4294967295u , 4294967295u , 4294967295u , 4294967295u , 4294967295u , 4294967295u , 4294967295u , 4294967295u , 4294967295u , 4294967295u , 4294967295u , 4294967295u , 4294967295u , 4294967295u , 4294967295u , 4294967295u , 4286815145u , 4278597203u , 4278597203u , 4278597203u , 4278597203u , 4278597203u , 4278597203u , 4278597203u , 4278597203u , 4278597203u , 4278597203u , 4278597203u , 4278597203u , 4278597203u , 4278597203u , 4281687155u , 4293915380u , 4294967295u , 4294967295u , 4294967295u , 4294967295u , 4294967295u , 4294967295u , 4294967295u , 4294967295u , 4282673278u , 4278597203u , 4278597203u , 4278597203u , 4278597203u , 4278597203u , 4278597203u , 4280704632u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 3211638728u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 1080932296u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4282812316u , 4278597203u , 4278597203u , 4278597203u , 4278597203u , 4278597203u , 4282673278u , 4294967295u , 4294967295u , 4294967295u , 4294967295u , 4294967295u , 4294967295u , 4294967295u , 4294967295u , 4294967295u , 4294967295u , 4294967295u , 4294967295u , 4294967295u , 4294967295u , 4294967295u , 4294967295u , 4294967295u , 4294967295u , 4294967295u , 4294967295u , 4294967295u , 4294967295u , 4294967295u , 4294967295u , 4294967295u , 4294967295u , 4294967295u , 4294967295u , 4291877343u , 4282673278u , 4278597203u , 4278597203u , 4278597203u , 4278597203u , 4278597203u , 4278597203u , 4278597203u , 4278597203u , 4278597203u , 4278597203u , 4279649118u , 4287801268u , 4294967295u , 4294967295u , 4294967295u , 4294967295u , 4294967295u , 4294967295u , 4294967295u , 4294967295u , 4294967295u , 4294967295u , 4280635241u , 4278597203u , 4278597203u , 4278597203u , 4278597203u , 4278597203u , 4278597203u , 4282021774u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 3748509640u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 1080932296u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4283668395u , 4278597203u , 4278597203u , 4278597203u , 4278597203u , 4278597203u , 4278597203u , 4294967295u , 4294967295u , 4294967295u , 4294967295u , 4294967295u , 4294967295u , 4294967295u , 4294967295u , 4294967295u , 4294967295u , 4294967295u , 4294967295u , 4294967295u , 4294967295u , 4294967295u , 4294967295u , 4294967295u , 4294967295u , 4294967295u , 4294967295u , 4294967295u , 4294967295u , 4294967295u , 4294967295u , 4294967295u , 4294967295u , 4294967295u , 4294967295u , 4294967295u , 4294967295u , 4291877343u , 4285763230u , 4281687155u , 4278597203u , 4278597203u , 4278597203u , 4278597203u , 4280635241u , 4283725193u , 4288853183u , 4294967295u , 4294967295u , 4294967295u , 4294967295u , 4294967295u , 4294967295u , 4294967295u , 4294967295u , 4294967295u , 4294967295u , 4294967295u , 4294967295u , 4278597203u , 4278597203u , 4278597203u , 4278597203u , 4278597203u , 4278597203u , 4278597203u , 4282812316u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 1080932296u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4278597203u , 4278597203u , 4278597203u , 4278597203u , 4278597203u , 4278597203u , 4292929258u , 4294967295u , 4294967295u , 4294967295u , 4294967295u , 4294967295u , 4294967295u , 4294967295u , 4294967295u , 4294967295u , 4294967295u , 4294967295u , 4294967295u , 4294967295u , 4294967295u , 4294967295u , 4294967295u , 4294967295u , 4294967295u , 4294967295u , 4294967295u , 4294967295u , 4294967295u , 4294967295u , 4294967295u , 4294967295u , 4294967295u , 4294967295u , 4294967295u , 4294967295u , 4294967295u , 4294967295u , 4294967295u , 4294967295u , 4294967295u , 4294967295u , 4294967295u , 4294967295u , 4294967295u , 4294967295u , 4294967295u , 4294967295u , 4294967295u , 4294967295u , 4294967295u , 4294967295u , 4294967295u , 4294967295u , 4294967295u , 4294967295u , 4294967295u , 4291877343u , 4278597203u , 4278597203u , 4278597203u , 4278597203u , 4278597203u , 4278597203u , 4278597203u , 4284129202u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 1080932296u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4280309360u , 4278597203u , 4278597203u , 4278597203u , 4278597203u , 4278597203u , 4289839305u , 4294967295u , 4294967295u , 4294967295u , 4294967295u , 4294967295u , 4294967295u , 4294967295u , 4294967295u , 4294967295u , 4294967295u , 4294967295u , 4294967295u , 4294967295u , 4294967295u , 4294967295u , 4294967295u , 4294967295u , 4294967295u , 4294967295u , 4294967295u , 4294967295u , 4294967295u , 4294967295u , 4294967295u , 4294967295u , 4294967295u , 4294967295u , 4294967295u , 4294967295u , 4294967295u , 4294967295u , 4294967295u , 4294967295u , 4294967295u , 4294967295u , 4294967295u , 4294967295u , 4294967295u , 4294967295u , 4294967295u , 4294967295u , 4294967295u , 4294967295u , 4294967295u , 4294967295u , 4294967295u , 4294967295u , 4294967295u , 4294967295u , 4294967295u , 4288853183u , 4278597203u , 4278597203u , 4278597203u , 4278597203u , 4278597203u , 4278597203u , 4278992474u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4283668395u , 4283668395u , 4282021774u , 4282021774u , 4282021774u , 4282021774u , 4282021774u , 4282021774u , 4282021774u , 4282021774u , 4282021774u , 4282417045u , 4283668395u , 4283668395u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 544061384u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 1080932296u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4282021774u , 4278597203u , 4278597203u , 4278597203u , 4278597203u , 4278597203u , 4285763230u , 4294967295u , 4294967295u , 4294967295u , 4294967295u , 4294967295u , 4294967295u , 4294967295u , 4294967295u , 4294967295u , 4294967295u , 4294967295u , 4294967295u , 4294967295u , 4294967295u , 4294967295u , 4294967295u , 4294967295u , 4294967295u , 4294967295u , 4294967295u , 4294967295u , 4294967295u , 4294967295u , 4294967295u , 4294967295u , 4294967295u , 4294967295u , 4294967295u , 4294967295u , 4294967295u , 4294967295u , 4294967295u , 4294967295u , 4294967295u , 4294967295u , 4294967295u , 4294967295u , 4294967295u , 4294967295u , 4294967295u , 4294967295u , 4294967295u , 4294967295u , 4294967295u , 4294967295u , 4294967295u , 4294967295u , 4294967295u , 4294967295u , 4294967295u , 4284711316u , 4278597203u , 4278597203u , 4278597203u , 4278597203u , 4278597203u , 4278597203u , 4280704632u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4284524473u , 4282812316u , 4281165439u , 4279848553u , 4278597203u , 4278597203u , 4278597203u , 4278597203u , 4280635238u , 4282673273u , 4286749088u , 4286749088u , 4286749088u , 4286749088u , 4285762966u , 4282673273u , 4278597203u , 4278597203u , 4278597203u , 4278597203u , 4279453282u , 4281165439u , 4284985281u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 1080932296u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 812496840u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4284129202u , 4278597203u , 4278597203u , 4278597203u , 4278597203u , 4278597203u , 4280635241u , 4294967295u , 4294967295u , 4294967295u , 4294967295u , 4294967295u , 4294967295u , 4294967295u , 4294967295u , 4294967295u , 4294967295u , 4294967295u , 4294967295u , 4294967295u , 4294967295u , 4294967295u , 4294967295u , 4294967295u , 4294967295u , 4294967295u , 4294967295u , 4294967295u , 4294967295u , 4294967295u , 4294967295u , 4294967295u , 4294967295u , 4294967295u , 4294967295u , 4294967295u , 4294967295u , 4294967295u , 4294967295u , 4294967295u , 4294967295u , 4294967295u , 4294967295u , 4294967295u , 4294967295u , 4294967295u , 4294967295u , 4294967295u , 4294967295u , 4294967295u , 4294967295u , 4294967295u , 4294967295u , 4294967295u , 4294967295u , 4294967295u , 4294967295u , 4280635241u , 4278597203u , 4278597203u , 4278597203u , 4278597203u , 4278597203u , 4278597203u , 4282812316u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4284985281u , 4282417045u , 4279848553u , 4278597203u , 4278597203u , 4278597203u , 4278597203u , 4278597203u , 4279648861u , 4286749088u , 4292862937u , 4294900972u , 4294900972u , 4294900972u , 4294900972u , 4294900972u , 4294900972u , 4294900972u , 4294900972u , 4293914850u , 4287800745u , 4279648861u , 4278597203u , 4278597203u , 4278597203u , 4279848553u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 1080932296u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4279453282u , 4278597203u , 4278597203u , 4278597203u , 4278597203u , 4278597203u , 4291877343u , 4294967295u , 4294967295u , 4294967295u , 4294967295u , 4294967295u , 4294967295u , 4294967295u , 4294967295u , 4294967295u , 4294967295u , 4294967295u , 4294967295u , 4294967295u , 4294967295u , 4294967295u , 4294967295u , 4294967295u , 4294967295u , 4294967295u , 4294967295u , 4294967295u , 4294967295u , 4294967295u , 4294967295u , 4294967295u , 4294967295u , 4294967295u , 4294967295u , 4294967295u , 4294967295u , 4294967295u , 4294967295u , 4294967295u , 4294967295u , 4294967295u , 4294967295u , 4294967295u , 4294967295u , 4294967295u , 4294967295u , 4294967295u , 4294967295u , 4294967295u , 4294967295u , 4294967295u , 4294967295u , 4294967295u , 4294967295u , 4291877343u , 4278597203u , 4278597203u , 4278597203u , 4278597203u , 4278597203u , 4278597203u , 4278597203u , 4284985281u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4284524473u , 4281165439u , 4278597203u , 4278597203u , 4278597203u , 4278597203u , 4278597203u , 4278597203u , 4278597203u , 4281686896u , 4293914850u , 4294900972u , 4294900972u , 4294900972u , 4294900972u , 4294900972u , 4294900972u , 4294900972u , 4294900972u , 4294900972u , 4294900972u , 4294900972u , 4294900972u , 4289838780u , 4278597203u , 4278597203u , 4278597203u , 4278597203u , 4283273123u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 1080932296u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4282021774u , 4278597203u , 4278597203u , 4278597203u , 4278597203u , 4278597203u , 4285763230u , 4294967295u , 4294967295u , 4294967295u , 4294967295u , 4294967295u , 4294967295u , 4294967295u , 4294967295u , 4294967295u , 4294967295u , 4294967295u , 4294967295u , 4294967295u , 4294967295u , 4294967295u , 4294967295u , 4294967295u , 4294967295u , 4294967295u , 4294967295u , 4294967295u , 4294967295u , 4294967295u , 4294967295u , 4294967295u , 4294967295u , 4294967295u , 4294967295u , 4294967295u , 4294967295u , 4294967295u , 4294967295u , 4294967295u , 4294967295u , 4294967295u , 4294967295u , 4294967295u , 4294967295u , 4294967295u , 4294967295u , 4294967295u , 4294967295u , 4294967295u , 4294967295u , 4294967295u , 4294967295u , 4294967295u , 4294967295u , 4284711316u , 4278597203u , 4278597203u , 4278597203u , 4278597203u , 4278597203u , 4278597203u , 4281165439u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4284524473u , 4281165439u , 4278597203u , 4278597203u , 4278597203u , 4278597203u , 4278597203u , 4278597203u , 4278597203u , 4278597203u , 4278597203u , 4292862937u , 4294900972u , 4294900972u , 4294900972u , 4294900972u , 4294900972u , 4294900972u , 4294900972u , 4294900972u , 4294900972u , 4294900972u , 4294900972u , 4294900972u , 4294900972u , 4290825158u , 4278597203u , 4278597203u , 4278597203u , 4278597203u , 4282021774u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 1617803208u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 4016945096u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4284524473u , 4278597203u , 4278597203u , 4278597203u , 4278597203u , 4278597203u , 4279649118u , 4293915380u , 4294967295u , 4294967295u , 4294967295u , 4294967295u , 4294967295u , 4294967295u , 4294967295u , 4294967295u , 4294967295u , 4294967295u , 4294967295u , 4294967295u , 4294967295u , 4294967295u , 4294967295u , 4294967295u , 4294967295u , 4294967295u , 4294967295u , 4294967295u , 4294967295u , 4294967295u , 4294967295u , 4294967295u , 4294967295u , 4294967295u , 4294967295u , 4294967295u , 4294967295u , 4294967295u , 4294967295u , 4294967295u , 4294967295u , 4294967295u , 4294967295u , 4294967295u , 4294967295u , 4294967295u , 4294967295u , 4294967295u , 4294967295u , 4294967295u , 4294967295u , 4294967295u , 4294967295u , 4294967295u , 4293915380u , 4278597203u , 4278597203u , 4278597203u , 4278597203u , 4278597203u , 4278597203u , 4278597203u , 4283668395u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4282021774u , 4278992474u , 4278597203u , 4278597203u , 4278597203u , 4278597203u , 4278597203u , 4278597203u , 4278597203u , 4278597203u , 4278597203u , 4278597203u , 4292862937u , 4294900972u , 4294900972u , 4294900972u , 4294900972u , 4294900972u , 4294900972u , 4294900972u , 4294900972u , 4294900972u , 4294900972u , 4294900972u , 4294900972u , 4293914850u , 4283724931u , 4278597203u , 4278597203u , 4278597203u , 4278597203u , 4282812316u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 2154674120u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 3211638728u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4281165439u , 4278597203u , 4278597203u , 4278597203u , 4278597203u , 4278597203u , 4286815145u , 4294967295u , 4294967295u , 4294967295u , 4294967295u , 4294967295u , 4294967295u , 4294967295u , 4294967295u , 4294967295u , 4294967295u , 4294967295u , 4294967295u , 4294967295u , 4294967295u , 4294967295u , 4294967295u , 4294967295u , 4294967295u , 4294967295u , 4294967295u , 4294967295u , 4294967295u , 4294967295u , 4294967295u , 4294967295u , 4294967295u , 4294967295u , 4294967295u , 4294967295u , 4294967295u , 4294967295u , 4294967295u , 4294967295u , 4294967295u , 4294967295u , 4294967295u , 4294967295u , 4294967295u , 4294967295u , 4294967295u , 4294967295u , 4294967295u , 4294967295u , 4294967295u , 4294967295u , 4294967295u , 4286815145u , 4278597203u , 4278597203u , 4278597203u , 4278597203u , 4278597203u , 4278597203u , 4279848553u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4284524473u , 4280309360u , 4278597203u , 4278597203u , 4278597203u , 4278597203u , 4278597203u , 4278597203u , 4278597203u , 4278597203u , 4278597203u , 4278597203u , 4278597203u , 4278597203u , 4281686896u , 4291876815u , 4294900972u , 4294900972u , 4294900972u , 4294900972u , 4294900972u , 4294900972u , 4294900972u , 4294900972u , 4294900972u , 4293914850u , 4288787123u , 4280635238u , 4278597203u , 4278597203u , 4278597203u , 4278597203u , 4278597203u , 4284524473u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 2154674120u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 3211638728u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4284524473u , 4278597203u , 4278597203u , 4278597203u , 4278597203u , 4278597203u , 4279649118u , 4293915380u , 4294967295u , 4294967295u , 4294967295u , 4294967295u , 4294967295u , 4294967295u , 4294967295u , 4294967295u , 4294967295u , 4294967295u , 4294967295u , 4294967295u , 4294967295u , 4294967295u , 4294967295u , 4294967295u , 4294967295u , 4294967295u , 4294967295u , 4294967295u , 4294967295u , 4294967295u , 4294967295u , 4294967295u , 4294967295u , 4294967295u , 4294967295u , 4294967295u , 4294967295u , 4294967295u , 4294967295u , 4294967295u , 4294967295u , 4294967295u , 4294967295u , 4294967295u , 4294967295u , 4294967295u , 4294967295u , 4294967295u , 4294967295u , 4294967295u , 4294967295u , 4294967295u , 4292929258u , 4279649118u , 4278597203u , 4278597203u , 4278597203u , 4278597203u , 4278597203u , 4278597203u , 4282812316u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4284129202u , 4278992474u , 4278597203u , 4278597203u , 4278597203u , 4278597203u , 4278597203u , 4278597203u , 4278597203u , 4278597203u , 4278597203u , 4278597203u , 4278597203u , 4278597203u , 4278597203u , 4278597203u , 4278597203u , 4281686896u , 4285762966u , 4287800745u , 4290825158u , 4290825158u , 4290825158u , 4287800745u , 4286749088u , 4282673273u , 4278597203u , 4278597203u , 4278597203u , 4278597203u , 4278597203u , 4278597203u , 4278597203u , 4279848553u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 2154674120u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 2154674120u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4281165439u , 4278597203u , 4278597203u , 4278597203u , 4278597203u , 4278597203u , 4284711316u , 4294967295u , 4294967295u , 4294967295u , 4294967295u , 4294967295u , 4294967295u , 4294967295u , 4294967295u , 4294967295u , 4294967295u , 4294967295u , 4294967295u , 4294967295u , 4294967295u , 4294967295u , 4294967295u , 4294967295u , 4294967295u , 4294967295u , 4294967295u , 4294967295u , 4294967295u , 4294967295u , 4294967295u , 4294967295u , 4294967295u , 4294967295u , 4294967295u , 4294967295u , 4294967295u , 4294967295u , 4294967295u , 4294967295u , 4294967295u , 4294967295u , 4294967295u , 4294967295u , 4294967295u , 4294967295u , 4294967295u , 4294967295u , 4294967295u , 4294967295u , 4294967295u , 4283725193u , 4278597203u , 4278597203u , 4278597203u , 4278597203u , 4278597203u , 4278597203u , 4280309360u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4282812316u , 4278992474u , 4278597203u , 4278597203u , 4278597203u , 4278597203u , 4278597203u , 4278597203u , 4278597203u , 4278597203u , 4278597203u , 4278597203u , 4278597203u , 4278597203u , 4278597203u , 4278597203u , 4278597203u , 4278597203u , 4278597203u , 4278597203u , 4278597203u , 4278597203u , 4278597203u , 4278597203u , 4278597203u , 4278597203u , 4278597203u , 4278597203u , 4278597203u , 4278597203u , 4278597203u , 4278597203u , 4278597203u , 4278597203u , 4282812316u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 2154674120u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 2154674120u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4284985281u , 4278992474u , 4278597203u , 4278597203u , 4278597203u , 4278597203u , 4278597203u , 4290891220u , 4294967295u , 4294967295u , 4294967295u , 4294967295u , 4294967295u , 4294967295u , 4294967295u , 4294967295u , 4294967295u , 4294967295u , 4294967295u , 4294967295u , 4294967295u , 4294967295u , 4294967295u , 4294967295u , 4294967295u , 4294967295u , 4294967295u , 4294967295u , 4294967295u , 4294967295u , 4294967295u , 4294967295u , 4294967295u , 4294967295u , 4294967295u , 4294967295u , 4294967295u , 4294967295u , 4294967295u , 4294967295u , 4294967295u , 4294967295u , 4294967295u , 4294967295u , 4294967295u , 4294967295u , 4294967295u , 4294967295u , 4294967295u , 4294967295u , 4289839305u , 4278597203u , 4278597203u , 4278597203u , 4278597203u , 4278597203u , 4278597203u , 4278597203u , 4283668395u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4284129202u , 4278597203u , 4278597203u , 4278597203u , 4278597203u , 4278597203u , 4278597203u , 4278597203u , 4278597203u , 4278597203u , 4278597203u , 4278597203u , 4278597203u , 4278597203u , 4278597203u , 4278597203u , 4278597203u , 4278597203u , 4278597203u , 4278597203u , 4278597203u , 4278597203u , 4278597203u , 4278597203u , 4278597203u , 4278597203u , 4278597203u , 4278597203u , 4278597203u , 4278597203u , 4278597203u , 4278597203u , 4278597203u , 4278597203u , 4281165439u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 2154674120u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 1080932296u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4282417045u , 4278597203u , 4278597203u , 4278597203u , 4278597203u , 4278597203u , 4279649118u , 4293915380u , 4294967295u , 4294967295u , 4294967295u , 4294967295u , 4294967295u , 4294967295u , 4294967295u , 4294967295u , 4294967295u , 4294967295u , 4294967295u , 4294967295u , 4294967295u , 4294967295u , 4294967295u , 4294967295u , 4294967295u , 4294967295u , 4294967295u , 4294967295u , 4294967295u , 4294967295u , 4294967295u , 4294967295u , 4294967295u , 4294967295u , 4294967295u , 4294967295u , 4294967295u , 4294967295u , 4294967295u , 4294967295u , 4294967295u , 4294967295u , 4294967295u , 4294967295u , 4294967295u , 4294967295u , 4294967295u , 4294967295u , 4292929258u , 4279649118u , 4278597203u , 4278597203u , 4278597203u , 4278597203u , 4278597203u , 4278597203u , 4281560710u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4284524473u , 4278992474u , 4278597203u , 4278597203u , 4278597203u , 4278597203u , 4278597203u , 4278597203u , 4278597203u , 4278597203u , 4278597203u , 4278597203u , 4278597203u , 4278597203u , 4278597203u , 4278597203u , 4278597203u , 4278597203u , 4278597203u , 4278597203u , 4278597203u , 4278597203u , 4278597203u , 4278597203u , 4278597203u , 4278597203u , 4278597203u , 4278597203u , 4278597203u , 4278597203u , 4278597203u , 4278597203u , 4278597203u , 4278597203u , 4279848553u , 4284985281u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 2154674120u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 812496840u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4280309360u , 4278597203u , 4278597203u , 4278597203u , 4278597203u , 4278597203u , 4281687155u , 4293915380u , 4294967295u , 4294967295u , 4294967295u , 4294967295u , 4294967295u , 4294967295u , 4294967295u , 4294967295u , 4294967295u , 4294967295u , 4294967295u , 4294967295u , 4294967295u , 4294967295u , 4294967295u , 4294967295u , 4294967295u , 4294967295u , 4294967295u , 4294967295u , 4294967295u , 4294967295u , 4294967295u , 4294967295u , 4294967295u , 4294967295u , 4294967295u , 4294967295u , 4294967295u , 4294967295u , 4294967295u , 4294967295u , 4294967295u , 4294967295u , 4294967295u , 4294967295u , 4294967295u , 4294967295u , 4293915380u , 4281687155u , 4278597203u , 4278597203u , 4278597203u , 4278597203u , 4278597203u , 4278597203u , 4279453282u , 4284985281u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4281560710u , 4278597203u , 4278597203u , 4278597203u , 4278597203u , 4278597203u , 4278597203u , 4278597203u , 4278597203u , 4278597203u , 4278597203u , 4278597203u , 4278597203u , 4278597203u , 4278597203u , 4278597203u , 4278597203u , 4278597203u , 4278597203u , 4278597203u , 4278597203u , 4278597203u , 4278597203u , 4278597203u , 4278597203u , 4278597203u , 4278597203u , 4278597203u , 4278597203u , 4278597203u , 4278597203u , 4278597203u , 4278597203u , 4279848553u , 4284985281u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 2943203272u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4284985281u , 4278992474u , 4278597203u , 4278597203u , 4278597203u , 4278597203u , 4278597203u , 4284711316u , 4294967295u , 4294967295u , 4294967295u , 4294967295u , 4294967295u , 4294967295u , 4294967295u , 4294967295u , 4294967295u , 4294967295u , 4294967295u , 4294967295u , 4294967295u , 4294967295u , 4294967295u , 4294967295u , 4294967295u , 4294967295u , 4294967295u , 4294967295u , 4294967295u , 4294967295u , 4294967295u , 4294967295u , 4294967295u , 4294967295u , 4294967295u , 4294967295u , 4294967295u , 4294967295u , 4294967295u , 4294967295u , 4294967295u , 4294967295u , 4294967295u , 4294967295u , 4294967295u , 4294967295u , 4283725193u , 4278597203u , 4278597203u , 4278597203u , 4278597203u , 4278597203u , 4278597203u , 4278597203u , 4284129202u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4280309360u , 4278597203u , 4278597203u , 4278597203u , 4278597203u , 4278597203u , 4278597203u , 4278597203u , 4278597203u , 4278597203u , 4278597203u , 4278597203u , 4278597203u , 4278597203u , 4278597203u , 4278597203u , 4278597203u , 4278597203u , 4278597203u , 4278597203u , 4278597203u , 4278597203u , 4278597203u , 4278597203u , 4278597203u , 4278597203u , 4278597203u , 4278597203u , 4278597203u , 4278597203u , 4278597203u , 4278597203u , 4279848553u , 4284985281u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 3211638728u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 3480074184u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4284129202u , 4278597203u , 4278597203u , 4278597203u , 4278597203u , 4278597203u , 4278597203u , 4284711316u , 4294967295u , 4294967295u , 4294967295u , 4294967295u , 4294967295u , 4294967295u , 4294967295u , 4294967295u , 4294967295u , 4294967295u , 4294967295u , 4294967295u , 4294967295u , 4294967295u , 4294967295u , 4294967295u , 4294967295u , 4294967295u , 4294967295u , 4294967295u , 4294967295u , 4294967295u , 4294967295u , 4294967295u , 4294967295u , 4294967295u , 4294967295u , 4294967295u , 4294967295u , 4294967295u , 4294967295u , 4294967295u , 4294967295u , 4294967295u , 4294967295u , 4294967295u , 4284711316u , 4278597203u , 4278597203u , 4278597203u , 4278597203u , 4278597203u , 4278597203u , 4278597203u , 4282812316u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4280309360u , 4278597203u , 4278597203u , 4278597203u , 4278597203u , 4278597203u , 4278597203u , 4278597203u , 4278597203u , 4278597203u , 4278597203u , 4278597203u , 4278597203u , 4278597203u , 4278597203u , 4278597203u , 4278597203u , 4278597203u , 4278597203u , 4278597203u , 4278597203u , 4278597203u , 4278597203u , 4278597203u , 4278597203u , 4278597203u , 4278597203u , 4278597203u , 4278597203u , 4278597203u , 4278597203u , 4279453282u , 4284985281u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 3211638728u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 2674767816u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4282812316u , 4278597203u , 4278597203u , 4278597203u , 4278597203u , 4278597203u , 4278597203u , 4282673278u , 4293915380u , 4294967295u , 4294967295u , 4294967295u , 4294967295u , 4294967295u , 4294967295u , 4294967295u , 4294967295u , 4294967295u , 4294967295u , 4294967295u , 4294967295u , 4294967295u , 4294967295u , 4294967295u , 4294967295u , 4294967295u , 4294967295u , 4294967295u , 4294967295u , 4294967295u , 4294967295u , 4294967295u , 4294967295u , 4294967295u , 4294967295u , 4294967295u , 4294967295u , 4294967295u , 4294967295u , 4294967295u , 4294967295u , 4293915380u , 4281687155u , 4278597203u , 4278597203u , 4278597203u , 4278597203u , 4278597203u , 4278597203u , 4278597203u , 4281560710u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4280309360u , 4278597203u , 4278597203u , 4278597203u , 4278597203u , 4278597203u , 4278597203u , 4278597203u , 4278597203u , 4278597203u , 4278597203u , 4278597203u , 4278597203u , 4278597203u , 4278597203u , 4278597203u , 4278597203u , 4278597203u , 4278597203u , 4278597203u , 4278597203u , 4278597203u , 4278597203u , 4278597203u , 4278597203u , 4278597203u , 4278597203u , 4278597203u , 4278597203u , 4278597203u , 4278992474u , 4284129202u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 3211638728u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 1886238664u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4282812316u , 4278597203u , 4278597203u , 4278597203u , 4278597203u , 4278597203u , 4278597203u , 4281687155u , 4291877343u , 4294967295u , 4294967295u , 4294967295u , 4294967295u , 4294967295u , 4294967295u , 4294967295u , 4294967295u , 4294967295u , 4294967295u , 4294967295u , 4294967295u , 4294967295u , 4294967295u , 4294967295u , 4294967295u , 4294967295u , 4294967295u , 4294967295u , 4294967295u , 4294967295u , 4294967295u , 4294967295u , 4294967295u , 4294967295u , 4294967295u , 4294967295u , 4294967295u , 4294967295u , 4294967295u , 4291877343u , 4280635241u , 4278597203u , 4278597203u , 4278597203u , 4278597203u , 4278597203u , 4278597203u , 4278597203u , 4281165439u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4282021774u , 4278597203u , 4278597203u , 4278597203u , 4278597203u , 4278597203u , 4278597203u , 4278597203u , 4278597203u , 4278597203u , 4278597203u , 4278597203u , 4278597203u , 4278597203u , 4278597203u , 4278597203u , 4278597203u , 4278597203u , 4278597203u , 4278597203u , 4278597203u , 4278597203u , 4278597203u , 4278597203u , 4278597203u , 4278597203u , 4278597203u , 4278597203u , 4278597203u , 4278992474u , 4284129202u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 3211638728u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 1080932296u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4282812316u , 4278597203u , 4278597203u , 4278597203u , 4278597203u , 4278597203u , 4278597203u , 4278597203u , 4286815145u , 4294967295u , 4294967295u , 4294967295u , 4294967295u , 4294967295u , 4294967295u , 4294967295u , 4294967295u , 4294967295u , 4294967295u , 4294967295u , 4294967295u , 4294967295u , 4294967295u , 4294967295u , 4294967295u , 4294967295u , 4294967295u , 4294967295u , 4294967295u , 4294967295u , 4294967295u , 4294967295u , 4294967295u , 4294967295u , 4294967295u , 4294967295u , 4294967295u , 4286815145u , 4278597203u , 4278597203u , 4278597203u , 4278597203u , 4278597203u , 4278597203u , 4278597203u , 4278597203u , 4281165439u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4280309360u , 4278597203u , 4278597203u , 4278597203u , 4278597203u , 4278597203u , 4278597203u , 4278597203u , 4278597203u , 4278597203u , 4278597203u , 4278597203u , 4278597203u , 4278597203u , 4278597203u , 4278597203u , 4278597203u , 4278597203u , 4278597203u , 4278597203u , 4278597203u , 4278597203u , 4278597203u , 4278597203u , 4278597203u , 4278597203u , 4278597203u , 4278992474u , 4284129202u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 2406332360u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4282812316u , 4278992474u , 4278597203u , 4278597203u , 4278597203u , 4278597203u , 4278597203u , 4278597203u , 4281687155u , 4290891220u , 4294967295u , 4294967295u , 4294967295u , 4294967295u , 4294967295u , 4294967295u , 4294967295u , 4294967295u , 4294967295u , 4294967295u , 4294967295u , 4294967295u , 4294967295u , 4294967295u , 4294967295u , 4294967295u , 4294967295u , 4294967295u , 4294967295u , 4294967295u , 4294967295u , 4294967295u , 4294967295u , 4294967295u , 4290891220u , 4280635241u , 4278597203u , 4278597203u , 4278597203u , 4278597203u , 4278597203u , 4278597203u , 4278597203u , 4278597203u , 4282417045u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4282812316u , 4279453282u , 4278597203u , 4278597203u , 4278597203u , 4278597203u , 4278597203u , 4278597203u , 4278597203u , 4278597203u , 4278597203u , 4278597203u , 4278597203u , 4278597203u , 4278597203u , 4278597203u , 4278597203u , 4278597203u , 4278597203u , 4278597203u , 4278597203u , 4278597203u , 4278597203u , 4278597203u , 4278597203u , 4278597203u , 4283668395u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 2154674120u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 3480074184u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4284129202u , 4279453282u , 4278597203u , 4278597203u , 4278597203u , 4278597203u , 4278597203u , 4278597203u , 4278597203u , 4282673278u , 4289839305u , 4294967295u , 4294967295u , 4294967295u , 4294967295u , 4294967295u , 4294967295u , 4294967295u , 4294967295u , 4294967295u , 4294967295u , 4294967295u , 4294967295u , 4294967295u , 4294967295u , 4294967295u , 4294967295u , 4294967295u , 4294967295u , 4294967295u , 4294967295u , 4288853183u , 4282673278u , 4278597203u , 4278597203u , 4278597203u , 4278597203u , 4278597203u , 4278597203u , 4278597203u , 4278597203u , 4278992474u , 4283273123u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4284129202u , 4281165439u , 4278992474u , 4278597203u , 4278597203u , 4278597203u , 4278597203u , 4278597203u , 4278597203u , 4278597203u , 4278597203u , 4278597203u , 4278597203u , 4278597203u , 4278597203u , 4278597203u , 4278597203u , 4278597203u , 4278597203u , 4278597203u , 4278597203u , 4278597203u , 4278597203u , 4282812316u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 2154674120u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 2406332360u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4284985281u , 4280704632u , 4278597203u , 4278597203u , 4278597203u , 4278597203u , 4278597203u , 4278597203u , 4278597203u , 4278597203u , 4280635241u , 4285763230u , 4290891220u , 4294967295u , 4294967295u , 4294967295u , 4294967295u , 4294967295u , 4294967295u , 4294967295u , 4294967295u , 4294967295u , 4294967295u , 4294967295u , 4294967295u , 4294967295u , 4294967295u , 4290891220u , 4285763230u , 4279649118u , 4278597203u , 4278597203u , 4278597203u , 4278597203u , 4278597203u , 4278597203u , 4278597203u , 4278597203u , 4278597203u , 4280309360u , 4284524473u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4283273123u , 4281165439u , 4278992474u , 4278597203u , 4278597203u , 4278597203u , 4278597203u , 4278597203u , 4278597203u , 4278597203u , 4278597203u , 4278597203u , 4278597203u , 4278597203u , 4278597203u , 4278597203u , 4278597203u , 4278597203u , 4278597203u , 4282812316u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 2154674120u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 1617803208u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4283273123u , 4279453282u , 4278597203u , 4278597203u , 4278597203u , 4278597203u , 4278597203u , 4278597203u , 4278597203u , 4278597203u , 4278597203u , 4278597203u , 4282673278u , 4285763230u , 4287801268u , 4290891220u , 4290891220u , 4290891220u , 4290891220u , 4290891220u , 4290891220u , 4286815145u , 4285763230u , 4282673278u , 4278597203u , 4278597203u , 4278597203u , 4278597203u , 4278597203u , 4278597203u , 4278597203u , 4278597203u , 4278597203u , 4278597203u , 4278597203u , 4278992474u , 4282417045u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4284129202u , 4281560710u , 4279453282u , 4278597203u , 4278597203u , 4278597203u , 4278597203u , 4278597203u , 4278597203u , 4278597203u , 4278597203u , 4278597203u , 4278597203u , 4278597203u , 4278597203u , 4282812316u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 4285380552u , 2154674120u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u , 0u }; FreeRDP-1.0.2/resources/FreeRDP_Icon_256px.png000066400000000000000000000146721207112532300206320ustar00rootroot00000000000000PNG  IHDR\rfIDATx yǏFEK I'iN550N5ID3aI6,6Fk5ˤ16)[ڴ2-$Ȋrj5F1 =w_={w˞9ysqG]>t<^ ?5xF~ 3+Mq@cȏkXBM~%Et~(XWePJk!z K\ x̨tӯ1(zUHJ`&šg|?$`(G Qd'P";?FM<p`eBxu~!P3R ,Bv~x!-Ƕ/ƶwn`1v~V t#(K^)A@Xŝ0eXGd_dDEXAXv0ݎ 3(K7ABX=YC(қN=0Xo4ݎ p)! J/ "<.0jD?m7@<}*Dv~L# yPwKpP0~I'.D PXЯjM7 P20@8T S@c~Ͱ?(p`$xO@P%0f^a/ (8odPvnӍ Ah|#RAЄ#z`PpοN(xopw_ YY_B_ )FxPH i`/P(<+ ȉgSP9l NCdéȈSsȀG?Ͱ?p(0A KpÐDŽ,`~`%@MCࠏXbIPO UA (=%8V̤)>A*i]Œ-SMT=$(?;/D`Nxc(~9Y#XG0C^6}cY! +XBK@E f!F "XӃ' Qf!?I PD,d1^u("dm"Ve Tr"4 nU_y!XBZA Ap]PL 0]iA-ip>t ,Ap]n+ jAkp]޴2q Z`/':32l 5t @:p`. Gpnt @q,\hX7 >)ߓqY/4@@( xa\amp2zo&! Wt ҂ @*i⾟jRM/Hv/ʬP4pZ z)} 7U(d @So8w/& \mRR`P΍ǓN>U)*Ax1N YA)^,SN'M٘xDM.ɏO#Q( W5xY'MtT% HKn)r%!':BpO`t#B x| 0CP%S 9o23]>3ݎL2Yv)#IC$NaF ͘u|NsQcYg̚MI!j" HM5Q| 1 nP Wz1v_ v|#2HX. G>3Ʒ$~QYtp6 Osyvk4A4?7N:~F؍\h`Ƭbiԟ8:?$0b!BM:Ng@},R#x`Qyz)+t9ڸ *I@AϜmApty}20n;Á@`?Xxp av ;V X1ϭ hw`' &;? 5[F$ Ę8/v~O $g"|)F/m\tH L7. Sv`'28%% Ytڧݻ c~犤b)g +,<MgfDώ3 B]xzNIxSQd.sSELw-嬠Z?|W`Reo">)SpoD6>f7P,\j)3(m:1%ׅ?txt|e?n:\.o>MbԏL7Wp7ۃM/yO!q[m˯5f -xsdxepD9p_hgY;/_ȥ«7\S/k% Jg B>yeQ7o<$?DK>>xR0@i9Λ9H*;~\l(d<@ R^l R֧;>:G_'lO8n(x鍫2KޫE[2`%Xɋpe2:?~~(ʿ}g'L|?(G`)@ #,o2kw3ŞInޱW\zW)(`}?_5\ҧwĭw=}^M2.5H+VKnDQՇduGtrbBoH ~#o f0P/2U DAo?/|]C\.?~'[ ,Ql'I9$߂>L"P\bO:]AW @|-S \S PË@|*}{k~uuqcH?`:>@?g1uz^%,ˀB8 BVTNΤNrsؐtǵ>O`eQAV}9Qud]Y҂$q-*8s2`@SU`ҁe@hnURtH$IG>/e .:{G@ r!2 q#:KW_~%:ܳeo_9f ǥC>-YV-;r*I m1L|>(V~QO"V:9oOy7`SXiNƿ-\p c #60A7B9", ", c #245C76", "' c #205670", ") c #174C67", "! c #063653", "~ c #407F95", "{ c #0C3E5A", "] c #0A3B58", "^ c #4D8FA3", "/ c #67AFC1", "( c #2D667F", "_ c #5397AB", ": c #134662", "< c #3D7D94", "[ c #3A778E", "} c #39778F", "| c #5A9FB2", "1 c #265E78", "2 c #46879C", "3 c #205771", "4 c #316C85", "5 c #46889E", "6 c #194E69", "7 c #4C90A5", "8 c #60A7BA", "9 c #69B2C3", "0 c #62AABC", "a c #336E86", "b c #4E92A8", "c c #599FB3", "d c #6BB4C6", "e c #579DB1", "f c #346F87", "g c #44687E", "h c #638194", "i c #839BA9", "j c #547589", "k c #16435E", "l c #A2B4BF", "m c #E0E6EA", "n c #FFFFFF", "o c #B1C0C9", "p c #FFFEF9", "q c #FEFDF2", "r c #FEFCED", "s c #FEFCEC", "t c #DFE4DB", "u c #63808C", "v c #355C73", "w c #C1CDD4", "x c #FEFDF3", "y c #D0D7CF", "z c #254F67", "A c #738E9E", "B c #FFFEF7", "C c #EFF0E6", "D c #FEFCEE", "E c #D0D9DF", "F c #547486", "G c #446879", "H c #D0D7D1", "I c #254F66", "J c #C0CBC6", "K c #92A5A9", "L c #EFF2F4", "M c #547483", "N c #8299A0", "O c #254F69", "P c #92A7B4", "Q c #738D96", "R c #16425D", "S c #DFE3D9", "T c #EFF0E2", "U c #355B70", "V c #B1BEBC", "W c #A1B2B3", " ....... ", " ............. ", " ................. ", " .................... ", " ...................... ", " ........................ ", " .......................... ", " ........................... ", " ............................ ", " ............................. ", " ............................... ", " ................................ ", " ................................. ", " .................................. ", " ................................... ", " .................................... ", " ..................................... ", " ..................................... ", " ...................................... ", " ....................................... ", " ........................................ ", " ........................................ ", " ......................................... ", " .......................................... ", " ......................................... ", " .......................................... ", " .......................................... ", " ........................................... ", " ............................................ ", " ............................................ ", " ............................................ ", " ............................................ ", " ............................................. ", " .............................................. ", " .............................................. ", " .............................................. ", " .............................................. ", " ............................................... ", " ............................................... ", " ............................................... ", " ................................................ ", " ................................................ ", " ................................................. ", " ................................................. ", " ................................................. ", " .................................................. ", " .................................................. ", " ................................................... ", " ................................................... ", " ................................................... ", " .................................................... ", " ..................................................... ", " .................................................... ", " ..................................................... ", " ...................................................... ", " ...................................................... ", " ....................................................... ", " ....................................................... ", " ....................................................... ", " ........................................................ ", " ......................................................... ", " ......................................................... ", " ......................................................... ", " ......................................................... ", " .......................................................... ", " ...........................................................++++ ", " ..........................................................@+++++ ", " ...........................................................#++++++ ", " ...........................................................$+++++++ ", " ............................................................%++++++++ ", " .............................................................&++++++++ ", " .............................................................*+++++++++ ", " ..............................................................++++++++++ ", " ..............................................................+++++++++++ ", " ..............................................................=+++++++++++ ", " ..............................................................@++++++++++++ ", " ...............................................................#+++++++++++++ ", " ...............................................................-+++++++++++++ ", " ................................................................;>+++++++++++++ ", " ................................................................,'+++++++++++++ ", " .................................................................)!~+++++++++++++ ", " .................................................................)!{>++++++++++++ ", " ..................................................................)!!'+++++++++++++ ", " ..................................................................]!!!^+++++++++++++ ", " ...................................................................!!!!{/++++++++++++ ", " ...................................................................!!!!!(+++++++++++++ ", " ....................................................................!!!!!!_+++++++++++++ ", " ....................................................................!!!!!!:/++++++++++++ ", " ....................................................................++++++++++++ ", " ........................................................................}!!!!!!!!!!!!!'+++++++++++++ ", " .........................................................................}!!!!!!!!!!!!!!_+++++++++++++ ", " .........................................................................}!!!!!!!!!!!!!!:+++++++++++++ ", " .........................................................................}!!!!!!!!!!!!!!![+++++++++++++ ", " ..........................................................................}!!!!!!!!!!!!!!!{/++++++++++++ ", " ..........................................................................}!!!!!!!!!!!!!!!!(+++++++++++++ ", " ..........................................................................}!!!!!!!!!!!!!!!!!>+++++++++++++ ", " ...........................................................................}!!!!!!!!!!!!!!!!!'+++++++++++++ ", " ...........................................................................}!!!!!!!!!!!!!!!!!!_+++++++++++++ ", " ...........................................................................}!!!!!!!!!!!!!!!!!!'+++++++++++++ ", " ...........................................................................+++++++++++++ ", " .............................................................................!!!!!!!!!!!!!!!!!!!![++++++++++++++ ", " .............................................................................!!!!!!!!!!!!!!!!!!!!:++++++++++++++ ", " ..............................................................................]!!!!!!!!!!!!!!!!!!!!^+++++++++++++ ", " ..............................................................................)!!!!!!!!!!!!!!!!!!!!1++++++++++++++ ", " ..............................................................................)!!!!!!!!!!!!!!!!!!!!!/+++++++++++++ ", " ..............................................................................)!!!!!!!!!!!!!!!!!!!!!2++++++++++++++ ", " ..............................................................................3!!!!!!!!!!!!!!!!!!!!!1++++++++++++++ ", " ...............................................................................;!!!!!!!!!!!!!!!!!!!!!!/+++++++++++++ ", " ...............................................................................;!!!!!!!!!!!!!!!!!!!!!!2++++++++++++++ ", " ...............................................................................4!!!!!!!!!!!!!!!!!!!!!!(++++++++++++++ ", " ...............................................................................}!!!!!!!!!!!!!!!!!!!!!!{++++++++++++++ ", " ...............................................................................}!!!!!!!!!!!!!!!!!!!!!!!|+++++++++++++ ", " ...............................................................................5!!!!!!!!!!!!!!!!!!!!!!!~+++++++++++++ ", " .................................................................................!!!!!!!!!!!!!!!!!!!!!!!(++++++++++++++ ", " .................................................................................]!!!!!!!!!!!!!!!!!!!!!!6++++++++++++++ ", " .................................................................................)!!!!!!!!!!!!!!!!!!!!!!!++++++++++++++ ", " .................................................................................)!!!!!!!!!!!!!!!!!!!!!!!|+++++++++++++ ", " .................................................................................;!!!!!!!!!!!!!!!!!!!!!!!_+++++++++++++ ", " .................................................................................;!!!!!!!!!!!!!!!!!!!!!!![+++++++++++++ ", " .................................................................................}!!!!!!!!!!!!!!!!!!!!!!![+++++++++++++ ", " .................................................................................}!!!!!!!!!!!!!!!!!!!!!!![+++++++++++++ ", " ..................................................................................!!!!!!!!!!!!!!!!!!!!!!!'+++++++++++++ ", " ...................................................................................]!!!!!!!!!!!!!!!!!!!!!!'+++++++++++++ ", " ...................................................................................)!!!!!!!!!!!!!!!!!!!!!!'+++++++++++++ ", " ...................................................................................3!!!!!!!!!!!!!!!!!!!!!!'+++++++++++++ ", " .....................................................................7@#$$8&&&&9++++>____~[[''!!!!!!!!!!!!(+++++++++++++ ", " ...............................................................=#$0*+++++++++++++++++++++++++++/_~a'!!!!!![+++++++++++++ ", " ..........................................................7#%&+++++++++++++++++++++++++++++++++++++++|~1{![+++++++++++++ ", " ......................................................7#%9+++++++++++++++++++++++++++++++++++++++++++++++|>++++++++++++ ", " ...................................................bc&+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ ", " ................................................=%9++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ ", " .............................................bc*+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ ", " ...........................................#0+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ ", " ........................................7$9++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ ", " ......................................b8+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ ", " ....................................@&+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ ", " ..................................@&+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ ", " ................................@&++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ ", " ..............................b8++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ ", " .............................7$+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ ", " ............................#9++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ ", " ..........................b&+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ ", " .........................$d+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ ", " .......................=*++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ ", " ......................cd++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ ", " ....................7&++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ ", " ...................@d++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ ", " ..................$+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ ", " ................70+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ ", " ...............=*+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ ", " ..............@d++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ ", " .............e+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ ", " ............$+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ ", " ...........8+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ ", " ..........8+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ ", " .........8++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ ", " ........8++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ ", " .......8++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ ", " ......8++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ ", " .....8+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ ", " ....e+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ ", " ...e+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ ", " ..=d+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ ", " 7d+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ ", " *++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ ", " +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ ", " +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ ", " +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ ", " ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ ", " ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ ", " ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ ", " ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ ", " +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ ", " ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ ", " ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++/[a''''''''[~ ", " ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++1!!!!!!!!!!!!! ", " +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++'!!!!!!!!!!!!!! ", " ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++'!!!!!!!!!!!!!! ", " ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++'!!!!!!!!!!!!!!! ", " +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++(!!!!!!!!!!!!!!! ", " +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++2!!!!!!!!!!!!!!! ", " +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++{!!!!!!!!!!!!!!! ", " +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++^!!!!!!!!!!!!!!! ", " +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++/_2[[[[[[[2_/+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++[!!!!!!!!!!!!!! ", " +++++++++++++++++++++++++++++++++++++++++++++++++++++++/2(:!!!!!!!!!!!!!{1~>++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++>(:!!!!!!!!!{f ", " ++++++++++++++++++++++++++++++++++++++++++++++++++++/2'!!!!!!!!!!!!!!!!!!!!!6~/++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++/_^[[[[_|++ ", " +++++++++++++++++++++++++++++++++++++++++++++++++++>[{!!!!!!!!!!!!!!!!!!!!!!!!!!(>+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ ", " +++++++++++++++++++++++++++++++++++++++++++++++++/[{!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!(>+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ ", " +++++++++++++++++++++++++++++++++++++++++++++++++^{!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!{[+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ ", " +++++++++++++++++++++++++++++++++++++++++++++++/1!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!6>+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ ", " ++++++++++++++++++++++++++++++++++++++++++++++|{!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!{^++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ ", " ++++++++++++++++++++++++++++++++++++++++++++++2!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!![+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ ", " +++++++++++++++++++++++++++++++++++++++++++++2!!!!!!!!!!!!!!!!!!gghiijgg!!!!!!!!!!!!!!!!!!!(+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ ", " ++++++++++++++++++++++++++++++++++++++++++++2!!!!!!!!!!!!!!khlmnnnnnnnnnnmlhk!!!!!!!!!!!!!!!(++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ ", " ++++++++++++++++++++++++++++++++++++++++++++2!!!!!!!!!!!!!jonnnnnnnnnnnnnnnnnnog!!!!!!!!!!!!!!a+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ ", " +++++++++++++++++++++++++++++++++++++++++++_!!!!!!!!!!!!hmnnnnnnnnnnnnnnnnnnpqrstu!!!!!!!!!!!!!2++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ ", " ++++++++++++++++++++++++++++++++++++++++++/{!!!!!!!!!!vwnnnnnnnnnnnnnnnnnnnxssssssyz!!!!!!!!!!!!|+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ ", " ++++++++++++++++++++++++++++++++++++++++++'!!!!!!!!!!AnnnnnnnnnnnnnnnnnnnnBssssssssCA!!!!!!!!!!!:/+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ ", " ++++++++++++++++++++++++++++++++++++++++++~!!!!!!!!!konnnnnnnnnnnnnnnnnnnnnDsssssssssplk!!!!!!!!!!a+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ ", " +++++++++++++++++++++++++++++++++++++++++>{!!!!!!!!kEnnnnnnnnnnnnnnnnnnnnlFssssssssssxnEk!!!!!!!!!!_++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ ", " +++++++++++++++++++++++++++++++++++++++++(!!!!!!!!kEnnnnnnnnnnnnnnnnnnnmg!GssssssssssHlnEk!!!!!!!!!6++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ ", " ++++++++++++++++++++++++++++++++++++++++>!!!!!!!!kEnnnnnnnnnnnnnnnnnnnEk!!IssssssssssJ!hnEk!!!!!!!!!2+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ ", " +++++++++++++++++++++++++++++++++++++++++(!!!!!!!!onnnnnnnnnnnnnnnnnnnEk!!!!ysssssssssK!!hnl!!!!!!!!!:++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ ", " ++++++++++++++++++++++++++++++++++++++++>!!!!!!!!AnnnnnnnnnnnnnnnnnnnLk!!!!!MsssssssssI!!!lnA!!!!!!!!!_+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ ", " ++++++++++++++++++++++++++++++++++++++++[!!!!!!!vnnnnnnnnnnnnnnnnnnnnh!!!!!!!Nsssssssu!!!!kLLO!!!!!!!!1+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ ", " ++++++++++++++++++++++++++++++++++++++++:!!!!!!!wnnnnnnnnnnnnnnnnnnnm!!!!!!!!!MysssJG!!!!!!Anw!!!!!!!!!/++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ ", " +++++++++++++++++++++++++++++++++++++++|!!!!!!!jnnnnnnnnnnnnnnnnnnnnA!!!!!!!!!!!!G!!!!!!!!!knng!!!!!!!!2++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ ", " ++++++++++++++++++++++++++++++++++++++++[!!!!!!!EnnnnnnnnnnnnnnnnnnnnO!!!!!!!!!!!!!!!!!!!!!!!wnw!!!!!!!!1++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ ", " ++++++++++++++++++++++++++++++++++++++++'!!!!!!gnnnnnnnnnnnnnnnnnnnnL!!!!!!!!!!!!!!!!!!!!!!!!inng!!!!!!!{++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ ", " ++++++++++++++++++++++++++++++++++++++++!!!!!!!lnnnnnnnnnnnnnnnnnnnnw!!!!!!!!!!!!!!!!!!!!!!!!hnnl!!!!!!!!|++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ ", " +++++++++++++++++++++++++++++++++++++++_!!!!!!knnnnnnnnnnnnnnnnnnnnnw!!!!!!!!!!!!!!!!!!!!!!!!gnnL!!!!!!!!2++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ ", " +++++++++++++++++++++++++++++++++++++++2!!!!!!jnnnnnnnnnnnnnnnnnnnnnw!!!!!!!!!!!!!!!!!!!!!!!!jnnnj!!!!!!![++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ ", " +++++++++++++++++++++++++++++++++++++++[!!!!!!PnnnnnnnnnnnnnnnnnnnnnE!!!!!!!!!!!!!!!!!!!!!!!!innnP!!!!!!!'++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ ", " +++++++++++++++++++++++++++++++++++++++a!!!!!!Ennnnnnnnnnnnnnnnnnnnnnk!!!!!!!!!!!!!!!!!!!!!!!lnnnw!!!!!!!'++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ ", " +++++++++++++++++++++++++++++++++++++++'!!!!!!nnnnnnnnnnnnnnnnnnnnnnnj!!!!!!!!!!!!!!!!!!!!!!!mnnnn!!!!!!!'++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ ", " +++++++++++++++++++++++++++++++++++++++'!!!!!Onnnnnnnnnnnnnnnnnnnnnnnl!!!!!!!!!!!!!!!!!!!!!!gnnnnn!!!!!!!{++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ ", " +++++++++++++++++++++++++++++++++++++++'!!!!!gnnnnnnnnnnnnnnnnnnnnnnnnO!!!!!!!!!!!!!!!!!!!!!wnnnnng!!!!!!!++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ ", " +++++++++++++++++++++++++++++++++++++++'!!!!!gnnnnnnnnnnnnnnnnnnnnnnnnw!!!!!!!!!!!!!!!!!!!!jnnnnnng!!!!!!{+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ ", " +++++++++++++++++++++++++++++++++++++++'!!!!!gnnnnnnnnnnnnnnnnnnnnnnnnnA!!!!!!!!!!!!!!!!!!OLnnnnnng!!!!!!'+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ ", " +++++++++++++++++++++++++++++++++++++++a!!!!!gnnnnnnnnnnnnnnnnnnnnnnnnnnh!!!!!!!!!!!!!!!!kEnnnnnnng!!!!!!'+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ ", " +++++++++++++++++++++++++++++++++++++++[!!!!!gnnnnnnnnnnnnnnnnnnnnnnnnnnni!!!!!!!!!!!!!!vLnnnnnnnng!!!!!!1+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ ", " +++++++++++++++++++++++++++++++++++++++2!!!!!gnnnnnnnnnnnnnnnnnnnnnnnnnnnnEg!!!!!!!!!!kPnnnnnnnnnnO!!!!!![+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ ", " +++++++++++++++++++++++++++++++++++++++_!!!!!!nnnnnnnnnnnnnnnnnnnnnnnnnnnnnnEAv!!!!Ojlnnnnnnnnnnnn!!!!!!!2+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ ", " ++++++++++++++++++++++++++++++++++++++++!!!!!!mnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnE!!!!!!!|+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ ", " ++++++++++++++++++++++++++++++++++++++++'!!!!!onnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnl!!!!!!{++++++++++++++++++++++++++++++++++++++++++++++++++++__[[[[[[[[[~__++++++++++++++ ", " ++++++++++++++++++++++++++++++++++++++++[!!!!!Annnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnh!!!!!!1+++++++++++++++++++++++++++++++++++++++++++++++>2(6!!!!IGNNNNQG!!!!:(/++++++++++ ", " ++++++++++++++++++++++++++++++++++++++++|!!!!!OnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnO!!!!!!2++++++++++++++++++++++++++++++++++++++++++++/~6!!!!!RNSssssssssTKR!!!6++++++++++ ", " +++++++++++++++++++++++++++++++++++++++++:!!!!!EnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnE!!!!!!!/++++++++++++++++++++++++++++++++++++++++++>(!!!!!!!UTssssssssssssV!!!!^+++++++++ ", " +++++++++++++++++++++++++++++++++++++++++[!!!!!Annnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnh!!!!!!(+++++++++++++++++++++++++++++++++++++++++>(!!!!!!!!!SsssssssssssssJ!!!![+++++++++ ", " +++++++++++++++++++++++++++++++++++++++++>!!!!!kLnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnL!!!!!!!_++++++++++++++++++++++++++++++++++++++++[{!!!!!!!!!!SssssssssssssTM!!!!2++++++++++ ", " ++++++++++++++++++++++++++++++++++++++++++(!!!!!innnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnni!!!!!!6+++++++++++++++++++++++++++++++++++++++>'!!!!!!!!!!!!UysssssssssTWI!!!!!>++++++++++ ", " ++++++++++++++++++++++++++++++++++++++++++>!!!!!kLnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnmk!!!!!!2++++++++++++++++++++++++++++++++++++++|{!!!!!!!!!!!!!!!UQKJJJKNG!!!!!!!6+++++++++++ ", " +++++++++++++++++++++++++++++++++++++++++++(!!!!!hnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnj!!!!!!'++++++++++++++++++++++++++++++++++++++2{!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!2+++++++++++ ", " +++++++++++++++++++++++++++++++++++++++++++/{!!!!!wnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnno!!!!!!!_+++++++++++++++++++++++++++++++++++++|!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!(++++++++++++ ", " +++++++++++++++++++++++++++++++++++++++++++~!!!!!kLnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnmk!!!!!!a+++++++++++++++++++++++++++++++++++++>{!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!6/++++++++++++ ", " ++++++++++++++++++++++++++++++++++++++++++++'!!!!!vLnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnLv!!!!!!:/+++++++++++++++++++++++++++++++++++++a!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!6/+++++++++++++ ", " ++++++++++++++++++++++++++++++++++++++++++++/{!!!!!hnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnj!!!!!!!|++++++++++++++++++++++++++++++++++++++'!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!6/++++++++++++++ ", " +++++++++++++++++++++++++++++++++++++++++++++|!!!!!!hnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnh!!!!!!!2+++++++++++++++++++++++++++++++++++++++'!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!:/+++++++++++++++ ", " ++++++++++++++++++++++++++++++++++++++++++++++2!!!!!!gLnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnLv!!!!!!!a++++++++++++++++++++++++++++++++++++++++'!!!!!!!!!!!!!!!!!!!!!!!!!!!!!{|++++++++++++++++ ", " ++++++++++++++++++++++++++++++++++++++++++++++2!!!!!!vEnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnEO!!!!!!!(+++++++++++++++++++++++++++++++++++++++++[!!!!!!!!!!!!!!!!!!!!!!!!!!!!{|+++++++++++++++++ ", " +++++++++++++++++++++++++++++++++++++++++++++++2!!!!!!!innnnnnnnnnnnnnnnnnnnnnnnnnnni!!!!!!!!(+++++++++++++++++++++++++++++++++++++++++++'!!!!!!!!!!!!!!!!!!!!!!!!!!{|++++++++++++++++++ ", " ++++++++++++++++++++++++++++++++++++++++++++++++2{!!!!!!vwnnnnnnnnnnnnnnnnnnnnnnnnwO!!!!!!!!~+++++++++++++++++++++++++++++++++++++++++++++2:!!!!!!!!!!!!!!!!!!!!!!!!_+++++++++++++++++++ ", " +++++++++++++++++++++++++++++++++++++++++++++++++|:!!!!!!!gonnnnnnnnnnnnnnnnnnnnlg!!!!!!!!{^++++++++++++++++++++++++++++++++++++++++++++++++|({!!!!!!!!!!!!!!!!!!!!2++++++++++++++++++++ ", " ++++++++++++++++++++++++++++++++++++++++++++++++++/1!!!!!!!!OAwnnnnnnnnnnnnnnwAk!!!!!!!!!'>++++++++++++++++++++++++++++++++++++++++++++++++++++^({!!!!!!!!!!!!!!!!2+++++++++++++++++++++ ", " +++++++++++++++++++++++++++++++++++++++++++++++++++^:!!!!!!!!!!gAPwwwwwwiAg!!!!!!!!!!!{~+++++++++++++++++++++++++++++++++++++++++++++++++++++++++|a:!!!!!!!!!!!!2++++++++++++++++++++++ "}; FreeRDP-1.0.2/resources/FreeRDP_Logo_Icon.ai000066400000000000000000041121471207112532300204530ustar00rootroot00000000000000%PDF-1.5 % 1 0 obj <>/OCGs[5 0 R]>>/Pages 3 0 R/Type/Catalog>> endobj 2 0 obj <>stream application/pdf FreeRDP_Logo_Icon 2011-08-01T20:34:57+02:00 2011-08-01T20:34:57+02:00 2011-08-01T20:34:57+02:00 Adobe Illustrator CS5.1 256 204 JPEG /9j/4AAQSkZJRgABAgEASABIAAD/7QAsUGhvdG9zaG9wIDMuMAA4QklNA+0AAAAAABAASAAAAAEA AQBIAAAAAQAB/+4ADkFkb2JlAGTAAAAAAf/bAIQABgQEBAUEBgUFBgkGBQYJCwgGBggLDAoKCwoK DBAMDAwMDAwQDA4PEA8ODBMTFBQTExwbGxscHx8fHx8fHx8fHwEHBwcNDA0YEBAYGhURFRofHx8f Hx8fHx8fHx8fHx8fHx8fHx8fHx8fHx8fHx8fHx8fHx8fHx8fHx8fHx8fHx8f/8AAEQgAzAEAAwER AAIRAQMRAf/EAaIAAAAHAQEBAQEAAAAAAAAAAAQFAwIGAQAHCAkKCwEAAgIDAQEBAQEAAAAAAAAA AQACAwQFBgcICQoLEAACAQMDAgQCBgcDBAIGAnMBAgMRBAAFIRIxQVEGE2EicYEUMpGhBxWxQiPB UtHhMxZi8CRygvElQzRTkqKyY3PCNUQnk6OzNhdUZHTD0uIIJoMJChgZhJRFRqS0VtNVKBry4/PE 1OT0ZXWFlaW1xdXl9WZ2hpamtsbW5vY3R1dnd4eXp7fH1+f3OEhYaHiImKi4yNjo+Ck5SVlpeYmZ qbnJ2en5KjpKWmp6ipqqusra6voRAAICAQIDBQUEBQYECAMDbQEAAhEDBCESMUEFURNhIgZxgZEy obHwFMHR4SNCFVJicvEzJDRDghaSUyWiY7LCB3PSNeJEgxdUkwgJChgZJjZFGidkdFU38qOzwygp 0+PzhJSktMTU5PRldYWVpbXF1eX1RlZmdoaWprbG1ub2R1dnd4eXp7fH1+f3OEhYaHiImKi4yNjo +DlJWWl5iZmpucnZ6fkqOkpaanqKmqq6ytrq+v/aAAwDAQACEQMRAD8A9U4q7FVskkccbSSMEjQF ndiAAAKkknoBirxbz7+aN5qM8mn6JK1tpyEo9yhKyT9qgjdU9up7+GZ+HTgbnm6fU6wyNR5IT8nh dv5yVomb0lgla6oTQpSg5f7NlyWprgY6C/E+D3bNc7p2KuxV2KuxV2KuxV2KuxV2KuxV2KuxV2Ku xV2KuxV2KuxV2KuxV2KuxV2KuxV2KuxV2KuxV5J+bnnhnkfy5p0lI0/46Mqn7TdRCCOw/a+7xzN0 2L+Iur12p/gHxeV5mOre1fktoa22hz6vIv76/cpEfCKIkbfN+VfkMwNVOzXc7ns/HUOLvei5iue7 FXYq7FXYq7FXYq7FXYq7FXYq7FXYq7FXYq7FXYq7FXYq7FXYq7FXYq7FXYq7FXYq7FWOeffNK+Xd AluUI+vT/ubJTv8AvCPtkeCDf7h3y3Dj4pOPqc3hwvq+dZJHkkaSRi8jks7sakkmpJJzaOgJtbih 9Efl1f2E/leztbaqyWUSR3EbUB5sORYU/ZZq0zWZ4kSs9Xe6PLGUAB0ZPlLluxV2KuxV2KuxV2Ku xV2KuxV2KuxV2KuxV2KuxV2KuxV2KuxV2KuxV2KuxV2KuxV2KuxV8/8A5n+YzrPmeaONq2en1t4A OhZT+8f/AGTbfIDNlp4cMfe6LW5eOddAxDL3Ediqefkh+Y7MVE7kzWlIbtO8ludkkp/Mvf3HvlWb HxCnJxZPCnxdDzfSUciSIsiMGRwGVhuCDuCM1bvgbbxS7FXYq7FXYq7FXYq7FXYq7FXYq7FXYq7F XYq7FXYq7FXYq7FXYq7FXYq7FXYq7FUv8w6gdO0LUL4Gj29vLIh/ywh4j/gqZKAsgMMkuGJPcHzC SSSSak7knNu801irsVeX+V9ZfQvM1vdAlIVl9K5XxhZuLg/Lr8xi5EhYfZ35b6xJc6fLp8pq1mQY ievpvXb/AGJH45gamFG+9z+zs3FExPRmOYrsXYq7FXYq7FXYq7FXYq7FXYq7FXYq7FXYq7FXYq7F XYq8+86fmxZaU72Ojql5frtJMTWGM+G322+W36sycWnMtzycHUa0Q2juXl955784Xcxlk1e5Ria8 YZDCo/2MfEZmDDAdHWS1OQ9S9O/KPzfqesQ3lhqcpuJ7QJJDO32yjEhlY9+JAoffMTU4hHcOy0Oe UwRLo9DzFc92KuxV2KuxVi/5nSmLyLqrDusS7f5cyL/HLsA9YcbVmsRfPGbN0CMttKvbgBlTih/b fYf1xRaOTy4afHPQ+CrX8ScbRxMN1L8mjNNNPa6mFaR2cRSQ/CORrTkrdv8AVxttGZ7v+VJS2u2i uZ0E/wBWSIAkD1HBFeNaV+zmJqgeEOX2dIcZ3eoZgu6dirsVdirsVdirsVdirsVdirsVdirsVdir sVdirsVeT/mZ+ZL85ND0Saiiq3t7GdyehijI/wCGYfLM3Bg6l1ms1f8ADH4vKMzHVOxV67+RmnMt rqmosPhkeO3jP+oC7/8AE1zC1ctwHbdnQ2JepZhuydirsVdirsVYr+aSs3kTU1UEsTAAB1J+sx5d p/rDi63+6Pw+945p2jxwqJJwHm68TuF/tzZPPkplixdirsVbBIIINCOhxV6N5G83SXhGl6g/K5Uf 6POx3kA6q3+UB375g58Nbh3Wh1Zl6Jc2aZiuydirsVdirsVdirsVdirsVdirsVdirsVdirsVed/m n59OlwNoumyU1Gdf9JmU7wxsOgPZ2H3D6MytPhvc8nA1mp4Rwjm8VzPdM1iraqzMFUEsTQAbkk4p fSnk3Qv0H5bstPYD1kTncEf79f4n+dCafRmqyz4pEvRYMfBABOsrbXYq7FXYq7FXn/5ka8zSLo0J +BeMl0fFuqJ9H2vuzN02P+J1HaOf+AfFgmZbqku1LzHoWmPwv76G3k6+mzjnQ9+Iq34YshElV07W dK1NC9hdxXKj7XpsGI/1h1H04oMSOaMxQ7FUk8yeYfMuhvZXWhacb+USFnKhyYylChog774CLFNu LY3dU+gfKmtvrvlvTtXktns5b2BJJrSUFWjkIo6UYA7MDQ03G+aqceEkPSY58UQe9NcizdirsVdi rsVdirsVdirsVdirsVdirsVSDzt5rt/LeivdtR7uWsdnCf2pCOp/yV6n7u+WYsfGaaNRmGON9Xzr d3Vxd3Mt1cyGW4mYvLI25ZmNSc2gFCnQSkSbKjhYuxVln5X6Mup+cLQSLygswbqUf8Y6cP8AkoVy nUSqLl6LHxZB5bvoPNY712KuxV2KuxV2KvD9VvGvdSubtjUzSM4+ROw+gZtoRoAPL5Z8Uie9i3nL VdRsdNht9KQy6vqc8dlp6KKn1ZjQEDufD3yRNJww4pUyS6/J78vPIHkS+8yea7JvMuq20ay3kkks io88riNY4gCKKZJAObgt39swfGlOVDZ3ngQxxsi3j+tah5NvrrTL7yFaz6Pr6WklzqVsrubb1YI/ VlijErOxHBXp8VGoBwBOZMOMXxcnFyRxzHp5vSfLurprGiWmpKvH6wlXUdA6kq4HyYHLXVSFGkxx YuxV6r+XdyZvLaITX6vLJGPpIf8A43zXakVN3/Z8rxe5k2UOa7FXYq7FXYq7FXYq7FXYq7FXYq7F Vk00UEMk8zBIolLyO2wVVFST8hiAgmnzp5481TeY9cku6kWcX7uyiP7MYPUj+Zzufu7ZtMOPhFOg 1OfxJX06Mey1x3Yq7FXrX5GaeBFqmosNy0dvG3yBdx+K5hauXIO17OjsS9VzDdm7FXYq7FXYq7FX gpBBIOxGxGbh5NIfMkkdhqXl3zBMGa00TVLa6veAqy2/MCRwO/HbIzFxIcrSTEZi30Fr2iaL5r8u XOl3tLnStThALxOPiU0eOSNxUbEBlPTNXGRibeglESFF4+/5OeR/yu0fWvNt3qEt9cQWdxDpqXIR VWS4iaJUCr/eSPz4+FCTTwyPGlkIDjjDDGDJjvkXTrjTvKenWtwOMyxs7qeo9V2kofcc8znQZDZV /MnmbTPL9iLq+LHmeMMKCru3Wg7D3JxRGJKUWf5jaBc6A+oG+hi1bkVtvL4juZLiUhiqr6yx+krP sRSo33NdsrMpcVVt3uWNNHhsy37nuP5WSs2mXasOJEiMU6kFk3/VmLquYczsw+kjzZvmK7N2KuxV 2KuxV2KuxV2KuxV2KuxV2KvMvzk82G3tU8v2r0muQJL0jqsVfhT/AGRFT7fPMvS47PEXXa/PQ4B1 eO5nOodirsVdir0r8tvNsmi2EdpLEjWM87SSyAH1AWonKtaGnAbUzHzYeLfq5em1nh+kj0vZVZWU MpBUioI3BBzXO9dirsVdirsVdirxnzRp5sNevIKUQyGSP/Uk+IfdWmbTFK4gvN6rHwZCEpkjjkja ORQ8bgq6MKgg7EEHqDljjoXSH83eXoTaeWvMEljptSY9OuYEvYYqkkiH1CrxrU14hqZVPDGW5c3F rpxFc1C/07V9c1CC/wDNWrS61LaHlZ2xjS3tIm/mWCP4S3+UxOShjEeTDNq5z5plk3FS/WtB0nWr YW2pQCaNTyQ1KsrEUqrKQRiyjIjkxTyl5N0PTPNeqLEGnksFt2tjKQxj9dWJOwAr8OxxbJzJiH0D +V8RGnXstNnmVa/6q1/42zB1R3Ds+zB6SfNmuYrs3Yq7FXYq7FXYq7FXYq7FXYq7FUJq2p22l6Zc 6hcmkFtGZHp1NOij3Y7DJRjZpjOYiCT0fM+sapc6rqdzqNyazXMhdh2APRR7KNhm2jHhFPOZJmci T1QeFg7FXYq7FUy8o+Yba/N5puy3WnSMjLX7UZNQ4+n4T/bgWca3e3/l7r/1ywOnTtW5tB+7J6tF 0H/A9PuzA1OOjfe7js/PxR4TzH3MuzGdg7FXYq7FXYqwj8ytGMtvDqsS1aD91cU/kY/C30MafTmX pZ706ztLDYEx0ed5mumdirsVdiqF1TUbbTbCa+uSRDCtSAKkkmiqo8WYgDFIFmkt8raZdQxXGp6g CNU1Vlmuo+0SqCIoR/xjU0+eLKZ6Do988m6a1h5eto3FJZQZpB7ybj7loM1meVyL0Gjx8GMBO8qc l2KuxV2KuxV2KuxV2KuxV2KuxV5Z+dnmEpDa6DC1DLS5uwP5QaRqfmwLfQMzNLD+J1vaGWgIh5Hm a6l2KuxV2KuxV5qmvXOi+c7jUbep9K5kWWPoHj5EOp+fbFvq40+gvLmviN7PWdOfnGwEsZ7MjDdW +Y2OQnESFFpxzOOVjo9v0++t7+yhvLc8oplDL4jxB9wdjmrlEg0XpMcxOII6ojIs3Yq7FXYqsuII biCSCZQ8UqlHQ9CCKHCDSJRBFF435j0ObR9TktWq0J+O3kP7SHp9I6HNniycQt5vU4DjlXRK8saH Yq7FXEA7EVHXf23xVPvJ2gnVtWQSLW0t6SXB7H+VP9kfwrlObJwx83L0eDxJ78g9dzWvQuxV2Kux V2KuxV2KuxV2KuxV2KuxV80+cNYbWPMuoX9axySlYf8AjEnwJ/wq5tsUeGIDzuoyccyUmybS7FXY q7FXYq8j19eOuX46/wCkSn73JwuTHkz78oPMrCSTQLhqq3Kayr2I3kQfP7X34C1ZY9X0L+XfmD6t dnSp2/cXJrAT+zL4f7L9eYmpx2OIOV2fqKPAeRekZgu6dirsVdirsVSPzhoK6tpLhFrd24Mls3ck DdP9kPxpl2HJwy8nF1eDxIeY5PIM2TzrsVdiq6ON5JFjQFnchVUdSTsBikCzT2Pyxocej6VHb0Bu H+O5cd3I6V8F6DNXlycRt6PTYPDhXXqm2VuQ7FXYq7FXYq7FXYq7FXYq7FXYqlnme++oeXNTvAeL Q20rRnp8fAhP+Gpk8YuQDXllwwJ8nzHm2ebdirsVdirsVdiryjzOnDzBfClKylv+CAP8cLkR5IXS dRl03U7W/h/vLaRZAPEKd1+kbYpIt9KWl0HSG7t3NGCywyDY0NGUjIuHuC9w0e/F/pdreDrNGrMB 2alGH0NXNTONEh6fFPjiJd6MyLY7FXYq7FXYq8T16BINbv4U2RJ5Ao8ByNBm1xm4h5nURrJIeaAy bS7FU88lNZDzNZC6YAMzCDl0MvElB+G3vTKc98Bpy9CB4ot6/mtehdirsVdirsVdirsVdirsVdir sVdirE/zTuPR8jajT7UnpRj/AGUqV/CuXacesONrDWIvnzNm6B2KuxV2KuxV2KvMvPEXp+Yp27Sr G4/4AL/xrhb4ckhxZvoLyJctceUNKkbqIBH9ERMY/Bci4mQep7t5AZm8r2wJqFaQD5eoT/HNdqPr LvdB/dD4siyhzHYq7FXYq07qiM7GiqCWJ7AYqS8N1C6N3fXF0es8ryU/12J/jm2iKFPLZJcUie8o fJMHYqh9QEv1ZpIWKTQkSxOuxDIeQI99sWUTRt7L5K8zReYtBhvQQLlP3V5GP2ZVArt4N9oZq8uP hlT0mnzeJG0+ytudirsVdirsVdirsVdirsVdirsVYJ+czlfJ4FPt3USn/gWP8MyNL9bha8/u/i8L zYukdiqpDBNM/CJC7eAxVM7fy/K1DPIEH8q7n7+mNseJHxaLp6dULnxYn+FBgRaIWys1FBBGP9iM VtRn0bR7huc9jbytSnJ4kY08KkYpEill55C8oXYPqaXChPeEGGny9MqMUjJIJppOl2uladDp9pyF vACI+R5GhYtufmcWMjZt7H5EutPbQLe2t51kniDNPGNmVmYtuDv3pXNdqAeKy7/Qyj4YAO7I8ocx 2KuxV2KpJ5zv/qXly7cGjzL6CfOTY/8AC1y3BG5BxtZk4cZ+Tx/Nm847FXYq4gEUPTFVvkbzK3lb zO0UzEabdMIrodlUmscn+wrv7VyrPj4o+bnaPPwS35F76rKyhlIKkVBG4IOax3zsVdirsVdirsVd irsVdirsVdirz787SR5UtQDSt9GD7/uZTmTpPq+Dgdof3Y9/63iWbB0ya2GhvJSS5qidRH+0fn4Y oJTuKGKFAkShFHYYGC/FXYq7FXYq7FXYqq29zcW0yT28jRTIao6GhBwEA82UZGJsc3pPlLzvHqRW x1AiO+O0cmwSX29m9swc2Dh3HJ3Wk1vH6ZfV97LcxnYOxV2KsA/NC/q9lYKegaeQfP4E/wCNszNL HmXU9p5OUfiwPMx1LsVdirsVSPzDBSSKYftDi3zG4/XhDKL0r8pPPAuYE8vahJ/pMI/0CRj9uMf7 rJ8U7e3yzB1OKvUHc6HUWOA8+j03MR2KR695v0rRyYpCZrulfq8dKivTkTsuW48Jl7nFz6uGPY7l jLfmffPKFh0+P4jRVLszVPToFzI/KjvcL+U5E7RZrpdxqk0PLULVLWSgoqSepX57Cn3nMWYA5F2e OUiPUKRuQbHYq7FXYq7FXYq8+/O0E+VbQDr9fj/5My5k6T6vg4HaP92Pf+t5jpekrCBNOKzHdVPR f7cz3SEppixdirsVdirsVdirsVdirsVbVmVgykhgagjYgjFXq3krzN+l7IwXDf6fbAeof506B/4N /bmuz4uE2OTv9FqfEjR+oMkyhzXYq8h873ZufMt4a/DEViUeHBQD/wANXNlgFQDz2tneUpFlziOx V2KuxVL9dTlYE/ysp/h/HFMWPQzSwypNC5jljYPG6mhVlNQQR4YSGwGjYey+XPzTS+8t3Iu2VNdt I6KCAFmqQqyKPEE1Zfp6dMGWmqQ/mu1jrv3ZJ+oMOlkklkaWRi8jks7sakkmpJOZoDpiSTZaRmRg 6mjKQVI7EYqDT2nQdWj1XSoL1aBnWkqj9mRdmH39PbNVkhwmnpcGUZICSYZBudirsVdirsVdirzz 8y9Ytrh4dJRRIbaQTyud+MnEqqj34uSczdNjr1Oo7Rzg+gMHzLdU7FXYq7FXYq7FXYq7FXYq7FXY qjtF1WbS9TgvYt/Tb40/mQ7Mv0jIThxCm3DlOOQkHtUM0c8Mc0R5RyqHRh3VhUHNWRT0wIIsL8CX ivmHl+n9S5Vr9am6+HqGmbXH9I9zzOo/vJe8pdk2l2KuxV2KpfrrUsCP5mUfx/himLG8LNcjsjB0 JVlNQR1BxVkumait3FRtpk+2vj7jAwIRuKGfflddyH69aGpjHCVfAMaq330H3Zh6oci7bsyZ9QZ7 mG7Z2KuxV2KuxVL9e1VNK0q4vW3ZFpEp7u2yj7+uTxw4jTVny+HAyeLzTSTSvNKxeSRi7sepZjUn NoBTzJJJsrMKHYq4kAEk0A3JOKpJeed/KdpIY59Ug5jYhCZKH39MNizGORXWPnPytfP6dtqcBkPR Hb0yfkJONfoxU4yE5xYOxV2KuxV2KuxV4Z550jzFa+Y76aSO4e2mmeW3nUO0fByXChhsONaUwuXC Qp9Df84ua7rd95S1DTdT9Z0024X6nNPyr6U6k+mpbqEZCf8AZZgaqIEr73baOdxrue0ZiuW8e85W 5g8zX69mcSD/AJ6KG/jmzwG4B53WRrKUqtbdri5ht02aZ1jU+7Gg/XlhNC3HhHiIHepYWLsVdiqU eYpKRQxeLFj9Ap/HCGUUixZOxVVt7iS3mWWM/Ep+8eGKs00u0u9UEf1GB5zINggJp8z0FPfISkBz WGKUjQFvWPJ/ls6LYMJSGvLghpyOgp9lAfapzX5svGfJ3uk0/hR35lPspct2KuxV2KuxV5/+Z+os ZbTTlPwqDPKPEmqp91GzM0seZdR2nk5R+LBMzHVOxVDalqVnptjNfXknp28C8nb8AAO5J2GKQLLx +91fzl+YOtLpGi200schPoadB04j9uZtlp4ljxGMpCIsuZiwkmhzZ7pX/OJvm+4tll1LVrOxlYV9 BBJOy+zEcFr/AKpOYx1Y6Bzhoj1KF8wf84reebCAzaVeWmrFf+PdWNvMf9USfu/vcYjWQ67LLRS6 G2E+XPOWv+UtSfStWjmNtA/pXVjOCJYCOvANQqR/L0P45kggiw4GTF0Oxez2l3bXlrFdW0glgmUP HIvQg4uIRSrih2KuxV2KuxVmH5Z3hj1ie2J+G4hqB/lRmo/AnMbVR9Nux7NnUyO8PS8wHdvN/wAz bIx6nbXgHwzxcGP+VGf6MMztLLYh0vaUKkJd7HvLahvMGnA/8tMR+5wcvy/Sfc4mmH7yPvCEvoDb 3txARQxSOhHhxYjJRNhryRqRHmoYWDsVYlqeqRXerXNsp3taJ89qsfoYkYWwDZQxV2KuxV7T+SWo STaBeWTmotbjlH7LKtaf8EpOYGqHqt3PZ8rgR3F6NmK57sVdirsVdirsVeQ+drk3Hma9NarGyxKP DgoB/wCGrmywCoB53WyvKUiy5xXYq8v/ADe1O5uL7T9AtasXpM8a9XkkYxxL+B+/FyMEbfTP5Vfl xp3kXyxDYRIj6pOqyareAbyTU3UN14JXig+nqTmsy5DM27/FjEBSh+dHnm78meQ7vVLED9IzulpY uw5KksoJ9QjoeCKzCu1aVxww4pUubJwRJeH/AJW/85GJ5d0i7sPM9veapPJNJcwX0brJK7yAVSX1 WXao2YE/LL8+j4jcdnFw6zhFSYlfald/mZP5jvLiEJrNjFNq2nlTVvqcTgzWbNSr+mj84yenFl/a AF8Y+GAOnJqMvFvvG4/Umf5N61JLaXekSvX6uRPbA9kc0cD2DUP05cXXZo9XpGBodirsVdirsVTr ybceh5msG7M5jP8Az0Ur/HKs4uBcrRyrKHsOax6Jj/nrSzf6BKUFZrU+uniQoo4/4EnLsE6k4mtx ceM943eaeX34a7pzVoBcw1PtzFcz8n0n3Ok05rJH3hF+c7U23mW+Wm0jiVff1FDH8ScjgNwDZrI1 lKSZa4qF1W/j0/T57ySlIlJUHu3RV+k7YpAsvKLNdRubxp7epnLF3k6CrGprXxyTkGmUW5ufTH1h UD9yhJH4gYGsquKHYq9o/JCyePQr68YUFxcBF8SIkG/3ucwNWfUA7js6NQJ83o+YrsHYq7FXYq7F XYq8V8wknX9SJ/5aph90hGbXH9I9zzOo/vJe8pdk2l2KvPI4Fl/P7QFuADGbyydAf8ihX/h1yGX6 C7DRi5RfX2ap3jCfzj8i3HnTyLd6TZsBqMTpdWAY8VaaKvwMTsOasy1PQmuW4Z8Mras2PjiQ+K9T 8u69pd++n6jp9xa3qNxNvJGyvX2FN69iOubMSB3BdSccgaIfQ3/ON35Tarp7XvmbzDaNbJe2zWdj ZTgrI0UpBlldDRlBChVr1BJ8K4epyg7BztLhMdy8o/KBAvmq9CHlEtpIA3Y/vo6H7szXVZ+XxewY HFdirsVdirsVRWlzejqdpNWnpTRvX/VcHIzFgtmI1MHze45qXqHEAggioOxBxV5F5j0ltB18emD9 X5rPan/JDV4/NSKZssU+OLz2oxeFk8uYTX8y7Vfr1nfJvHcwleQ7lDWv3OMr0p2Ib+0o+oS7wwzM p1rz7z35giu7gaZayB47Zq3JU1/ejbjt/L+vCG6Ea3a0WONNOiKD7dWY+JrisuaOxYuxVG6RpN9q +ow6fYx+pcTtRR2A7sx7ADc5GUhEWWePGZmg+kvL2i22iaNa6ZbmqW6UZ6ULud3Y/wCsxJzVTlxG 3osWMQiIhMMizdirsVdirsVdirxjzPEYvMWoqRSs7t/wZ5fxzaYj6Q81qhWSXvSvLGh2KvP/AMyb e+0vVtH84aeKz6XNEZPAGKT1IiaduVVPzGAixTk6fJwl9T+WPMemeZNBstb0yT1LO9jEifzKejI3 gyNVT75qpRMTRehjISFhNMiydirCPzi88WvlHyLqF40oXULuN7TTIq0dp5VKhh7Rg8z8qdxluGHF JqzZOCJL56/KDQpLXTLjVZlKvfEJAD19KOtW/wBkx/DNoXns0uj0HA0uxVhfnf8AMW30GRrCyjFx qdAX5V9OIMKjlTcnvQYtsMd7liPlP8wrWTzKlz54lvr3RQjVtLCT0B6m3AskbQ8kHccge+/Qwyxk Y+nm5mCOMS9Q2Zn58/M/8qLrQZLLynpeoRa04C2d8sktuImr9okSu0h7cSu/jmPix5RK5HZyc08J jQG6f+Wv0mmh2B1FmOoCJDOX+1y6/F/lDvmW6eR32fRead6pjXnT8xfKfk/T5rrV76JZ405R6ejo bqUn7ISKvLfxOw7nJwxmR2YTyCIsvnrzN/zk1NrkqQny9FDZRuGjczs9wo6NRgqpv4cfp75n4sHB 1dXqcwyiqZRL+enkDWPJMcF5dTWmq6cyCG3lhdmmUDj8LRiRPsnfkw3GRjjMZ2ORRMieERJ9UXm/ mb83YpLRrbQopEmkBVruYBeAO37tQTv7np4Zk04UcXe8xEkgcuGPMmpaprU++FvT/wAv+cLvTW9K 55XFoxqVJ+NT4qT1+RxYShb0fRmutZQNplhfXVdyIrS4enzKIy/jkDOI5lA08zyDMtG/KrznqLK0 tmNOgYBhLduqkiu9I0MkgPsyjKZamI83IhoMh57PYfKXkvSPLVp6dqvq3cgAuLxx8bnwH8q16KPx zCyZTM7uzw4I4xsn+Vt7sVdirsVdirsVdiryv8xLMweYnlp8N1Gkg+YHA/8AEM2GmlcXQ9oQrJfe xjMhwXYqpXdrb3dtLa3MYlgmUpLG3QqeoxSDTFPL+p+evytv55tBjOs+V7h/UudMcksniy8alG47 c1BB/aGwyvJiE/e7DT6wx2enaP8A85QflreRJ+kDd6VPsJY5oGlVT3o0PqEgf6oPtmGdLIcnZDVw Pkg9f/5yn8k21uV0K0u9WvmFIkKehFU/zM1X6+CZKOll1RLVwHLd5bc6b5y/MTXl17zm7W1kn+8u nKCgWMmvpxoTWNdviZviP4jMhARFB1WfUmRZ9FFHFGkUShI41CoiigVQKAADsMk4S7FXYq8785/l fc6rqU+qaddIs09GktpgQvJVC/C61606EfThtuhloUXnOs+Vdf0bfULN4o60Ewo8ZJ6fGtV+jFuE geT0T8t/IH1VY9a1WP8A0o0eyt2/3WD0kYfzeA7fPolqyZOgejYGh73mneseGaz/ANCr/pa8/Sf1 f9I+s/1uv6Qr6tfjrw+Hr4ZlR8WtnGl4V71aEj/6FH5rx+q1qKcv0jSvvy2p88P75j+58k60n/oV 36yPqv6E9Wop9arwr2/3p+DInxfNkPB/ooDzP/0Kl9df9Jfo/wBfl8f6O+t8K/8ARh8GGPjdGOTw etfj3InRP+hV/VT6n+iOVRT676nGte/1z4fvwHxfNkPB/ovRfL//ACrX1U/w9+hvV/3X+j/qvLt9 n0d/DKZcXW2+NdGS5Bk7FXYq7FXYq7FXYq7FXYq7FWP+af8ACXO2/T1OdH+r/wB9Wm3L+6+jrl2L j/hcTVeDt4n6f0JF/wAgq/z+uZd++/FOJ/gn44nf8gq/z+uY/vvxS/4J+OJ3/IKv8/rmP778Uv8A gn44nf8AIKv8/rmP778Uv+CfjiSfVf8AoXv1T+lv0f6u3L636vL2r6m+P778UzH5bpf+yX6T/wAq B5f7iPqPKn/Hp61af888f334pB/Ldf8AfJr/AMgq/wA/rmP778Ux/wAE/HE7/kFX+f1zH99+KX/B PxxO/wCQVf5/XMf334pf8E/HE7/kFX+f1zH99+KX/BPxxO/5BV/n9cx/ffil/wAE/HElfmb/AJUd +g7n9Of8cv4PrH/HQ/34vD+6+P7dOmP778Uyj+Vvb/fJkn/KqeC0rSgpy+u1+mu/34/vvxTH/BPx xL0/5VZzXj9qo4/719fpx/ffikj8p+OJ/9k= uuid:3f9dfa49-13c5-43ef-b449-19dceef32d35 xmp.did:A52CEDF16CBCE011BC36B4B7420BD8A9 uuid:5D20892493BFDB11914A8590D31508C8 proof:pdf uuid:29e17876-faee-8948-9286-1741a44a591b xmp.did:F77F11740720681188C6A5613A2C864B uuid:5D20892493BFDB11914A8590D31508C8 proof:pdf saved xmp.iid:A52CEDF16CBCE011BC36B4B7420BD8A9 2011-08-01T20:34:52+02:00 Adobe Illustrator CS5.1 / Document Print False False 1 210.001652 296.999959 Millimeters Cyan Magenta Yellow Black Default Swatch Group 0 White CMYK PROCESS 0.000000 0.000000 0.000000 0.000000 Black CMYK PROCESS 0.000000 0.000000 0.000000 100.000000 CMYK Red CMYK PROCESS 0.000000 100.000000 100.000000 0.000000 CMYK Yellow CMYK PROCESS 0.000000 0.000000 100.000000 0.000000 CMYK Green CMYK PROCESS 100.000000 0.000000 100.000000 0.000000 CMYK Cyan CMYK PROCESS 100.000000 0.000000 0.000000 0.000000 CMYK Blue CMYK PROCESS 100.000000 100.000000 0.000000 0.000000 CMYK Magenta CMYK PROCESS 0.000000 100.000000 0.000000 0.000000 C=15 M=100 Y=90 K=10 CMYK PROCESS 14.999998 100.000000 90.000004 10.000002 C=0 M=90 Y=85 K=0 CMYK PROCESS 0.000000 90.000004 84.999996 0.000000 C=0 M=80 Y=95 K=0 CMYK PROCESS 0.000000 80.000001 94.999999 0.000000 C=0 M=50 Y=100 K=0 CMYK PROCESS 0.000000 50.000000 100.000000 0.000000 C=0 M=35 Y=85 K=0 CMYK PROCESS 0.000000 35.000002 84.999996 0.000000 C=5 M=0 Y=90 K=0 CMYK PROCESS 5.000001 0.000000 90.000004 0.000000 C=20 M=0 Y=100 K=0 CMYK PROCESS 19.999999 0.000000 100.000000 0.000000 C=50 M=0 Y=100 K=0 CMYK PROCESS 50.000000 0.000000 100.000000 0.000000 C=75 M=0 Y=100 K=0 CMYK PROCESS 75.000000 0.000000 100.000000 0.000000 C=85 M=10 Y=100 K=10 CMYK PROCESS 84.999996 10.000002 100.000000 10.000002 C=90 M=30 Y=95 K=30 CMYK PROCESS 90.000004 30.000001 94.999999 30.000001 C=75 M=0 Y=75 K=0 CMYK PROCESS 75.000000 0.000000 75.000000 0.000000 C=80 M=10 Y=45 K=0 CMYK PROCESS 80.000001 10.000002 44.999999 0.000000 C=70 M=15 Y=0 K=0 CMYK PROCESS 69.999999 14.999998 0.000000 0.000000 C=85 M=50 Y=0 K=0 CMYK PROCESS 84.999996 50.000000 0.000000 0.000000 C=100 M=95 Y=5 K=0 CMYK PROCESS 100.000000 94.999999 5.000001 0.000000 C=100 M=100 Y=25 K=25 CMYK PROCESS 100.000000 100.000000 25.000000 25.000000 C=75 M=100 Y=0 K=0 CMYK PROCESS 75.000000 100.000000 0.000000 0.000000 C=50 M=100 Y=0 K=0 CMYK PROCESS 50.000000 100.000000 0.000000 0.000000 C=35 M=100 Y=35 K=10 CMYK PROCESS 35.000002 100.000000 35.000002 10.000002 C=10 M=100 Y=50 K=0 CMYK PROCESS 10.000002 100.000000 50.000000 0.000000 C=0 M=95 Y=20 K=0 CMYK PROCESS 0.000000 94.999999 19.999999 0.000000 C=25 M=25 Y=40 K=0 CMYK PROCESS 25.000000 25.000000 39.999998 0.000000 C=40 M=45 Y=50 K=5 CMYK PROCESS 39.999998 44.999999 50.000000 5.000001 C=50 M=50 Y=60 K=25 CMYK PROCESS 50.000000 50.000000 60.000002 25.000000 C=55 M=60 Y=65 K=40 CMYK PROCESS 55.000001 60.000002 64.999998 39.999998 C=25 M=40 Y=65 K=0 CMYK PROCESS 25.000000 39.999998 64.999998 0.000000 C=30 M=50 Y=75 K=10 CMYK PROCESS 30.000001 50.000000 75.000000 10.000002 C=35 M=60 Y=80 K=25 CMYK PROCESS 35.000002 60.000002 80.000001 25.000000 C=40 M=65 Y=90 K=35 CMYK PROCESS 39.999998 64.999998 90.000004 35.000002 C=40 M=70 Y=100 K=50 CMYK PROCESS 39.999998 69.999999 100.000000 50.000000 C=50 M=70 Y=80 K=70 CMYK PROCESS 50.000000 69.999999 80.000001 69.999999 Grays 1 C=0 M=0 Y=0 K=100 CMYK PROCESS 0.000000 0.000000 0.000000 100.000000 C=0 M=0 Y=0 K=90 CMYK PROCESS 0.000000 0.000000 0.000000 89.999402 C=0 M=0 Y=0 K=80 CMYK PROCESS 0.000000 0.000000 0.000000 79.998797 C=0 M=0 Y=0 K=70 CMYK PROCESS 0.000000 0.000000 0.000000 69.999701 C=0 M=0 Y=0 K=60 CMYK PROCESS 0.000000 0.000000 0.000000 59.999102 C=0 M=0 Y=0 K=50 CMYK PROCESS 0.000000 0.000000 0.000000 50.000000 C=0 M=0 Y=0 K=40 CMYK PROCESS 0.000000 0.000000 0.000000 39.999402 C=0 M=0 Y=0 K=30 CMYK PROCESS 0.000000 0.000000 0.000000 29.998803 C=0 M=0 Y=0 K=20 CMYK PROCESS 0.000000 0.000000 0.000000 19.999701 C=0 M=0 Y=0 K=10 CMYK PROCESS 0.000000 0.000000 0.000000 9.999102 C=0 M=0 Y=0 K=5 CMYK PROCESS 0.000000 0.000000 0.000000 4.998803 Brights 1 C=0 M=100 Y=100 K=0 CMYK PROCESS 0.000000 100.000000 100.000000 0.000000 C=0 M=75 Y=100 K=0 CMYK PROCESS 0.000000 75.000000 100.000000 0.000000 C=0 M=10 Y=95 K=0 CMYK PROCESS 0.000000 10.000002 94.999999 0.000000 C=85 M=10 Y=100 K=0 CMYK PROCESS 84.999996 10.000002 100.000000 0.000000 C=100 M=90 Y=0 K=0 CMYK PROCESS 100.000000 90.000004 0.000000 0.000000 C=60 M=90 Y=0 K=0 CMYK PROCESS 60.000002 90.000004 0.003099 0.003099 Adobe PDF library 9.90 endstream endobj 3 0 obj <> endobj 7 0 obj <>/Resources<>/ExtGState<>/Properties<>>>/Thumb 12 0 R/TrimBox[0.0 0.0 595.28 841.89]/Type/Page>> endobj 8 0 obj <>stream H͎|.e'0| lAZz{dwW[ͮ"?1|at꬧pg1}_xVB;|>~)DRH}C~=׃ízC*g%6 Xa i{(gx;8{2cR:{aYS ̕[/EgΒ,(Mϡ1-*Xނ p˜S×ٱVN\ ΜVޏ[Ng+=iψt\<"oǿ >!\ỄMAxz?s6|q'L٢ e?9Qsap/~Q! GpZjX/crɗ@Bcb$lvb\;wiU,gIF6ȥy<𡝩c YɝP˶qy  +˙吉E uIϑxݒBy_0!u,s$)]9v#ꦨ7vՐ[JMsTꕽ"?sf;'N޲KBuDz٨F%pno b׏cزtK9 &C8׃uqjŋOVjNπZ ê@Ʋ&Mw9س9јiI"f.sD+ZN$,3;eQ&zĈ{'*&+B<3KS_"sn)FA04G8)p@P%V=x6 kcGκM瓷*JxzWIq@uw%mA@*=NG>)Xg]-JYNq35 %R6|TM@ȓҗD_V_(<vDcbhEmXgє8fqyxkB$sj&jNkR}H4-*>C/*t~1Gdk$]_PT:$)"ERz_[?uXLr-"V׽C2HC#z\%JBLc9 M0"Ft8Mdɹ(+E$B|aO3*sʡs,Ֆ8͑':RJ$$-EJ!' C*vrjrzM4lDR*f1xyJ[mTͪæ~V_)99^;v\,&d.)>=7Tv;y|~Hpf`]yu'0E?k/XtWV|Wjݻm??-ѧ(ͬW'%/*׷>Zk-c@^5{н\K:M HY#\"]{a}H3$< u9Hx+ˡ,Ǎ4Q;AK*OX%=n$hђ~!n${~@WGCz?P5ɛX3GQ] o*t Еg*AAP{,+_$yӤ=-IZ[c+f,P扊htHNc2כ(/c$B#P;ۛ;6V pBtJ3|b=3ژ`o-C2+ pV#f CKGcx㔞]gZ0@u AT,S˜"8VkP*ʶIiU;z(9s[4b:pFbU;4LPP"[EA5yyOۇ*5W<# endstream endobj 12 0 obj <>stream 8;Z]!4-mc<#XqBgbZ%I$`CQ70UZG2bD.`isr'QVTG6:%!30AicDB:bt>?G!0=BJ[- kRk7i$@1fA.^Zmbah-pd9r-tn9o^X4pdQR,j<;35Lab?;q,MgeWfg0cnbSOkJjblM*"YdI#.3gUf?WDUba*S.Yk=\.Bt4ip1@0%81@3&dMaX V9Ok[QC8#BG"t@:oP9JU$7Dt-bDbm8+!;@t8nSa0m^J@c6@D$HD9)6iT3mbF9&39* (#sQ`KGY5KPFQQoOn)R\Km5i%Q$*M"b,J4Kk' /1`>'rd"DN!*0i#D?~> endstream endobj 13 0 obj [/Indexed/DeviceRGB 255 14 0 R] endobj 14 0 obj <>stream 8;X]O>EqN@%''O_@%e@?J;%+8(9e>X=MR6S?i^YgA3=].HDXF.R$lIL@"pJ+EP(%0 b]6ajmNZn*!='OQZeQ^Y*,=]?C.B+\Ulg9dhD*"iC[;*=3`oP1[!S^)?1)IZ4dup` E1r!/,*0[*9.aFIR2&b-C#soRZ7Dl%MLY\.?d>Mn 6%Q2oYfNRF$$+ON<+]RUJmC0InDZ4OTs0S!saG>GGKUlQ*Q?45:CI&4J'_2j$XKrcYp0n+Xl_nU*O( l[$6Nn+Z_Nq0]s7hs]`XX1nZ8&94a\~> endstream endobj 5 0 obj <> endobj 15 0 obj [/View/Design] endobj 16 0 obj <>>> endobj 11 0 obj <> endobj 10 0 obj [/ICCBased 17 0 R] endobj 17 0 obj <>stream HuTKtKKJI,t(݋4K%ҹH4J#Ғ(H wqyy~3̙g<3Y9El @ ]!O-@\+BVKK :OX~WCaiHKL0qY `5ck X]x= 8 XĿ׽>.f#aPn D^{y8  dp H st:Y׬cxc IV?S!:_9[YbQP~+rA ShHht^ '0߅™kYXY9Yqqpl'WzEE$%D>,^|t*K)%/`\ҫ:&D [7dplDa5|mb4,yy{e5 3⚅,t+whlA   m k xYUH&%Ȥ qO'Mz3KT@v[NUnn^\o]abTrtlmE]e~U+jאZ:zaqi5};CS[\_ۆwCaQ1;>L$Lz}4:%8M7l̎Χ/}XT^]X>\Ym[n!ycskkƶʷ;v{pIs0Xݯ3s󝋒&$WWW*)!$$%!e$cHNOAKIMEq ƕ;KLw@YX;ؚ8^+DspfKOTCPpJ%D=++O%$*8IZ\Z^UK_wL"dx]}>9=;s_G8/̹N!Gz[<=2|B}PQzlH0Wc(Een|Pds::5&89yFT"od䳔i/ZK^&gd:fgQl kJХeJ*+篍kj5U[ZUh0|em6]B@`PpH?QM1Msψ*iϛ.Z [JYZ)X-]R޸Ѻپw?@?5 ǖ'vNg W3gLC#u!MMMEvAms˔FVNA̝GLwA̬,llؿsݛnͽ+!B²" 'R&k?3?4+:6oT\ұڿ6VʝoF?LT;:>::>:;eqvx^sawݥʕ'_EFO\DKLtAnFF)F|ԭ6\`@z?m+F;LwiAhy͖)Mgw~_ @ZH_XA,"F)%/*9aZ:Q,\B^_AU񡒀2 *'[j o5[uR1uh`fm$1xJgBdrltlyyEe$feg-g#`dGbwj0TOC9; ܨݿxz6zx8IP=A!.aAxۑϊ}bG-ޒēx`G/Ԝq_O?0"۬խЮ˯ǰı²µŶȷ͸ӹۺ 0@RfzƏǦȾ *GcЀџҿ'LsٛFsM6+1MZ:{T?~ò~i~L}~cbA~Dad~ty~W~O>~\/~|~`Cx}%H}1X}%z}K} {N}׋<_~7A~-ψ||Dz|+E|[s|z} ^}wO@}-~ċ {Gu{Dz{]Ĭ{f{Zx|[]|ϕM?}R<}Ǝz]YzHħz|z={LNw{\|=>|v|ېI8z/r z;bz'sMzd6zɬqv{D[{0> |;|yyaIy?yazYvzݮ[{^=c{ФI{R*y߄yfUy`VyyuKzZi{ <{z%zȎ~+~}͇}W0}3}HtЄ}Zk}=~zɇ}!~Єd*s}Y<9wpSwuuVrUW؈|;,뇔{RsѲ;:8q)PCV:4.8Ȅ2񡂡?Up Vu9S c bփR.ՁNn U388A/ͬδz6߆өn1T\e7݀tXT)$̯̕6;eCʷˆ imw3SƀV7M \lGNػځNāa5tNzlߴS<H6*-N}o2ن N%է>w֣A}⇤\fXMݘ2, KԐ3g°[} 0e6M _1 ? 1ӣǾI^I|B̯dܪwLe1$: rW] 1S{z|diL g0\ U{[G{!{ ޔ`{&yE{xbie{Jr|/c5}~ ~:f#MKx+Ca|uI~.yW ώәߎ%¡唘[w!^T`^H*- 5GȨ瘎=Π4rv_ҍRGf,ދ̋|,ƕ{ Ҙtٕ^1Fő,;',#h%T,Qۥ{[s:9󅼓&^!Փa@!" y .Jl6mHju,bU6+s hܸd-ʥ}wi-sun=0Ľi-_*)U_ˈb$na+;ϧT;ppA7C4.*Iߥa8Mm.ACi7\j|fiԫ)]ޭjʄU]3(í whJch-4x7h׿*P0H됎L랇ڡuÂ,{Bz}8vggҲd[!XTZZ.vlAg {;Sm`vؿ`~?ga. 3Ì{L^WYe4]L7ok!wI~Ira^=C#Zh`Wu}p)"z7ff&3$FJ8Ҷ5m uR_,^VS&aR~PfLL_Dw*`\-9]q  TI6)>u6 D`e͢/xqY%9ʜ;åOd\˾P&eRz;].R<oΡ]P{?: r̨\ʻb Ҥ3|m s؟W9oZt]RnÅ\cW#+nI&gyAjsN06HiD'@J+a5V~cRI̫vwtUc[3+?F|l(iU^+O?Rs1Hqil$Wþh=(RE 1BvџnF/ BsGMY9>ܖ3ȗqI ڣ5V_1ȣβiJiX0WVH[8g_/ n3 ` 38A.|f|ј0I6bv%& ;Y㿜҄#dD.).p'3J12K[Duɥ$s8IƊ.z^48e!R6}vcMiozo0'=~i,3:?-?oS,9w#ROa; ?pB ֞IO ݟe#}ԯN$\l?], y,>&Рq]yh0AqK)ĝBFҍcH:-h-ǟcf)K9T127]qEjL<>h;|U dpG ƫ`&!8al`83>.qɂnA9 ; `HByg KB*k㰗2fF=#OM eT? mTm_OBۊV<ɆF('n3uG~Ȯ#7Њ9[١`Ns.P..콤 'KnpF\? B>-`NWOOWBlfxW^b-_x&*/(j_=߆󑊢zF`LdE:SNʔ@S 03|TOKokto}bFz$4-,.m'j*J|)J6BP ^3ewܫpX.*,07xPڳ:2XOT21|"7=0ߴy}ĸB)H[Fs V+̯+Y(I(x&9JAI'tXmyG=X[8TK)2<TSRvxlȓGO|g/{>4/gRFȶ&A52 uЯ*B幃AuFǞѧuD)B,*?n` 'qQIzK֗4{B_g68#ʉ2.A$69!̒ub1&D3Qx" >ɏnνxVG&TۨÓ)sxd-5KxߣD&1±jdGjJ|J{Z ޲f6/vTp̄ub PmBU#gBg˷)-*E ar>>Ƶrn[ɭF-IByѸP=ĶKUC wG D}"vN.p]]Q8uY{#qCv}sax_oyiNr( d8aw2CQ}V8UWO\g \yk@dcZt9$u p-1z(=f) vě92 w u煼ת#{P6+Dq3HIi%BCb!kc5&U ):X$܎[b2*@PkcӘdoTB_L1Uwi")=2#pI9,RO>T@>;bnDPuCfk^^\G~ oLRcHqܮ=-8^5Ońy*9:-\g8:T<?*C;[yX+I;lRL߭$DvYTQ6DyVmfy%/sIsmXP1Lռȭvow)QBb_LVwupeėO*|+](uHװ4WU.{ 4\m.QwR~MAiRz+%BKz?'{ k҉aa{H]sX}da~3_auQz VM\ĵv5I0LM)DŽp1:5,&4 %!$}ocޤA]R^xT◬M&/B:DwA24?cd&g]5b4a?iǐ Ĉ.OA 6vfvsd(5yTH/P=(a;zUs bWxDa)Eʼ $sgPJreY3w`cFo0|U[j5k.5J&eTor È´}I lpjC8c5J=g%Uo|L58E" ِ[Ak]J͆VBM"{NrQihЦ@Y?6^߫ZWٯ]ذc؋hKSLj:>O ɲ.ݰQ{5mm<ٷ?^v"}ъw9O&vX7km[ ,70nΒ7|eP\I;-wgFN cIP#qWI ;NٶA)H~7i thl~~dzY Cx2>*c&mb{9f1X*L #> V@g蒼]7n249=MK% ;,F\j 1klZi؊ΐ.|Q9а$_.!;̿lE,ɥDi}D3^a`Y5g{J=mɳy3CM'jM-iЦm n5? SJE+U~ ;q.tXd~~p*QeS%.Ћ"ưBsZ6-6[\d;^z4`;64藸ͱw;|+&AfLU3XTm)lF'l VɺgcGObbɜ9;v \CL, >B?KGCe"z -@EHILp<5'҉$>8#gL2m c1 c Fw)P+rkC qp/u8#!*g°Pa`vu@oH`"Ž:z_Q<,D>'ӅWP .`xW3|!6 5 El[",0 e[Oz0~lUO+&xkPc|u$k.?{Qp""kr6isVa=~@W_ .<7 2#h?c~m'rE_xs6aG+K 14L^kUp^^_mS^dШ'>}5$:τ!E[bJx&n t(m;ZsF5uqX.ՂBqKP *l%{ٓ{'f';,TT,bhUq2Z3;}T9vwRR;GD K*/@hUv$j!@ vyבm,W|-͢ ^ ~D_􆭍"ĉ#c禘*X/Ϝe>|XH;:)d9gƖ4aBQ4Ew,C ۯBU#>SV$L-5gV ϯ*B#} npþtdU$Db&$^\^&Z"/˺+-}%Z:}9AYu rTlP0"~! ͚*@5K?߫Z-P=j>܈[O?)a5 ?WUsy5^(ge${Cm> "Gգ+$踿ϫ& Xw8?g,'ō="/xNM)'EFqrf CįQ9ZY$r!6m)4 V9kJ$# FьX٥Cp[ģ)CS;rFP#ImKGɺzj>>X9,ZL-jIbkȉ8˚?vtxPIO}_ay@:|Ve6ubd/e3<֭ztea'cLaM lz&,f^_!?l2x2Xyń3D)\?ye ~4O+9$  EVDTSؓ7X?MM!ԼuOtP Cbt;iްa@gW#@4c9.Do z2>M5i~u0 qswQ9ǸLt삟Mz)>kɝI;io"U)]$YL >$$T:gUo$UK,C`sCMAJMÄKC(g]ٮ9sUG0?L5QM%0Ol5&`Ƒ1,x'{k+mY}-Js#\d:i/NK\8HstQ#-ND).s*Zymnf\1l{(E=VGW9s:?wǟQZsC6A1ƃ6K@8OUY^`7j6@9?,yt4&}"T- \Y&kVx녣391ٵqQ=beMq\`/nņ|2͌JkzDmͫIR4\~5NlօKɁZ]TC3l̅D3jSS)tWw$IX[wV WTUw^PeUhWE^ؓ~Wchs sIg`wgs (5mr] B`7JfAaA3ƓG?{O[ ?xj/Z*7exXz Ά})C?`KcMՌ&)Y5J]q':]$؞]Yv x(ıH1eU>_0b?*񸨎b¤،D;Wxm]|N7U13*;.=>SÜj)CM>.eI1/QvН6Tkk+Ɯn\\FFV#Xde&~WE7"bju^I@j@bQ Wk8w_D ^z xZKA _`T}] x}ЁM0S,rV+ KO&ƈ`;E{irf0F] w86f fm_8c3V<)r1p +hs|p!QP'Ղʛ2rӤej4Y r, r?4! Uq]f(*&umM+;1 -c8CjL=L1TDJ7>)BH*cHY}~xI,{7WjWާʇhg_YovMKiN> QRǧ}AQj^G syJG"?txt,L>֍p_>Po$^<%}KDS4 *S<ܖyd;éIJ~JMn>ȸcI6uɖژ䩊i77_5W2' 9t^}/8%wd0k)ͦF9kih3ShPBULzs'0$Y/L3ol|f ɪ\AW#siS-O^I+36xas @M A hm45V-' ѵ1S+ ~*%~k˝ʉl * lك=3_2~OgPs Ccd[aے{<ХjA {! ߲ۓ;O'9+wEHE&JV?fiӺ j05瀶bhWZxo=ƺ 0zhK5mov (YOut;e=R*yMVn,$v:QڳE.yVl;svn,Wi.[@34SD_!MF>J柣ND @$Y~-CMu (+lBpБ^#$~2è /@̣6 3nh ;۪.3Fq3\َvZnZ"/vNFNJ2V{#ΚVse_쑮Ta8C¢!Η>FL\M{5eH~7;F AB?VY=۩Q i9J.sӿc%FVbdեiL`a)kD=W \ne>NX7Ƒ†2IYf-to7/~Uas[`W*v3_`~:kjR("E * e)DDIss,f_n6":hmh+]AqñQqSa9{~8|~bh6GZĠםN\h+(E30~kTMGβ1:zka'LG2>,gt X&@?e% =@Ihs)HUOeX^m7R7~,, \jJԌfͬ8!*]JR:WR]Mɚ PZ;JN.8ɦ,[r*Α]MM"waX)Lbjd`>:?|:?u>^G$fa. ʥ_S%ED8 J=ĕK{6r zGG Ui<Kg"^ q I6vPWy^,uc/5@:ǹ+[N+li{P#^yv,ñ-NѳH⺣<֡gxV</nb6󴳜Ρ +nhB˾PoT(W##ĉTwZU} w-vT-9O᭺HIz) z9R'dI5aZGS˟agW=.P1ٜ y?2X)r4VaGXBe`9Q1͚@85$W?D}z2* pt +;Br\ܕ'> -vCNeʔL-ʌqKHr 7I d<BgNelB^փRγF2AqCR&t7߄{" D9u)Cw1t}?"'[7o̩~1{>Ru* ʖdClutqf2[l~{S4>J$.nQnlP#x])By`r+wLH?VD:|iUG~ժ+&+Rb gP>}WԹkQǖ]WSkqwZ DQdVd24KGMvU35KJ~4&jwJ*y;X߉˔O@5hw)񘴕o-9E:_̂o&6#V(ѽS-te$ פp}4%4mrnzhe4KX*KÃ29ʩ~'Ǥl|O5ÍB ;^j㛑Q`exH;J\*`l˴Khk &tF|(8VǡܷR:ϳoG*UjSKknRgl ޅ-6&Nŗ7O4rGmO[du_TvY{ ̏Iy\aRKy&P7ݪJ)l"W5{K S_j0WSW;wixF1^lО伴^'1b%OAXhq)L7j}=9PX=n`ɗKX#CùA *7{ jWܴTByufכd=Af]F=_u*`q+_i݋\^`BaE|S&%Z a8+QgQ[IK-jIKr2Tcju=A ʧQ"7{ٮם*X|,Yzѽ}ƈf:jCo[>]x^hlhNrϳEDkcCǪ ת9c Ht<)}z!hE~DBӳ2S͆i{;ouIp??砃46ٺ^"1R<-65sjpCSjqi6dzھİ紈 41.$5EG9:=ob쾄 v#[xﯦAF+T(C@RQF772I$^a$Eq>.AEbiO0]ТK5ΫPÛG ZdJ*$d ^}E*֤>?Ƅ$dO _tl%$^7[KSECqz"$]*B]}W zT[Rk"n]EUYvFUW\B6-RB^Me2B4/wͺh4Ek5˖<1U[tD>Q!.kR涧7uJc>c l/i^3;iڐ0sĀZnS qW7Np:([568ViAFޜ~h9Pldüj2dO +61--1Ewv =JCHW34܏&x8,&#Rc3Dvz6RSyu_N/nmكvT֥Y˼?RFװKzn9Q4gC^5l`P\ܲG&ޫ` 9PҞٲXr6 V4,{a؄\tcY`]lǿԾar鴯؏=b!&Yb ^[\aYt$w [R)i[{$7f"o Xp zBz'hO|Ō4ǐ|-j :}̴a%Tv5Y9QK d0 ?$ćH|#uD3 phrd@,@XmVKY@ou([8#!OM~.7SoJn%OG" Ü3N|/'O-R_1Vh&׺ NPz8de 勊ZTH;XQ6}+'h_|ȋCcuHjBA,NOS{3 L`]1> A rxӴ*E^.ؐ`Q5 v{`=W6뼟\9avGOXc& v1w~0W:ʎ~f: 0/˵%m KRKAcR% P#CSߥfmD5oEx17B0<&Yd8"1wܡ5 TaaJ3p57A>+yIMcu Zd?Bk1x-rsV9sH6p]DGgO| y5S$aE`$Ls [Ym ~u8p`6*I ߕ`S88sn9O3nXOE /7f^lbN[PBFO.9Z_.5>F S̉R'}ΪѬ`_dX|{dHXԾ3QlZe7PRqشO5OkZrx5u`aǂ:*`T), DPQʮdߓJRk=H+ *#u)h) )B6s9߹瞏HZGzGT"93hDͺ sr|b4y $TK "$I~$v(B#].qi?CN ~ޱ|ܷLcOnT~vxj̦5<.f\K<2p:CpSy,66>|zC E T)f/:X1}J+>_~Q;^ㆪvs&۸>.k7yZS:˩㜍rݖۜaKa!l.g57Kv0!;ڗfe %]"XT J3aժlwVj=v姠αe=bI/gH& :g,(y 27>aba88fVVqɌT0NɉB`( _"fo! t}Wg_0}HX 9,Qx=~Jٹx>ӱe9M2mFS)Vk-eZFF٥btg0O?Dǐ%7eyښ6WSCyeUS}l`a8i g"1лJ"|PKڝc,$+&PvꖴGBoj_t4I vqf熚(eC!b׼^SbYi1¨;2W`/7uh?4 !z@#(T 6 ^!R S#>E/Sq9z_ /G%ӈ0C9[ۼ@(٩P ,}XTOkpQȫUG6 x2e,> -?ϭQެYz/T5FL^`tީ3\#̬D:,vw[mDW)TBZ`0Ֆ`3tBQ˟kks41y `\޸cV#z`XHhwA0چFTyqӵܫ*F˪%*/>9 gS'"b'zL=N)cs*bR)W<#S 癛)K &L\9WtW!Y17i*%wJ_ 閥nWJ!p-0T`:K6B+SzlL,~J#ZLHBEe߈Eq1 ڸTD}bB;*OTCnՍl$OYQ0mz7o9NŻ|hDV[Ve֩b7YZÖHl~I)ܻJ5oOݑ%(,hZGҼmRd!/NEWutV57z;jjs^^lDǾ0-a_aL؁w44簍b^ppi&nX uƻ-݂ -cY4_g ?jGIfH %J҂[%ϩC6OzvWzoZtA$?z;ؼFT2/+0@@S<@>0bSuqw;j4S'/4sEթ(P[V^5ƊHkg/ۄw 0*֭ ajyB5TC J(_F4!m, RN ?S9 :״OfOV"յڇ1,V)S@._ #Q`K|ͨ%cj/&\: [Ft^Z"q٤Jm뙊jMarח`VCg w"~>< 8i}XT8dzQVY<p%HG/Û`rq;Nm~Ms\/Zh:(MXа^F.꜋.Ys}5`a((X0T+JS 4&~|iB!! !)$)ʰ WFY]E븎3x,˽}|dc |i-0Ws Q_GpRjy0׿tjT̎ԍD1څڍ›N:ka? 7ek_%]a;זF=9-b= &Mm0-vD'^j+/5(er^+EL F1$1KWE|fOFMKm::1`ڥfXЩM*i9 l?+Lw?-Nx͈wɳ\C0瑃f sM;iđ`$O0z*RٹB9@"k5v~.lB?ug]ed8JAj͹um.DO^^v:y;ske+,L¶vŝҼخd_5Z;q#k> MU\J{l*͟ґ3Doy"UDcu#H)BPit/ v`_Sʝ{e5mpPpy=-2[m+v6*.WۿSǔ] ^DMk,2.#ɲ\!{^I4Ԉ.~çlDcBU\b"c jvJG|H`_2rHѥ tHHBaG :Bf{'9 [jaЧe &hz6Fdy?>gۑx&l$^:^nx-'-]O 5@S Uڏy]Tu _,zWPT|BJ,ɕ}`8ߴy?p7gˢu\JO(_vOUue4+Qbi?A.jCxyRJ駥Pt㸲rTfdd$ֺFR>PaL'v2M*׵T]`W*cD*hAe#"ɆKO9JKL2J( KgK3jԉfZnL5oM(_>FOӹGi}<@w#Ndhoo4Y ̾Fٸ2YAz$W֜5Copli\ 32l;a<;S?B>zprjsm1tZc̥{s/J{c*#3ހfϡneh->Bc9SJ"չO8'8ހ `yHϤu-*` x[c')Oy\x!QS9q*;$;d'=NY ,|ܶ34qT=ka%hs䬺UX7Fl[ o1apuxf9QGk4;e ˸7荇5xB:yZdͫ,`2?_a[0~9iY Fs3g Ë9u<,yx87 1Ja,O@/gO㔛94 |.]16'^@1'p:XtwL,jVQv@wl{έ̱\?R^UV\GI+9D03oyd[R<""" .2}"!<4tH~(-r25DH@l"K濣,/S}"+~wF}V dRz,:w&?C~FqJ}JݢJirjzEgU#p]ZF%+[PjewVjlW7wR/*C%%jGx @EFH)&0_Օ|Xu DRNXA\0JSH307͛73 CWc+U#r# aQOL4Eљ?s~{sIy?y>ҒLָKd-ޣJ1v*fH 6hz+~BO:IQqZUՍP[UD#BM >$ z|?^!J0W8N WzXfщ@'h< %sdR۔e[$z,Z2H5[&Ht L UO 췯+52j&P6uRɮ! a+rk!o4 `ܗP)f%VQTF(Z]s,TR|O)O?ho# ]6yл)OU,F٠E})gsٴGyҘp/kw~˖I'Y;TdgYU'I8@F* 8 $I+A2((+y8OϋWȗE {բbW"@}@C׌teYgvֈHofE`eagbN_4!/e%O;mhtWv6[iyFy4ʔat V] au #QYm3rM/q{~tjD 7fiɷ  . =[n`4qShBrx_5wԐ %nQ~x'G[ `+qb]Q2Ըi=UGn~ڋJ(Aݪd E7Kz +M]!} jnh-Cզ_魺a٭Dfrj6$-4nUZF)Zpux'@]U/ٳۿ3Ug`iU}ڰULWu+SU[;uXJPvOŀ{$KF,qQruH.}imfZh~atMBb0*iWC䶧jZmn[nKfi c+.&oV.&ʭ{5_s9dmIA. *s5: 1Ů m!|fl'6#N Z>\oMkCZ8)*bEE@(27{I" $!0a=+vUZŁ`-xEJUǺ ~~7TSsV6i1=2J眆Jh@ Uu;7!0 ߽\醮%-;=.e/T7D$v{.ʫ|ZѮmcDֲ+-Cu_{>1H1]"D^nR ٺ:E3[h9 7TJOW+3 vœLimc @6'[c`Ǧ8v!bR{1_ӵuoPE2\@;4"mO m{ ߺE1dA}C=WB}[3']\PJG5VmnYG Xyahd'J[U~ vWۅWo]WnGnR9H7ѨAu 1vZm]lUrTVA sj6lhm,My4A*0vJR? Ĵ>2C!*#q0MJ!:ŏCR|dFa?2݂ch3dBzSIt?%LmF[AxYGҏ0m;GY1űh%[sጒ@9 q_8G>r Wn)jodEzC.qJviN&If8bg v|sd%:uTf&L0~p.(RU ; _)w%$/ t# ~#u`u[w.qsY_-*'̳ɩk/)2* i9$7fUzflc9}],툏WYCIkS-ty7>T! 26Kݲ m&cӣh' ..+upC6&@j5tdP0=I˂Ė C{޶$tR:(ϭuOR4$=jluq1?פ9Si|cqF!_z^SK}`d%DT wV>;<'V=(5H%jWMV#9YD2֓p~~J }D]gNSsjJmn->,vg&SLl#>^i8ʞ%4'RJDhRN0hBA0(r0K+aMY|"EGE_R^v4/?m[˨yN`K/5[71[Gؒ' '铯RGhqꭁ]>iIX 5'\GB ćd^ux+[^%e ֪pxE  6%!Itި@Ҿ#% :*h$r7שׁ55׈Ց'I+6*ЮwȰ%U#zD+Jt BaUؕ 6}uOr7dP Cu}FEua7RV"KST20 EN{^lkƕ$vW(,F7b ˢÞOy<"_).kh[n 9W?gڈ7yș*ӼuA@ OpIRrP($e[iVYR n#(aFq&mq3%\g?%ӆM5XD3b$ʁW ƿ5&͔D4®KcᏊ . 1Zo ^`~¿`6z q aXǰ)Ӽ܄'84 n"Db.yC<K d},{*h ڸh>wMv^ c8Iƻ(~j? eoyl/Dl5Żרpy1ܣܵ^004{ .%CA22dWuQ>okL<5.ſȠiffh7S-|^TjX[wCY*sG^1Ve֗+˃L3 /2y{+.;CtJ } ->٫y6q< WxA_PZ? Q y1>yK\.!OqM 0Cl];Sk)=RZ@[ɷ5JBeǐ$Ni"0 -úR4H~9.☫|Dϸah-)r~"eoMK%4 _7"‘e QD~0T.>"x*O>酧.Ey+HVy55RWsEk*PxEGB;(J X(8hiqmh^ 0`}_APWDLZ‹]<4zG֦`oyZR|u^gCF#nr)Va5ƪw9njyIt xI1bIy>}-AگOShKFx6xqqQ 3SU\ka椚̩Di~ ?{>J3mtߐZt]YNju]ɒQYlZZsNѴѷW>Sݥ0Bj+7q҄fU7m :8^;#eտ+*,_CY3MSU*LX.jQȖg_IWJ5a"9R'C\y׳qH)VU-Z.\+Ѥ/aen/|F[?SPkr" ^Y>VH9 &yaIxQfd}+] U.o.=q-y][viRgk*`/pLBu+A@[)&PYQ?im/K,Y*gu(i2`؀V"fJSs=RU@7+>dْsmY)w=U?ο3D qjv83׽} 1r@vy:{Eͩԡ.޸,珈~CH{ksv_l毁@"lOR."0Fl]]C˧Mfi nq˶Q{56ef e l[IuY_(i&;to 5kZ/ jjp~Ch⨿䦿iRs!G-֠5 &wa7WAƫXUr8+}E)oVӃIÌ}qZlh<gw A?=$6-ޡ|,)!<*ǘ*z!8߀ϸuPpD|Ŝe=sm4'ҢؽYaPOZ(vj?VGgxI=V-̹uMCJH_-C]B~2A\8*E8PTΔTo 9/whaߣby\'F,Ռo%wU/ժnM*T Ƌ{5NJԢT9L;y _fXD\uַA:x")V%V/*]1# )ԋ@X"SVӅ4u.f?Uչk%Nj;c~?]Pۺ˄WҌ=V듍1 E ֻqd{q׉; NYHdfttc #&vPtQjd1o ­R)ʽ@}<7 &8wyybH04͂@>o` ~M`Oi#T2"-!NSn\ z$SC%Q%;OzcT)!M.wf.Po1U=Bl1F#F0HD\u̞rڜ*ujQO5u8E$7:"І(UuANgulWYE*Z"cT\kTxlx)$8(YBIY`[}.Bb T$=U8Oŧ yP-x$]0_ j(sOH|/=wKR` ptl>f*ӡuU<=Ts(&zpKA?sLo`N0Mq+~*m-~F7^5惬H]${|-Ҷ9Y&=X'Vu+^ϖEm Y/0X cAdPc_X VRx6b|C6^FeC]o-F?f7Q3V>͝yFsy]ݯMF͊k^NնI#FZ.7ƆQfeϫCJn;AjB JFw mԗ6t(I5beElXQ͌ i,)6QS 1zJezVBf ۹ʹ/ HQ89SnE%o-4NJ``,)~utyQN]vحp+e"xN6y*,7$'x\CQL[8.d@}CɏE)1D?@晹b$?7 YM N| _Td'wa}0Z<9|3閗3~o=Y>l0Wb=P1jmE XR[louv:.C=;.a.BřS[nWJ3ǟN1='\Xr8۲:KXj6e g΀ap%z"K1.c1ɇzɭGTRiVBe-)K@iͬ!u@_`&2q up%P SЧ|NWP !o-t_ nyV|ؤ賐e`HʏE=>\Tǀ|cҎkIST!%Gu,%[IR'+#T}m3\/df)`n2#\M(CQd6flqGv첵).Z&wITe{JQܕQE\m`p`Ҵ\z[v7OVo9ݜQ}$SSFMWdnyuя: *o[3 O FRJ0ոl+L+&oE+d- @?^fEkoo\fyJ8zΰXmi  -Nw}OYpz&@>gݪHc. ]7Mz#fe"g\a@\qyºJc\3ܔ r'WQVE D|PLs\h_h#9Z-TdL>˼!WS/bniA3.1Fx@Ǡ3UNN^nPOZdtvWO&-8ךshveSȉ`wPU_cař=շ}m`<<$+UV66do88{ηzkG}ڻ<<7\jvg!5M!w&GmpfSgO3x? wZsLRq/~lK]QV:om<Q' R]AMXyu ^ȩ $}! 9LHaH8hʡrTtD-*fY]]wuu[bgg޼ߛ"ȹ I7HR7HBHudt *Ჲ=eJtj| #TI/W?{ΝO^'`v'$^E=7ITF2˵7-^'Z"[x ;[U7,QyWrr9E6cy'I gIRm2ZQ {0K,^H/>>G@l`T=FZnZH ѳ$m¯鵩KA3D;w7ŏw^J<`i$M_x8wU-,/h!pbP1|*k _U;N45jX_:]$ %ͫX+é Miwzz{7`fOE5FohX}fL}k%Jq_b_A54WK'h?:lTHmm. m&"X7rV7l̨b]r+ OpK[{0EuwrfӵFajCCPktMݻVw[FR(Y-VE8 P?)p>͛5 #TtF%3 qhk ;`LVOpZۓ. j&\Cʡ <*g!r)J;ȁ&xK0N\B&Գ$bԍ7fpt(0H23ӲG1d?ź bVֆ|\[w+tjj?b7hwJCmm#b.^VBDRb8E]4J 7LGc.Xd/a&ڎ @顢zQuֈ4Tqi˽èb˕ 43~,ymoθ[0 l} TCuLBt 2ZW>Eh@+[Řy0= sU"r];û](̏{e E=ma^2'FKv~.Оm0Oj(esߺ Pk*!3IBЦs4{^|{6k\* }XYǠD=A %$hǹWǂORV UBꯪr+Ca6 Kԣe :Zڿu6&?W&k).]%],lb7MX][H"}WL)RIrfr?AƁY&I~_IB${XlZXE&|w#؆`_vߢfu3fm89?9 ̟NՎ`jz1*.@爎܋`oْJ_+-4α6@/DWEjE}HRDl;Y+ z/1Dѓ(z)oι&;.4aZ#gsbZ+XWi;<~n"( M'b6!G lP<^\nM8--aG+dyXP^s:0q \p3bWu.,R&rm#қs)lej(^ ,=/FV6fj;ex%Dk%!FW@ao2QTvs 5h0B{UHiGCOzL'pbIq+'_1Lv QA%$[H~}{1fKٲ:HmWS ëd}2w7 j< O7i2G;SWݒ!@YsZ~*PƐ6xQܡ/9i7cGHVf3R>K2jZxH"Z")vHD} @} YJ64T(P_(*C]miSJqOZgA(ny8}wν37;?߇*x"D6HaeZ 5K e tE=H\ƒW8 72ym]Ly 1N<8͍@:> >6pӹ$.7$C$pA)hJewT*FmKg-lm*{{v\ܲsJa>3_*ݑہ>V5|WG_>RR_YL!RFjz S5fځO2< `}I\:XiZkRH*4[(xX$u|I9̺TkVzl_׼gC%*wXR nY)N.9+wZ[E9ľWJ%wp`Nj[.b|JOsdW,R~#* ĽyFdwCp*L(8OelL˞)A vfFʹ.Knd~A򥾺]Di(i]YʯJߟ?>w[侾7KK6w"!eDp5V* 3VEa{:KoEDcɾJ#oOU44lTjFk,>{S?ýSk>Su=|j}T SU.nk.mcŮ)RxbT<TV*yÙ<+`RC;S^0-itp<ȗ2IZ_0ȡVVKHWol9=fd jb%}DCy{sI*{ZL1r`n}+D_*Uz3}i779_kjxL+u ;FxL.mmQ`sKzK#>&ޗxiBV^\s3_XX_رC+ҭj|S kϽ|j|[X ΆBL.?\DCqߢ7nO(M&JOiݖw0IJLM,NCOYPoQRSTUVX Y#Z:[Q\f]x^_`abcdfgh#i3jBkRl^mgnqozpqrstuvwxyz{|}~ˀɁǂф{pdXL@3& ֜ȝ|jWE3 תū}kYG6$ڷȸ~kYG5"ŵƣǑ~lYD.оѧҐyaI1ڲۘ}bG,{W3qHvU3sIa)\ Z,      !"#$%&'()*+,-./0123456789:;~<|=|>|?}@ABCDEFGHIJKLMNOPQRSTUVWXYZ[\]^_`acdeefghijklmnopqrstuvwxyz{|z}o~dXMA5)ۈʉq`N=, ٖɗmZH6%ؤʥwog`ZTOLIFEDEFHJNRW]cjr{ĄŊƐǖȝɥʭ˶̿*7DQ^kyކߔ ,8CNYcjnoldVD/h 2 R e r xzzzyuph^RE7)4=@?:4 ,!#"#$$%&'()*+,-./|0p1d2Y3M4A566+7!89 ::;<=>?@ABCDEFGHIJKLMNOPQRSTUVWXYZ[\]^_`abcdefghijklmnopqrstuvwxyz{||}v~oiaZQH>5+! ؎͏Ðxpjc^YURPOOPRUY_fnx̰߱ 8Ql»!Ceª9^ɂʦ2TtҔӲ6Lat݇ޘߧoX\[VL=*b/fMq T p_L7! }tfUA, !"#$%z&d'N(9)%**+,-./01y2g3U4D526"7889:;<=>?@}AoBbCUDIE~% ہ‚rW; ϊ}bG-ޒēx`G/Ԝq_O?0"۬խЮ˯ǰı²µŶȷ͸ӹۺ 0@RfzƏǦȾ *GcЀџҿ'LsٛFsM6+1MZ:{OX͙~ʹ~y~eL~j~Qc=9~|4~cl@~]̳~nf~C~لOiZ/gP8v}6q}0}>ϲ:}i^},~ ׉_LpK-~~,*~&E()D9vyowy=TS3wI!D)J%OBvwN64;>FVWm S^Di*bPkpة?%"1#!ϼK`L<n-e2*+) X䥂C@v2l Q?(=0q MzǃIz7MEY; Y@K (-\U&>rI^2IMe;Ya"VN,S;o_%sD;fƎ.R?l ;0Dq>8zDKG)3o+&<4@n͗0EO94#ҐnW9 b_7}B2yːv/ąJH삻Ȧp$ȫވy;Æǘfo虔F¨LsI,KhW2!AjHE^τ _wdlXggΩr!jU)[%B\DCfp <_\?k,.wȲirJRݐ=>0+cvZ{HllLVAc۠ ^{6oCҏSمbȏ:sz 7jP@Q;[wg|z30Uq`!P-~|X3+z2lIђ:_p-FOJ*Yr(".O'qäfrCRJ'dc~h!€?`}WzBd;hѲGϲmT SAij9< ߨ%@`8xLTqė=,Mk $hJdx_r̰gʱhtG,KytomVK0X?R=Џ ]ٛa`sʠ7g&Grŀ?>r&z`b>&z%sxbw&{~څ]"WR%c"zD zA rs!֝=jcf]rmANJl$ے#ؑ >wTfGFF699<׵.'SZ*˺#-Jl.ZZx%m*| o 2ӝ_TWK4eRsu33'jRFBWl| Fgml0L1, y+Hu2f;[T0BE{:qntoT]okI, LgV_R:Kϋ0dP?= vE̷փ(M4m\Tk׉o,H=Zw/EI-LQ[ 8F/g֖'$?[u~fghXjݚ- VImKՀ,%ibQ*e97WKMYiHtXTBUDw-49#iԗ/r]hGވ/ lD2 h‘%TTT*Fdw">GY?"[f r5ʊ4`TAo4H5rWS8Xy;$Yr'q vUPV&4m/5LJE:S7Hvy.. kPXAl` ,e: E$@BKr.!{A$A,CY[EA;| TJkU>41aƜdcT.Us R&BchR) Pd;ʟHbl?1;_:i^mMh9Ӝ+,x+(‡j3=P6u>a}&b (0=.À<2&m%u9_~zL!S`(6͟>թVlW䨸m5ypg!2< PR%wC>ubvbF.0UK$K;؂P,!rA5%\v" [2gwdxJ:_'Eښ_+^Cژ I! v,V72UJLNITUKɎIy/R+=+(֨v6!M @PB%R--3|4-)#ͯ w.ܘ<;b#;*>$eG >3"و~AZ$xOUx f𜓜x;٥Q h X(Zx=`dš 8b†id, ϐ!enZ b /޲І2P0~ +1baktT ?g)˧9 С`.ޓ`>'4\DRdPaxԗ?i|9,t Ĵq]"m-9OD'Ex>#Bz6Nk%tm6BDzVQGq,2O: y{iHcy[]vaZT5 ȨR 345N@qG!fYXr{3^M7HX1ey87ҙ;NP9tn/D=}*I:2s̋%G{7abTBm6ۺ4JZmI׶Fהz\FD*rEyք ̣V-8ˉi#7XmZLW:2 $Iⷱd`U+z3 8"}Y\E^\Qܵ)<&uZ!FM)V"ڟ}&à/ ď 5 O546PW눤0 fGlEbdc 'ƪrӬ[{K("M/y%0=zFBx}{w6{Y50%,40R}ԓvTp>K@fR$7HU( /10f<,1BS>٨RI3#&&pa5j19#yTH9cI[էjU̟~? +7NzM`k|-kqJ}(Ҙ2SaӼGi ; b:`uǤayU}T 2Ftm̔%OpuDU0m~L-_:qWg0~huw-] NVrP =<]x;Y1iw@8,n\(zqb !$zB&5dn61Q& & CuЎy#c%$7]w'z\0Lk{8 ;fGS Fx¬P~Km%t3MccM(bCB$ _ J,@՜ %ӸZ;.6B)PT~~:_tHNITScΤ5_3bO6-[o 7$cn:zNqnE2~7\NT' "[fTT^2F&+c5r~ԕ(jl 48mWDC]X#<n_ T 45 C0 V~ m&AGA7w@w;Q8Q ?d9#1yʕq_eS]y|d*&6Q30J(WG>HN vAg+[o:y1ډGmUV'pJ{"M@3X|*oƙޞ%sfJ<ߔ[-0R'G i++qNPF\&XT~ykPx>–~u2LX'P MOW rة Z?qU\+w>-q}y/sRQQJ@737Ka[t̷E8X,Tp!PVK$`Κ׵bu~*LlBz-f{i8DbMp/ŲF_<`w[Uq. Y!'i7L' Rz$v]c-ީ%HY~ٕ 鞀ws{)Wa˹ԑ`{[z ϡZ& z - U@uBP.8jz B{GtϤ1ޕq# ^o2N*`DZm錞c@QY@Oy`ŕ^ )H??s %J@f-H%{#}řPKn@u5w:=YX9(5#p 9#Av(~-"]Qb'䠡ya '£ +vO@%7_*Z-r*~z Ց4!wBpG-q.a+c"wmqk=WfB +k^0>npu5㞃= m]0o-1:ǒ~%ui;pVO/a3;0oKܼL6Ed@ZU%{ ^ ͰyOVNHLmu?uMBEQ1\IُOui@L7Nk\dd[i|lRܰ3"rW^  19~(VZQjsfb5~Nl, $LAE \Yv3k"*Ie.gj4uDk"*T~~g^ ~<|1cPx7kF84K(/AI\%HG;'6`kK ZJAFqKq$5GT#.a;1 p't.t-SSUn;QY(sў*M8= BHZ# GcDS{d',Utl=,}*vcr+](_1rØ@?A[KDlv'”o>=ԏ[?Q ôn!ܘeoiB]u3PzP'ߧ%44Qw L7@?;gSVjgohop7syR\7V%xL| 3n|2Q|-GotuV֘Gk}fd'̐yQ/;^+b#&~ي2(ɚpTֆ)$Dru:5zj,|~0T\~>*,6Y ]7E9!7;au*8Y?Ң#WfiA~\mB\$OwDhE16:_JqBR%*X3 !O:`Iok2+}Y'1%Y GPMJ{rK w_ L&N NyA'ճmﺾo4gz"v;L je %Ɯ{NS6U'*@djNcvo^=Bi 795l€Aⶫ627ICkyV_}B.I=YR2U^c~o\Ƙa3Ƹ2@eU*Tlmcӱ~ xnNU)o`Iχa]PFŚVTC&ϣ࿋Y=d]/..FBXs+$=}buM>RWm6Ŗ6ᢐFX 5x{v*j;zv<_~AVUJϐ^IjQxシuQo=lK_ՑEkZ\4sqU7vOa J?Q)4C^\k[{3y~M|J'g4Ay,$0( jHl:Q"V҉1X&e s)MZ(W |Ϲ\88&tcpҔa͔ CC GU$^fb|8u̸&A֍9ke7;㥦koAvՏ0o5y'M3q"y$[Y@SgÓ=ݎP1)L \!B;U!)/C$N$A³ueuU},3Y'/Jc .8_[ON-<"NawGm_+yj~P]ſ^\y X,r-|㒒ܳ<L^T},^eDR,nkqց%|r,!gJx=~p{"\eeEN;Þ=${q@Q_\?/иLe>u#Mp'Yn_e<q㼅Ra8pLB=(YK[l`BKB#4;c;HS^OA>Ʉx\+0lkOԼ`Fcfup.wlCnKJIi]&fXPAn1کFTKBoI!ӮZ f)~Xhy9 ݨOC5&|T2ӲnSLB5eD0:yP;(w9mΪnWhKu{`wk kH>*ڲ1 wp5Q݌$;LvvJ1f3n*Tg@oO#9|}?V0M5.ۀz{" NK?C_$ P&B̆e>(qIu`|ob|_0l2WꂝsCܴLTIa?f(/+PIwB WhgšH EiŮ(G6 "  "(H2̙dfr $xZEP>ţC~EF:}< \{ % rH6N$(߫Nᷘ_%1]2:$o-8ȥ I-qt;'kTjJW^}kfQUr\ulNkHn᫂H*Wd6M2 *{`V%VRoJJ`+"yO|s86Vy8 :+;9ɨ=.qqѝ=ɥ^ӏwldG;fH^2`zBȳ ŞO*{M2MoR0i:T~%$9ED~cj<}${.-+P]c=Vzpwz\S;!?C:GFIױqYŞ ݇>;]mS)yrEz_n˕aI"l|sGvmߵ_7e]֭>ГU)i:D΂G}V W5*{f? ($p\)9D$ZYr|(4D܁OHʳ ;ܫv۱jxLr_r ;Wi nV|Rudܦ;@YNl-QnJȲc/14C:'K&̕BOJ{ߴzfsW|F-q2 ?}Y[pXdY<\v+M{ir8~LJޯ vlL: ?@o[g`}>?UrǛI2Lk.}GpI8QRV%܂L0/PUE ?ɹTcۼfHs^QMC!)$ ; ej uIy W6#LMi9ĦͱP*HʘFg]mߝn+|X$Z6K'OQJq m(B~ljSuZ ťbhWP"z@UVJ΂\,<\HA 5Oaf΍C75O Uݮx7F>QL~:ʥ#][eTS2%c Æ~EWg9i%3W4ފ:}޼0_X|-ƣµVu8H{YF"qĔ-F95E!L/3zLw@"FRmOQ&[#ZO/xˤr~9T00bܬ 4Pߋb>_nMFY%MOaN$ʡ˖~ &($~>tBM%^i3ϐEf8UB '`-icIaͨ+ دR=ZȾŁ=5U#5HR>njky/s6H؃E oLyCG/?QE%FvMMz)=ZB.ϡƋ/•3O85&YKլ(ST eҝZVx'xaV4Ë*H]z~h~ i0d,K8CZy{jCF')b|xNJ>V{0e#|SE1b狛*_R"37Boξ(p3_<ݥ%-tɫBetƓpx HuRuɵ)H?mf@Iz͂qrgM_D|Ce ӯ_wCՄYK/Ԩ 佨/Y0y̸7.]*ѳa !d[m9#{-;W[ U$mb?ci3ؘsq6ĂT t֠} dlv{Fyt/ټt̰KQ8 N"4ʻc'׸Ns6I ][#?wsb,4U_ f)Eď* uä6Go76ɵ{'CGa+RUA=@5_rgs1OUG*ʚO&Q͡4%nlc=%Z vY Zeਝ4? eC` _wvĦ10KB/*Brv4όwM 0r `$CܝGa6;g-N_&ɰ.` `0M/s\PMf`p3 $A7 i c(y jӍ 5!UiMSD-rBFL&^:OF-T4w T3c q]2Rd/3U\;?Up=@b TYRJ3O)*+sWu.[L6ǼA. 귒hoN_=C|HW Gz}w\2h{?Ur_ס,[<4DmD〷C/Fl Mr_򑹾g"P\TMIiDw$=` IӐ }6.jYx^h}]"]l 8"ӽ΃ǐL"Hڝk:^֖Tm.^@1~qxTlU#U75:LE|4&W25exz*̖̆;M0do^lpmaIS7kD#'͊$"lL?bADINmEh 8Ԍ*"vұE݌5Z5 `z~x[MN&a|b(ǁ$ch |cq)M_Ɔw>bSО$  Dpz!G@o3a]PnN2);K4 U"p+q 7bLay$04iCc9(6>E3a{ R䏡0`?s07y9'`Lq`ScLr&MP.ڽ,_ru/F=܏=1ltŜ 9>1lם KX_t+ =#ثL uuWK̹ u)F@jR_$YuBśGbQl+$,o8qlg!) n2QήU>Ytw(^'Y! %GU9, &>YcwU Mj"Zo6VWF9=al mynqA/2AI̐i qAN?!9NxlbO{eiYQ̶>SZ .&sbj?1_ǡPkٟx`дY!n6fVJ?ffon06l)7BuyMAѢ&m>>Nj#4J%&|E]ۊ:i2g0io*6zXh +҂3;1"2ҍ+O?KjaY|nMHpA/LsI5cu*ΐDx!W {|mpq%qehrYbBt M7uA- w%5,x+ z!Ί}|%wpȩxeXx|Yy$M}yAz5{+=}5"6~{άq~p^Q~Md~*XŸ~,LU~S@~5 ~+f2T"P{pUIpf P[AE;Z1ٓ0U)Fj"0΂op~7f ![BPY_EE;T\1撠C)k"djpmfr=[M,1P\ǑES;`Ћ1')}"Ρmfni=pkqr^mtolVurX wtDyw'0|Yz>̾jqźjlr`ntpu0rnvgkbtgwWIv~yCtxz0b{x|bh|~j|l|^n|~pp|j\s}AVtu[}Bw}0z~l;fׇ i 9kDmh5})oviNqꂿUtXBEv=/yVǧeP{qgi卞|l{nohLp(TsuSAv@Z/ryX_dִ2f}}hƖMk/zmtLgdojT3rxAKuI/8xσ[c&5e[}gܞrQj.xylfoDSr d@u/x\ębp vdܫg%iwy3kyenbSq@to.wUad`RfWh-xkkemn)Rq\@?t@.wZtf4uhvjxxm0xyosekz.qR|{itP?|w-~zK'rp{sqԜu#svFtgwwtudxw*Qz%x?E{zb-}|Xpzr'zssj{@(t{vxv|cwy|Qy }>z}-R|~H(oYpq݃^s=uPt;bvSPPx <>Ay-|0m{opzrt?s^auQOw+T=y>,{¹luSmoou{psGrlatqOvk?=txj,{ @k mܖnlprxqؔM`WsNuȌ=&x,zj׫4lgmomqq0_s*9N uI_|2so|u]}@vLO}xT;"~z-*|Ly(x*yyr z$y gWTaˢĮkTd@D\dPPp-HG&]30;sCg( 1DE*n6ܵaz*&>P3ĸg| ,X񦁓`S$>BG DǕu#i#܌-`xJ!wم:(`[HWeQ2UFD`|:Cd2~TvkdEeUb2̽p ʠ~[@QdF!7H$ #dLt!BOK*G-iCrB.UlmO> ,B2W<+367ߛ@ )۠&KO 0ޏO igm82=D 4FB[!AIb4~Z *fz\OtF&ӝN&3xF[Hjz&3n14bM zB! |+ /hw{V\lsTjg?қ۟u 깮D}û.5ʺ(wM ұ=Ljeo(u\ yPXƢ8p2232"uh0 ;(3-ybݷ3WdsF@w ,8#!H*9)iF^ P7Dg3I33D_)JQNdOm2ta':=J.۱ s`d+uu- ǵiȵ\L kw/i&G1|91:H^gW@-Eif?QF?/KvřMkz݈uN0:ӎ3BJ]PU@׊VVzDPC9>RTl{=EY^ScyjN96b~mwj[ Zl'd}[YގM:tU9WI-#d=sѣS IKuƷ6i/JO{s{c@6oPU,'9cV~M6IQ1WwoT+mlF0\Od?oi4M4MC%HfM[r0p[p|R’/Ld/_c8]׍ YpFKM(Ewo@jjI0/kad[H>|/ѓL |00SVRׂV2Cæav4x,'L82'7&n&CĿf]9-f]i{Ta4EeNٟή"V_ǔ3tf65ҷ, jP6Ex)ͻUSu@6M6dFVSˬGŦwƠuy@>.TȆVOdj?#驺sycA)w,zl<ـB*7ij,\P#;}}~r4fxO"ZhNMBe@(78,iA#FaN}qǖ*lf Zۋ M2HB-7߅,yY#p9|qeےNYƐ*M}"A튘6؈U,ۅ#||(qW,esY!MANJje6Ç,}#5tPcjOf=_`rhTkHm=op2s(Hv "zbtu5k#jl_-$nnSjpDHrB=tytn2ݑOv)yL |triIs ^ٟtSuSHt#v=_.x02y)B{! }~st(o.w]^`cCcHlVf+;t)i0aldOȯ>tsw[-wnw\-_AMb0ke#SsShA!a7kO|o>#r -v0[Dn^aaShdL%rg{`j哟On-=rfv-vm3Zp]­ `܄cr f؝C` jRNnb=q-vBw~o`^q&ccrfBti quk_wInN1yq<{u8,-}pymjynlpptnRrp/qsr_;utMwv2>@?nC)HKс#Eu$%`^>[ (?`~^x0_+OËv&"YD>s5x']~-if~>NF" P^OG# ǖ0<7ӆ7 :sXL!kݱrx{6Rt"+@q*7k1U誘Y}(~\H`J䞂\ 52[{F;Onݦ *C{2Hpuw0D(MHOB$vKѻX{'V' 5c sh]T4I DGãTD(2BNlz9eB_ ݫ.#JUbGɰ Pc36߅!3?o/˼ 4Ta1l-vKWZApɾ<>\Щހka8Z5$GdW#{{ߢ! e8l&Vlu4ʚ@ԸQWJ"쎛)9(6gf y'1?JL)b쭢l]4LkۘPpuﲹ)nCA Ŷ+2dEH'Hm&Y3uѷkѽӭ1n]_Z<ڮRvӛpjm9G݂#j}dA-uڠ 0\C"dhK>مٸ:IFq\BVhF'$[I&3BtK\ D'`;I ["%#N\I |?a8+ş3"-Aש_ZZKO%u6`X{cͯw1 $+OM{'E],jz6+~ Qk a=_/E qbVk&S7fg\"&]KOÑ: %ijeB>%j:l=T1e~/ߪg I0^YV)<^ϑ% զՏQS-WGpaθD8ߠ9D֑ՃXM' UJ]I"mteuuE)-3`Ҍ SoO6Ju@$ZZǚ;oam>݄92)@m{>-V|WU>r$Ӳ]qّ¸zEYuɔ>GT@蚩\'}њG9mp.d.@L4c&,r;b ӂdlt3ݦ]Q<b-w Nk k bK%H@ j"W4sf|Aa{8c%J@bW\E':Ehsř=}9fǹTW !3ߔ% פԘ]YzĀ&XIkWdPيb]9gbIi $ O1wu_)xS$P)m/UI .mpsf5Uwl}oyh 4;=DUIKSDSjj:?2*w0P4o+G4O6jeu HW)ϛ=ݮȆs51 okaIӽ֒Wo0%>#}?V5N_r}%7 Լ{!`D}K_4 !Q\HҽzȔHN>uA-^Ჰbg%+k58W #wi+q0khcuTT[`5Z[`J &-v**cs0:-7o3G(Z!d  z Q}vx'E}aQ#*'viƷ|'in˵Y;eR{E1vikYT24o/;K |O c Rr_T'UtKyγzaL= zs#k)|OĀ܇:axim&&^cŽoIѓ` W82K/ױϬ˽^ipuO:JD:WtG<8YJ] ՄyiZP-|xm4rQe`dZH ;4SX1̚`wpu>7 H2%Cd>zES?+&e{\Q>+) ^T9ZPFV+@l@ A B r3L2$$x *,^-ڷ[]<**RInpdk ŻΫ :C>KXi<_TTՖqcs.JmZEŒ:^΄hsVIbm8tSX&^ a*Ɋn^m=A2s^mICca|k`K{"Y١:nf,ڱW x_n~ !f睥# Aɧo(u gįVg攷E)?n/ؠbdSu3QQIB`\C!d P,2QC[Pһn`RXYU^',|Y5G4-},V{:T5zGFdx|4Zٲ u'ʦ"Ww[f^'0Xcx2rKJJDJmB|CÁ=55oc/hNL9'0jI. =$!_3s^>pX0]ScԹ`gi9Q?+,O|ekkC)6bf!),MjQZF_Y[-ۈfiv&mH!`5oIxudP#F P&h_2nnmMsC?wOt[Pk+jnA ǐHځY*zל`L﵋TL01|w:44o(%j̨5YJ_|fyl00DO+/.5T"$8[g)T`MH?Ɠ\fިÕyL/\Zj@Ν(Wڢud>P"Yd'$$ʗVJ+W>pG[^Gڻ2|M 5kci{ZJbILFPCR7<]'wKÍQXb* $f»~ ^̈́:)]}pA(+RXzE;b1t!9ݠBj` d> !L7gh%7nׅ _Qg1R2Ǽĸ:@n\KX)'WIC0hݤ!XL}4l5 Vh2,?bLb#(sÀytk]:ibP_"2S&F ߆*:/~5l6fݻ Ӡv(l1u;8qi7mL[@Wxlg Y<#nMDyYZOEX;/C<_IfGuROM++c7S 4ƊaZԃu Mߊ]>]o/m^&=Nh̕.g*>d_$ ]koj-]wz`g`@XRSZ^6uV^og~XQ 濮a%{s Tp4{HLydW)YU&R?FD/'gH7yOG S0᪄g :po)-.XF:e*diG{.㯙nwn.tY<"`7dsSC!x$g:SX9Y%r_']4K . q cYv.㏢Mrm*ADbW냊M1Dqby9mT'buq7Or }yXK8`微.;~1K}wҭrB;ҏޒ &6 Rr*?j䆑lugICkM|vhZYHn8VzQ3N??֫zGP5|No(RGJ[5&Hs)qq}^&2n:zǰkFmP03;7Nsi+ZiӍ ^zs7Tm , zb@p22{96ʄ/= 4)c x t&83B-(;^SedSy7yG^H@Es7<AQ|h[\jeZҎy1|i-M']|k!3h{&m5&[KiK%}UEk̀u hT[*FkkOZ e ev]G ؼ;GLW[d;oo3xY{OEk[@|l2섐^򒼗F6a 9uUQ[Em'*uWAw:^WfAw:Rc$DZ9-N7~c ?;A34VfO 5*DvUe_Rqr_pMv]{қ[;f4( c5ڑGdxEjO-n | g8 KٶŲ]{r3J(?ұqlu;S7qWA}ǰ=o nxg|GCTpTaH͗O0U`llڤClt0jh~pڱY_,x',IUjn\[M zDBb<Ô]T7S0Co}2%sF͘MQ ś!7fSѕ&.!mFk(+O Oȏ@ W1fG 0JZ-#=qb>@@gIxFz|޴\E=Yg6atҺ*SY5T9vh  %2{}n}I90v zRf8kOʼjVo:*xH3_ 6WWx4\;5juK::i7rʶYAd~X:J1<;e (;MsrlڪU[y5vw(k -OlHWeG㐣݆L9sŠFp6i&xИp0C2}TxmCH#ѽZyڇm{+EAaWdVSy%ې8bש"SLL14$Bs&Bj&d@Y?O+82}-D^ݒD(PR{Ѭ.s!$4Pڣo\i(#u"D8 :]C>6ڒ׶*m@1GQm lìOrusg# tk-ۤ^G) yۂ2b+PgDWB;T+4Qv{9輵;!f6~/ė|@r~EM$,<`2+oMҿ$ȵk뤆)<$\nnu|LX+z-]:r"Xꗺ.KW;–YFC :Aǔ+IU u+U>.+͋;SN@] LUXKx6 ͑8=*U4^qݗۥ>S韒+Ż eLsf v?m!'粈Yv0zْ2GwT1e{BHM, &fr(y)% P Ehl% $EVDĶt o \~6-s//E 2<뤪t :mbpVn(Q7:ziZNl*3miИ` snX U\Пbi0^Kc=!!{pwpyKH&Ș/UDg#M@1&yf_sIrŔ\ Bc7HexXltbu!hI &) ֩ršbps;Cu GFq~~c6RbO'l"<͖z [T0}5y V|EWrф\2aAA0 /ɷW&aA AK]מ q\kPU"Jѻ?W{j#'rG^$U)~VHDTup7eÊ⚊R"I^w0^+mOXiMi-T5ȝ'N]~{e r5Ճ-wA-VYF~UgBOJt8y0.{KO(vlJ uS0փyk^?6Wc+ Cl]Eko%ݼ脦g}h0[[tVۃw,U^|}X?4:a<X s%هU)<@ZQ/[6 . 0A=fxIҗQl3\PBoJ]Դ\>[3?,ЛMOyIOi> '|2kxo6oy*Zo9XYifNP?1k𾠣 *_BupֲB[ 4Xφ}P73d"dٮ&<ăT>x4Y"GXF%Ngt2S 8.hpq܏#~2HleҢ(j =~n$ Y9PKC‰/q䢘&lrS1|8+ۺp5q Z(QӸAX!\$$$CsrL2$L%,*OQuOłBuUX뵊]xV~n,[|nC -bY@X?(e92"կ)fm6@>_|Xȼ L N+VJ2v&ǂga:y*=>C,꽅zqwΣaVbP$Ԇ3H* |tc^7CvfCUʆN\A X)MȊQrK{Fۏe"j%hCi24.$ҲɹDӮ?2]HMtaPZ+C9J*_r%QNH4r{W) |em}^e ٻ .v_.e'T)V4(FoUgzf0=rƣ[(hGjKҢy}%]ʟ%(y쭬0L1sR1w^NJO7 نyoxõO`i0)¿6T@JJL#״C[!)9!w+@,&TQ0GU5a 5\1(-9]s41y3yʍ/ G䇫~IĴ41_35g%@.1N§ N̡Pi'74@rz8Z? i;f cENOri@Du{A6.ѱ>1_:, Jf?/LCNN*E]٭!mq=p)ݍ cFMH?b;t% 7r~L&3>ﰞ~6slD'9?6T­ϙ^ 5; k[}gX0^hq$WKJm3qV/f̔&|}31sO[9"6ε6 9K+|dj8a&kɐ=9wUͩ?|0,lugzeU,}* e-^uGSoy77bC#Qşn[,( l^ 6!ʌ>":jbiq2$V1\$ǕwkGԣQ%[`ѐJ Ή `]+Y)u!*5(HIdaoElw17hYxЈrMyA39ScLYgBل*dlQ P/Džml)IR`i?ĞAY訌:et/ ysn琸M>dSG&HPe*p:vFӫ}9|%*CdڌTm ؍θSVkq~VQ< f CB'LH? 6ǍZWzjxA|+cshi#a43 KZr?'H:m2AĽ eЭdcM^k^Cj#,@DL2I~tHGǫJ̀e W`_qZb "pp߄CH I&d2L)xʪ*jXEtJJ]EZ_=@XY#>(UT#tgE UO4E]cDix`Ffw0b(U Y]sAvjfhw@A,bx#iu+E_Xx˼U-EW'_@ce2b1( h^EN `V[@-kbn_Pe:60lu-'\j|Dme;tHGD˪&աD!ߪ@M?B=rΕtSwo2Y!;DLž]򮆁˶Rf;˷-r0ۏ첸R}"?5#mk+3((.RxP{K$ ~?uX m(U$C[KIl9vL"F]C2q.OI61Qx 1iQZxle_)O&uZCj7$6} A~8zXmb|n^i>]fQBchJDj^ k]rou#Ih 8ЂTc1)üW+-*kxueI~PE:LR] &t-¬^*$M4-bB c鎳A9ZuKDۄT}pp;dzx0w 7 ? rlJU/3BK3hf@jm1RזD*p֓2O(Vv ndmMAO;1S`M-a6)N˛,_ l[c.Hі%Ŗش+#]lcٶ$ s~&b~In^Y6-쪸ʟ/FRa` Ei|o$Գh:)=kZv6g|V'E;R^t\"ZW YnN'⢒LiK[!6bjnf$=+ *.ӃKvIchP*%zډ,1-pGsD8DC7x&X8e!j5kL4Y &XqYLA)$]s_g^.[fx́{sHq  o݌ KFaa)1$PoגיDO̐Ńwq?0$װޮxYZN8$8 _ُ$`lcZ6ݐ?ȇY+0H5zቔkQ}Ö!~QQ2&P{BcH|7gz9^sylu^A ;RckU>)vQ 8:oVcsK68#7>^nNk_<w*>mڹ3"ΨŢl` D#ޣ7W-#hD:G"DxA4 >X( 6b-X>*'qkxOOX+{5| fP|~NEzEy?|S-2<3}=`[~#ltGPj_ _߷,cn$kaM=UlMQ"gɆ 5iЉ5M%7R%qvLSG[]]M vKsw>q| 7pL=#.[CjϨ^wUOlTvCe]j20uuFfձʪ:AƆ"E*S'_ !Z:Qpt47rv윽Ys9{<Fr׃d+G1 F~ /bm1&&x, ^ LtZnDz4g?x7o߽06m3fB|=ksΛ 4|K5~Xp%&(*,.0<664^?|X@`PsB#b$ PX<1A͹O3l.O IrOS#?UBP' BPT;} *~>22 EOL_~[ g ,v,cy]zFl(}FVύPq㫪J6A$*H$Ρ`v0;f×9zL2ٞQC|QM5xzAR+Ԕ k*xGjsH%Ť^Vaݼr~Lȡ3h5$؋#2'$ ,FP].V!foDc&2`* _'ǹ{# ݰw%{2>aQ*X SV*5r1V/\2dL9x~dE ]0 ^z[AKmILŤSK``;m\ojc{.]w{]}A][UT5䄚T9"#֑$-QJ֙ (R;7n^윆a:VVTST@e& PkLlvw6ԷU8{`>5#8-Eʦhc5Ij ɱUx(EUu=XU=ux}{tjG 4a(=Gr(nËqZTivU肝 F7 :&|ؾĮȬ8CLNlG\nt{Bvx~T2?]ъ?:B': nAS+w."nG%PBRBz^MLpz&*T@ mHh؇Dc΢&ZT_Wj 5yI5LOї5m һE/`v0;fˡp;ϙ־A}UlK8SQC#kדtYFUVErAF̾!b7E|{e wY쓌E8T@V4U4<7IIiA(R@: j:8vug*tE@EQ*r 럄B; !rIC@V@]_ӇQ5UW/)aY/-Ry%F2"  InK/i"tY{p8d|Q\Đxi'6ĩ/UUi5gԧyebLY(ke&\1q(h-Ev;wΛ6 !5kC(xH@m՝N&וy UFeaf5n\+#$,۾.wAڐ&T%_}ؗY6"s 9G&j ơR9aWLt~-m ANv$&! 2p0t{z$?5Z uTj]Ġ`9t& f,h؈!%gS$&T<6ncK /'z&bp`F*8b(@H3x!}': yo8IP&\P{C@Rt(ɓʌ*rH1𵐗&dx'McČ`$f>m|S~䃱ؕ$x0mq]Pe& i#eF6AWB~8QChiTɞ <|]z[u*nz!bg9Ԓr3lq Xr3" >4SPh=m@A8 {Ͼ+\Ǖ--F3a@4M6;ҩ'Z8JԐpjj6 DzQ0'չ=;Qv(X N#0-z#}2Ң>ƾ#Ahw8Vw5C/[r:mU5fYH7H)N6S PX'>}<5ӽe~y'NNdtOݗdjM Z̓x3YAdECM&-ڀjG ož>ْm\-u ZTS#%xG;Ѣ8]0^`#Hƺb~ںnA-9*ViTR8 `'yM>aATm#GђZVZ˪ݐETD_l }mϒdo8zPc)VdjGT *:YϪ z*MSqKP}W7K۫Ov*om;Czzqt}JeVl|eryItV2j)kb腳h ?|lIlN^mzQr}\E+ݫl([Xp1ٔZ[m@_Xi䮠pvfy?q)?GZ3=@W =T2lvsdrڰP챢ށzE     q5YTp yOCŻReb &l[Ghmb9M%>]8!p~{gkl’B42?ȩVnI6 e%2G-8o QP6ncN/J/FQ&= }-9>#, +>nƙ,Π z,>3'ЏԍI6Mo$GWdosfܐT:jGyhKڻ)k[Leٓ#ceA>Vl oiEǪ2p˪lMe.{J~IT"Cvnc53}-"ÐhI'ِ,kHM"D[YjsUZCM:fD˂+)U Naa␽Zfk@ 0,"IBLtrAlĐ  N9Vr:#Q1ha x!coDjԀE_dLqi&]8NLSNIS/)WKlƜ5==\[jTv]٨@(WKsm!fwO)iiLڤ?鑓#tɕOL=?ٯ9,o9̳t2UAP@C6-!d!@ BB6BĂQDkop94Mre9*ӍRMd0W:rB5*G1GRBd; ib"P'dh8^`B5yϕJ\ L΄*nW2b߭L)3t*E&' sdr* i@s?/=:Vh,~ߗ;{u15k}6EnA;xobhS$u,N%ɕ8j 'q/qO=`S)г ,Tרs=@o5-z$^˚Fk3(lUA?5(!4v(_uw1ff:w-}hXKvzqAOQ NϜ@:&z$B/ $Gc*8?z0;ߗ]/ZZV#sY]X&qzlKNCd P¶GFޜ=;èj!,z5ϥ+D`C^n"NJf90 2?}ɉ=yΝi*mJnL6M$_e A ($eEU Ȁӏ^9,>IoGs}YEHBWh֯յYTwL3rS1MOeS-)*d`[hh%؝jӣ͓\$|[XRK@-_JoЌ+כŋ8V"]?/&{d_$]B?,kʯ2xF5xun#s [oyDs?{how1,8 fL?CVAyE% K.?)-amU [5[ڜȺMtM0o?s}*Ϝ|-.̩ {JZVu (lIneC6%FQnj̍;\M{w 564q@p${{bKXQVx &\^fA{O򒻭m.B0b @ħ/d?4m/o y0wA6kloz=vVtbd.RC{,DŽ4]@Г zӁ4#L#y,xK|}]XÿC>A𵲇i6pD1|܎,HψP(@c ii@Rq2[eaU^FR6Jz!` {v' fQm)0}^(6Rc$5 (r~P,y9wM:(^։gDHDϡyl"0A4t!5F5bl ”#@ )ۚ+Ou`;\ mqׂZ4++'8bqu2ǬN Gt$ F7 G,)O '6bgSo/+WuQ.mlc`rj($oQM 0rIF?i#@I_S>8Z7gW-[ܫ J?&[1Ck\B"mф;[ 7qD $fØt;Sj͖%qzfg,;-^Q`-}"ҘGHv- 35Sl.J7oÉ@ 5pNgmwٱٙmu*ꊸ/#7H NH  @HB\$77!PxE.ov[O8bD>Π)Q6AY-aWjLGU-oF7k1Fj@3\=ۉ <'#Gޙ?uߎo qxeP IÉh1nzY=Wu Mզgԥ'(e]-gCGi.];^ɹ>~o[?) oOP^M!=aǠtRl69m^rU4\ O%%-,O]TB*s;?Mw+Pmv{ւC)#HܥO)ih\LC.!K'b1 HQs.w{ϟ/2Tp c6#s6"bI)i+˰exVz:;9 sYAnSKG?vOW{$a R*ը1o7l ˯WC^kh+qf7 :B|J+*u}B2#PCѦˋS%e*:g cCh܁li) `Fm5{kï 5!>s^sUXt9UJ厓7YΆ-P7 $*gz0W]yl`\:XA>s97<5'&cE=ffӕDdyix M8ZH6."4Fm Iz9)d1 ź F+)mju@a7gDfFiUcԝRڊXxi>6|XG/@@+$kaQbќ0/nMҋ]%:c!רZTxY jq4Fּ]Xyw?=5a'v:u]㌵u=,"@n9 $$!+E@AHGBBpEA."(hA P뷙ӗ}Їw oPEiԑ9qͩ[ q)Q<\Uh.gY}WS(35QEJYj)zS h/Pk<^~'?aS| A :8}F/R+|cha 4Y^HjZU7 [C1 ?w<}Aw{_Kyē]Pmp\+ؐ- TźˠRVYĐ[tX;-i(i7[9GPq4zg6@0=4kֈ\c-MANTij *A+7V |ZQ4fmld/ 5@ ݽ#]w̋Usri07mN wˌ|!WQRQIc fWlerU:Gg&{ q? n. |f0rg$u͚B869A$Vˊ:bVoi L,EUJ@!Og)Л@v4>4=A[+g $fy4"nv,9r1gJc:5J-AYL :J匞Y*ϗȭy5Zg!W6@@6,GDOMBӆF`+٘^-+*uj/iuUcnC9K)7hsz 5]Nٰ;Td~>TJ4& *ow} u?zXcΑggS+~P2u.3MV&*1Z,_e%I#\iPpYRg/PphmsY}~'kGs4Tj`ޅX~>3en؈24"y 'ʸq~tZh/5kofصOa8s߸F_$@3q˰>'n9;7^^^=1.5?jD'_X,D,Qn?t/J\p &w!ב0؋gTStZ*j| D„=bCB3WYx{ot}5[,w$ 4LBA#oaQQ\xąʈ}IHNK ȇߠ Ke's}*_};v$p;$p\,1~ ?$  ! 9~|?}SRwp^@YH{VDrqQ"Ş'VpoTU$VdDױJtzt *BM"{i1a=~oضR[ Q!q/eUV.yVH[(`IʪYL 1KWiE2c9rg0]DgQ])ܚd]ѯWiMU}:o@:vN?ćѱ@Fq?.[cT(y1oM70œh~8Jh.#lQDҭWF[3j;E#@O<~.;YKhk&qtd=rT}J+zPUX}Ψ9gTz<#8:<1)y/%O$yevUm:>Cn^!R$,@P18Qr .eFҺs&o|<#AD1@q47剜_NJ5yvAT8a@Â*2 hc^3~13JEi颸r!:Aj$U^NMrs!&xt~8ۀ>4@sWѴm)9PV-kQŸiP8SYFR4c4Kl] IC4<Q zás!{2 ЅfNxfKH~JμΟuF^4܊prfJ@г:6BRBd Am-[[ꍏm@Ch[kd+>~r`vS!CkBD+Y]d=a&JD;Dlw؛7c_so` y툈z6tk4 6֗7Z *-Kآ&%ת#qfB׆cʡ2 GMTC?.X [ZH5:Wt6譥dUEFIҬŋ(ZǗkxZ,z0= >=P~?Y9=1y~4tV$aix%A!jLsLdEԶrV!tZQ<s`i ,{߸?xQ#/Ne`%zyx+UnGz)xVY'iNCV`k"|FyT&`y'_z>#n/F\Lz2Cs/)Tb%Ӌ\8yU B+|Ȫ/: {7Ӟ޸ho;A[,8N(V'O7* xUzjޝ;Wd(aCV%l`PPyp<}捑^gՕBkQG5wa…g7pkŭYlhd˿L^b/IİK(9w} ۿy7S[Zh=(L0~l.}-ZYn@."@P gSDFd{W5d˸:n8 \o3K>^=ݻ_%%4$&8 j%| A oմĶ^Ƿî:fԌ& 6-LzH| b?ӑu[}U ^^_b6QYU82Tݘi-434o'iͩZRn ZoH͟sӹ?}W>ߪm7 b#1en ?#s"*aQ{u5k ixtJK} LjH 0}0:[gAM vtv3tљvZuծ]uC;rCDD @ !`BBHHBr;\BZPXnŋu ؇}f~/76ذQ @Bbh\Yuun^R! lQwLs6H-M{#RpRʒKʓ7k׌MrM'?gİkS!" q8@& xw3KsޖG!禼:􊑟 %X~H<齾vmWkaİu~AD (Dh>F,AC~I)o|J"&xŭԤǮ03bgF}PM}3-z[6|ǓoK@C' 룐A PtD`#c{xʢHjl80bÀ!s'<jc/q/Ӄ@ | 8- QMxFeU>iHR|/1{.K<['-<+AIgPW7 K g N H]iD/X"IYEMo( g]Ytd_6]8|pR~ =)L}Uz{@ yf4HsRA:VPRX[CYqDu*ܹr. Y%3XlsZ~=*UN^i\U^,t{gP5y - AEr(ӣAeQq>IY`<<)`?5Y^2]b+0gnϪn]T_\Vc/=˚%>x[@A#I=,-B- g Vm<Ǿ_%߭PfZewJ-۸?{5# %SryUC ݠ>Ф'XʂRlFyCrsTI0%ŭҐǞ݌!Wi KFMvWZfC?]>jqF-VTyl?d^6b#Sl0bYKO̹4KftDuE5spx!DGSvWLv|j'mmcUZգ_E&Ѕmc~0 ֑ܙyWk:nv}þv sv$4y4A֏K磻2nuJUaDG222qwQ؃RpaWPgM/ uLnmXivu:3_0%yN䍡I/ɴQ:8nj %bP,|Tv@^@q;$8ΐBOGhOtP___r:!͆i`=li_(x1ra q#Ь$ $v@mdx8$ F{8 ;("a)^STS 7 Ә>ɟAdL bc!3쨠bUom`kRS2i@1ȏlr>>^@=͚#K+ڴW+lc4`}_81CQ~u6hxF 0l? y;H !?)|$Y"3?iV徊H!fLSI̝Itx#{vMH!!M@0cr?H+e.%fNMcH͐/dLk V-I9wȫ_G 7^P6P%Ȩea-\`XL)jYFX| ך3"紒jro/&ꀣmjv;!NzA1 1+d)VasYV.o*X0N?'Tg<'TZs{ZI=yw)=?S4О\ p|*N{?(ы Q#eMeXqiJѳRSFz9XFRwOMnUzwOqKqOVgKx}E5qcu(:ʢ2 R^P)R @JHC"BE0 A\ gnև}99? ^!HyYz@-F*#1KcH9}b_Rh2/s/gf 97y7 HPa 0WRX3aA *v=A)%(j*5ybf?7 +@\MH@2 P7]APeB<*#q r|h%x\N/bz|VViè- 5(n@ ^$k $ub wkd߁zf0]1>F)\d7KheRUr:[Dx%2Q5I%euaYI+tJ^%(G-il \~NSyU0.FyaM𔋵dCPq d&؜L,QdJ)BJ)dB֋$SC wNyߧ6Ʈ6/> qJhMIlm"Y+q &WQ%+ŕm Tbs@@ӞEoܭ-~b0䤶2'rą >UepKyBBc^3XVVIqUz1 >7O;AtzB;~ICțF-LZ,8GK(^4#J]cz9@YA}O_\;nzGPLh%%lƲ.I*\Y(ؼX%mK$ik ^-!Bs@i ?lu?ov9цwD%HS2{31| n)c!5*!/Q)Hj&I A |sPsp3F>M/Gl|tĺκ>mw3ȭUNӑ98żbt,Bw2IjVs:L&9Z&9&^ MaݕɤvOeq'Ey+_hbh'GDzCȺB(kAzE*f5Ό0"4ӌ)ftPnjXo]+o?سB쨅手e36M$Po(u v02`Ry=0^G/z*TN k㷩a#3 sr%ۿ Ve ˴?si1ߓAԇaqIw3SY*v5(Y51讆to40xQ9rl|Wӆus^Y~mKw|NQ^#Bqsғi1s̈9Zn0/GϷ`{|{cn[:6-2vk-oVZm-FC q4Fcqƴ(c j&Rߕ}L{#}9,Wϼ3 , S!VCfi}ؼþMGNK?z8O.{—`bc?[BD/b>bSPo93){J<#}Yw:W@F4 WAZY۾[hΪ8,v ]#xA7̀}@a zZ`C? O-"ܖ#>65ڷ;2"{+vM%\ -ypI^vq2_gQMg9=ǥ=Gg>(*(Ȏ;Hd%| ,심@EERVOU0l*wo{_;Ci zCg н|_H)Om;ݠ0ʃ]ʬ_Y4("65p`63q' ܭc~3!>G P~؎wr+ ..:rN@uᎅEc *lظ zHMQ xzAԾDkW pN8t8@`s$@fka;PYln "b HQƺoc.᮳cً9 ܹ11?` v뀍5}wG!Bj/YD}鈿S +5wqY.棇xcy/q14o(v7kHx AAn8x|A e=1ı.${5pנq &+0ȋ9 55l eԄJtJ{UK?Mj>"k>G>EOsE7ڙ+2k1`0)쉑KxP{ ]D#؄t J2:xՙ&V"_8Cj71RuӲ 6YPsMҹ>jY,BOz;[Rd:MRhg75V]={__Зsbc kAENBv?k|?0j78H89PE -aoPoꤜYB#k 5*a\pP&k, E|>O<3KbXC㟡m+y~oߛ`b<&Uȥ\59颦lY€VɋTg*uũ 6cdJ3Ft@6cv`^GKq;}^] h;c;H N]/eS  VUfRe $7eMZYWF0W-3|@oΗ l1a ؜um%]V;B=vB\pW-%\gKERSy*ʐU(E_0}&79 @͟ S߮\tncuO:>hp{+!Z#9RM2Ǫ* KH)T*mN6M2յ4\DgB9_2?B p%MumwuL@#pBA^ ST::8iQimlY"YY9}^Pd9(R6 D)LI3 %8)|'r2$E9)yW ro?(}Sӑ) ֩ COǥ]%c7M5Y,iY!iFy-_RM-ϻR?{9,Rl|RRF$5tYqE7 )ɏ<ޑ)  Y4PSF5;/xWg-^f72.ԊU!AyW2*R/}8Bfzc%9gʥAgjĥ:NwJCrgECzu6Wzsmsw~a5eJmN qȈԪkRbWH:&*_V/+w_rDgfIkU[4Pe1vGO}MO@ٛK_omϕY' YwFHNM?x=G_sb:Uݔɬyɮ|ɭRAb/+զtU|J WmR}mNW)6'|cDŽ6%ňw3\Heܩ%w_J{1 GV(d2*uTnVyxիE5.vmyN5ҏ.b< >oDrZc}[-U$rD$j {.TB2/^#.SjПS3gi{ݒ>'Oqb_B]\~gݑ&ft{w t\ ꨎltz9)z68D WoZ?u#ꇗT ,iCzҏNF<,iQL?ЛO`S,W}ueyUL+vS;3$~S' j#*eߩ]o^T,7Y+O;'=#e4@ӑ/rdbO,B&xȏYhuX#wvݗ C3깢L!rL:{NFN&&%ST˴}P<4Mt /fVwWkS%*4ҩǡ; Ra:6p`F~ 0cFnuF##G! E$Ks@9]0D Te8v,`X` N70I>~ r>ę["fȱ2E>ރwf6uw r3W)˕ 0b WS $x9[LkpXBA{c7$;C#@!MO/ X/AbAh)c52 E0"Z+l xj=ir$5w« /Urc3\嬃hD1w!av%8?)b|Jؠs~S6$ o=OQ3MAdpm:f2ɷ@Hq$KˡS YeLT~Sz7I}t _(Âh#t! NuM5exuH،x1bCp = Ȣ{v)Ki5)Zޤw=@0A}N7PF,`Ȅݾr<`&OlX+m$9CiFg#Zd= ̠W5o*oQ+~(F{.0F0Lw$sD% lggEw:v/@2ڿ.bϰ=l.R-:{RUp#V$BB Y$9Y$0Baod(PW+^!,E^y>9/yw}qzP!qO( CT=gd W o#oŸ_F M"#Q/IѯȷP(7b5. 0w~B~`9PXT?9; @X\V?, !tǻ4̡Y%ԴjH#uz:~CCoX}:No\{5MU?ͯO+r3nwfB` 9HY}LpuD(09ZMF5M.t+y&A ?,'L2򤨈2% `uM%;Ěsy~QC| %'bzjb72zjRXMI\I-)'Kb mB\@ḨOH8Ww~rCsk 3s63Q64r6[!¶K&~˙F"D]?L 49.5%Y =7pH`1],Y1W|rTMOweC/0m|L"H Qo\JhKٍU}_6HϵIӹ{n OO?|{e/ʏU{Pu''L٠KT2^fq OhgK ^\RQ?& lLjwxѬw݂{"YMв֞\;Tw}˄ nʦD֤ctB5YN7)S92 C'NEEC,PGI1YR PJ[rY¹}'}K5Uv Y/Ηg1c|I'SCR(NYd*R!Z2_ɞ*!hTAc2px3H]}=@]_Y0^}gwt# cOU EttAVJNSrY&U+UJJE1HaU@5ikwxN|ҹk5zC'KԘ<^-j3$/K5u&-Qp5 J暒Qr4rn,Am@7dK[>Tluٰ}së otxՕ`ߦ*P'B2p5 (\R' G&w5\gZ׻^<|}WwVPr9꘩{.+a%R!(Pq9g83mRa. $rt >SWV:rk>WX}rKEGK 2؀9ZG@$Ub\TDc+شB-h.YK}6(E[%XӸ$.wBly; OU+ڼGr꽳ݳҚ7y(n)(A=Ǯ52:ZVf$+̂J]#EOP)=@/q֯/qxpoӡrΟ}=K+3FNȺ :VMi ӒLC5vDS7<]~QmP.rF/Pm`C߽yݏ:6Žў%GVg  uDЏ fB)7^^Lu)6Z2>u䝆c Ъh](VED$ *d/FI  Œb#ngT-.uGܷ0n B39+r?%RC]9˻RzU.y;w;l`Wqy-g?cS_iy=*| BKZJO6>b)MSXT*4VUj^cu:ZvctWn`>ӳ~˴[9N;W/9'%j:f8#mϲLviTv:^֚ۖǔ.[Wd1uV#eߴj%?Pbv$k4mv!&2yҶ]7tG۝8 /t)]8IWN0׵^bvWrRsLyc?=*˷ /m $KQ TL eP`F80+c_ĴŦXJU$& U% J>=r25j"#C##KnD]=q=ɑgDGw>ѝW!p|!ݲ7=^Jp|Rq^>(9!Q( HaY1!;BG.;QȞX?2n )~c3:Q/H&à r"d(|!/1B?T`GMG b ֶj+}<Aw#` 'p3nI`ǃѴ(ȦG@=# :d Ry=[9}Ʀ߷ V|aStD}Hp GP''C>i>ԓ}<9S|P6%_z=P5uv1 ġP/r. ܙIH@Z^(%Q| DJ/&8X`a:$I!a xa;{K!Ȉra93aӡ@ eqqu1Syn-\Hnlf裆XT?go"aHi9C crY3aaH @FVҖECm<$ 1n&x k&i}V3 #~{Pi کaa5, >.A C+Ĺ!<20DC:oe@Xu QS|pS\(nD{;rPo,'!6@f A c8Lש( _6 hLj] 䛙āh'#NwY3a)X<,a&Fc42Q)mkD,Bg_ ܒZTO.P&6+%_e- / _'E}4pR4Bo`,L\jV[x~IvX%=!+9x-7+__)[T-=YsSn\V/*G5f. 9sPl8PY^X#*EP.r`i^|onI)k-筮EҗvElSecM셦Y֓~G>A^W֯;8"߇UcPwGs-}5bc)pڳS2$kw[4UՇ5wtO7T]Kzuᔦp?VM63rz\?Y Brs9z!p2;ik#|r[a[!g=,Ʈlׂw1XWef ƫVD)tL^Nn?Γ8rFJF7qxg3Pr|UO3& S5`їƽ}/0~_5t<᳷9h[C䙆xO$_TN r0󖻍\g'9YߎAZ-՘MOd%LM59U}v!5J@XĖ1fGyPdвp.O80v9f< smOvcb8fZp(%-$T,,5K34HDuQP"KٗdZN<9\vupdi}{>Q `>7ZNHM$RCÆGda+2ZB'pĂp2SHr] j yhC_K^hyb5b=lО# pQ,[8XG*cE_ODNCVNš)i8GU;ۈ&_HfPHZ!I!q"EmB"~>"pg#!(Ohg3aNQ4NB8kC{-!v,t5J d @T~|p7c1?#HKAo*V"t@' @ P{}dY7` b u: Z34b(@,i!֡%`D(0~N} G69?CL  [(B[= q.Ш=4Bqq%xg`]y=;{5x5,k 2)Blp'0\Wx@c2;U ._ QM;#tp[\6scc~pG{ÜʘT e0} 5alZ(~'gYb.cny8=לOO11v {*D̿D[!އ-L쑾h hśH 1%:K谺8|H!rP6 ca=,(^%~wBx/[bE܋=!9a grܑN6C=ڵQTUnE/?%'bW/wsᓸےRȬCAIɃL;8bXɜ!|n>sZzs~Ē7 ѯ4[؝>sQSYr_?ߓߑǷKWҋayu!CNF ;ڢ0xǡؐ|Ѹ#i{KcmJqkjobMZ:Oo tgw%;y}w,p>zݭB/M6小\!8D߲^7ZՐUPq̸%5:=iszGRUgcefobEf b,g":z_Jמ 獡#NvF:unrsԱLvSQpxWZy}&6K&w*簩2yCgu9Irr{A"rYLtފ#oserɁ`{&^ɛu6LfJSdSy:qMP\Tee`KBE~Cb2isjrqؤϷ&,%!T ; (]@{:!PRB( R'DD H*" qwPagȇ99ߒs9I$(BVK S%> ~"^=7y^as`&ETSYAʨcGq'y3좂s‚nÔ/.w-XOlDde1%PD _*s:bhqИvN~Vqt`~xv>ǵ6Ç_TSq4Һ"މDnW49z)p}8EGדrlD@`VFExߡ³JdT=bH2`#7>"ak{?~л>;0y&6)!3)l09l:`9e̒ (FPyyX햅#`\/X˜pQ<cr9Ut(PZ=/2*PmC|zu;+lrJ'&I̩ZgTn$VlDt_$ X' ڤEmۓJper7ujRzdYgg穾P3Qֵ]SNA&&t.C#I.^hz-;XO#v>c>N6nkRlrk}xg.+98=7Q; pa``4ݣARP.F}CycJO$ ]ㅾjQPpav:MaC/ao,lfʹ%?wHo, ןDY\$o4(^U5"kUfJglYsVXV^ R x_md-;]:fֳ{l`^`h>jd~rgc" t^hXx@@!`CӘJ*䣃t'w9O~[=>*~fnsK;jZ|[=8t#42B/kd@su:pPQD-JSь6t7t䌞[_Ce!S "gf(`*`Tݍ=.ne4.OH"Q(D'P\ЈhCFG t}JaFK!k.:7ict5A=Ș0EƬ_lWXi?M12qJ$ވ:&$*eQyPEY+:긺 (# ~| G E 3N:8ͺ;8Oz@5!8&cǴ |5;Gk :{nq#x9g 8fӸ/<.ou[@1?s!p@3 if o^9-j y;Rf5@nrv' tR/2}e_^S\?zqfLxÞ7$>hp ANAF\2r6hjіI,[t;RZq3~.Ӿg\^3E&$ߑN_%| , @`iRkCٽV@8y5l 9H:ff (wĬMқ\?'?z u:Lw~v{ S?xJ;oe;5CB"/oSlKlYk3)Nd;9ut3{ܟ1N|ʸI/WIs >@e@>AngkJXO]%i2Bӟ֯eǤ鎣2Մ!n 1!ktkk:K7J?(}\[0G}Eb=l AdHQ@[!Mڮ{W{zn4yX)(6~;aj<ⵠ*+6EI>9?nj3qf K10$H 0<_^ ꝉh4 ]\ܒ\w,_!5{omwrqqQ{/3=.iH}!徽jϾ&)id`Oˬc6'vMUE]sz=H٤[ ע/Kj{FܕXRgkܴ?ZWLdUE7pQ=’_DőEQoQ3C:~AW= 1%ޙhFIiV V\-[SOxgWVS{zTg*|$1ZpqXqU_-khbOc/scs^r⦅sx!!n꽫QZM}y6Tvnj Ҁ' ;#=T>)2U>(I*ي.Q$]qWVS4)u߀`_vP@cMjM給`:IkOk[ lZ ϗΉ#j3I%iCibVvr/]$8)NIC5Cǝ/: ;/1n&K `ŏX4jFtM@- aPBzVYaLYㅘk|kObX3ٱ~&6r6ȻOOG6ɠDW9i"ӽQEhƜ ,0b*e9,'aՖS3c3{DQ4H0)ځPqE! <Q=0i` 4LOt=.a.ʰ"aDCE4TQDU8 cPf([ .Rn(ASxX9xG r09ACڗZ1Jj ֨IGբ8hJ*\'8(>M\'ot b`8dLT;YR6*q~uF.J=QrNި?(KGyR$%zQQţGC1 0Vg်Qf@e;b/CxbQި$D*,,  ]彂w9zЧ[0OE-z c LZ` c16\0j #ڭaMzo0|?@uDЧj*[>*/x}P~|ݣ|ݥBY0< }c% \*fS1wM\H tdrtqƽ7jCd n]7{G}^kNtiD/5D/4Dj=|f~Rc5uԙqIDQ⊈ȾCHrsH }; #xZʴiZԱuZ>sx9||񐊵n.5YMAJ"KA 5 *#pL6#-pͶz7ӦJWn]Rc&S٥";H+,%p jHVJbe)Qa^b(,D y)|Z)qn3כ X)a zmVoRG,K)kȫvٕɎ|3LV&V%XU?@Uw(1ſ!1Ő(ZeW0Wi x6}=A{a.'M6eKȞ&!>6!$.ݙ[+tOfUUFW#ȑWy{R"wypьÝs8>Zﵡ7"fi-hgMoKKiIuHl7Iz7QCi n \+k{'B>p6?7{qevCd]@?ߓv> eЛbw8Gv廝xw{S;|)W[E?r/~V迒g9jfjk`s@=aSN3w1_3"ܑН]QM^i@AH ,!!   aȢ ѶNjkkGfܵ"hE .qj3/s{{sfW/=4rl4:&eUԉU'br(PV_}P#>NW8,9u >K~i]ԅ܋/a坟ÝyDUD^Rj NOD{Z\oO#"V7ЊwXN)iQOͿjr˹jʺZ\25/$7'6}&o 7}״Gm:i=ic l:;wP^Ս Ϳ㌊|QMD[}fpNۊ<zǷ1tmk|cm_blԶݜǸv ?6OvwP;;ye*pALdRԩ3vΰOJuvuO*vt/v^^ٳK޳[s.=͐^cHzak=U>GhùwK[w@9(+JcԾ"_L+)qZ;@U=h̦E;ȇ#J$ëpKi נZV7n7ˁp;8]~QBi8 c>H7'""zBJ*'T"}kC]dR!EBXd/48pܑ~p֑ ͎,xx5quoC('u"4c )d $L.9t?$\0Q ‚̷C|n Pݠ}f>g#Ѕf!8w W(|!g5q ̤+$a.9N )Br=H$$(H-@TPiwgpZwl!_t1 b v{ cbh01dU!$Ą Va8*Ĥ@= >re(>/}K _2AR]`O!tZ WR`HR~E$bP ev0CKq'@7' - r\>&@~ aأ+{X>߀8rɀ7(qVH pIj*$&9f̙!vh7z+bMDbGd*FU'9oTת+-Πӧ<S@?IH䓐0)IO0M_=_3[|5略3h5gx/4x57xk}10=c ֟.)~ HEnZ{4:ML5y$҇V'c0l{nj]^An}SwQDMЮ$M|[:A8n@,ҘHB>#/~|qĒ2U<}̷;u 3+ޣ&Op/Bh3Pxtp_t=ᙨ*рK_걺I& (NBQ(e(:\ Ź77ǽ#g={ U[Zm7SH!zʿE-!ƚ+ƛ9ji&"N}} {o7sY Rʳj)s\ΞMoBVkNŲZД!cR֐ȧ̻$VqSmDcYi@~<4VJ' s<0,bK%!dW"fŹbR~]ʀs> *SINf패';Q̨<Ѡs,AeԽ"xBBZuh)MְBXRȶ[ȯ)\.<9q]QMi$((H*"@V,f5@ !LK@(h5x92NGǶsȇ߹~z}c)̓*u96Ϝ e^*3WuZM?YP2r}mob ZfkVPa~RM|%Qz|Ǹ$~(ŵO%n %ZnUSOPj8=G`ߡ_ҥhܟ)<fA%z)U#%ܫefeE䶉ò3. ҼMBZ P+ڰ¦9$P%+2-%&DqlZ`ߗ+ ks9l3k2"Z*?﯊"you@+a{6 }jKKKbA*huE!j iTo5&#YP>e~L`C&ZSXQr5\k޸qM>ʮSkMmeCJ)׻_V& *W"5QXN< @>Bsoh\!B-"y3$0T`½z5:<̶ɖøPFm[ÉZUGJ>EMʪ|oHY8T*Wy-$W6Ec-sFF*"odRJ,48X`f:` -ؼbt̡Bpק{+y~š@~,6<_ɮdUL2d tt[Z?tBɐ!䭐\oJީr1p {@0uָ]r]Ky뀨1dzX]ksTu BV&*)LU*CqP|Ce¬Aȿ!mpLp~Wy z{ô1){˻O9w&)HWԖu㕧4K3!i03"Y3JJTϑ+ r|ȭ^:OuW) {hshF}p|f+iZ@՜#H1\%wc홗.:3.f$p㦥NNzj5y˟>?}?Oq$6nfDgpG p =I=@+B;D7xxK>ؼ04+6g|`rŁfڵCk3eO=IW_zFοC#fwv~Qir os+ k cLV-&۞˲?f`;Dx; ejgA'зhv 7|fkg/] z ٿկ{x`),@ [ߙ@C 8`64f1ƳGm4c5ȵ4W+jv8N Z] _;{ z LpA8"4```"pP, RFC` l¥zb'&jA'^R 4TxPQ HG</chm6F&Vjr l&e #n#D eSNCCC@:*"=S,kP%;LQRBlt$js_%nsFΐـ޻9sG^xWSo-Tj}'润 MuyVMg/hF5DӠDdEa0$L!g*Si=j0DG3t9G.ߌzFZd-tm%mӅZ!?9rNGؠq;EQ=QGNZ (M4LfΙIJz{zX[3ح ټkqyVcW\YgCSǟ"8(s9~P~Tx>좸6xx!IM8JEo`iǒ7g`Yûl;x ʩg[at5#}!UgєPp6i 6-)>$VG7yTE_UF?UcP=LxI ds0<Z@{-ΑR.¸j8]ECF.-D ǣ_:N N&!Ƚ2~"RVws܏^ZqO%(ߓok"!dc@13E4wкXD]c[lظ ]lq|,úՙ3 \+ֹM.}7מEIRN+g^3?*I1ބS8Ä́!9&1<&_b7r2Wi1_ì͍dIUTfgT6k^QIɷ<^3{{j϶:-畅w_u+7nJG騘=C<R}ZVry^).jpdI*/Wy`vs-q-[ 5gdBV.YMY2O(g6yK.omZ>a"^.#NzK\ g8@U+beV%y:Ewn_Bu.Ϩ<PD H)#LQA,"tІFpF RD *1XQp]f%'nf=G}s=WR*x-^nAIܐ84wQSQQ;aQP_B61xCTT0^,p̕_-]Qךnܔm^`UfWH+v)OmRIޒ)ܤ޹oEDBLH$ oA26.98]pfnt.*[;hQ]&8+e6lDzBY[Q+HouSEg|2R>H{-H#BK&E20\ߖpQ )qXt)*+4W֕V"ҭ &ۖg:J $\IN^vNWFv -h[i Q^R"K0T꺭bQ#U+,-}).$)" &{d1pq5k7٨&+46r5 j:^q:(X̝),dEK9wkE5/snAph}OQQQF_,Õ2ڃJwfm4Յlț5{V5d7DbRd+>6)uSu墈&ކ.uCq~hН) Sxgz7.^܃ZZi>5Pt:2e^iRuI*Knm7rKs=M2 JnHC{p OpCpC:=zW? -4 ]@e*{磤ϖ)sg.VY97[pp֮(f):v!;ikw۪n{B.^R=lRMPzA]H-u̕IrbVύ>u4BcuGLBd.XPWvﰢqy7N}7{;s& 9:t}C@HĶQc$:2%@`u#BF6_s*ppqp5~'[-LjL.7h2h1=D[!b܍Y?.b/Qߪr#icؤ#7&s,17]Կ+_6dǁ\DU#c$&3+Y+&lU}'|2爦4SJM&-m):S]{ýqwx+}P2 d.W)6ncmm,m ib191 qBG|KV@E1aɂ:3jQ!9N,vP>'Sߨ־XԤN]O}&gI}D]\wa% R)i~=>BO͂82ٙ!.g.CX~خe6JlQ*\iTS@H.!y`b FdA@A 4 aJ"cD'( (
Pϱ+߱}`:{uI ,c`#ց]{I|OdE?Xc{< 8b¯37*535.ClU4-B 8۰::paQpڱX'v1e| 2F9#a[ lA{̷Sɥ,s0\; "_ h@ |9 fрW2:pb5 a|'&Gq b{̽D|^'Fa7BMhXt'=o) <_YؗڝW(5ܞdZnQcU!-[j!.z5{%-dp_jI:Pw1 d_hwWеL*D:臕fJ>Y)hץ(Sc +e&Ir2j}S_l_W- TC|)3I]':&ͺ(f^zLd/.XBVJ/)y+nd)˼hYh=w2٬ )vQ,yvi%)YaYYWCoadbτd`Π6AfҊ`u ؋M,hSbE nU/*H,X%%.ls>abAǐSN7=p w %!9kųx)-vbE8{`u,= *̃/ŖŔ fL7=[+"|WhW+BwK' ,:}mDss^R(shRX\)wPCTffU*'EL;mV1$bل-mWC_^!S~\[~ uI}q-v P߻`G)@N9@ΡKհSk km N3<:fjm0ormڹ55K֤Uk|YxWWENѨQ?Jw0%wrf@Rɼe%ǘג3Ly)P@w_wOqץu*N:ڕyw[6~_U%1/;{xb ؅>K= c.Ul&׮VsǭX[-uMu^uY~%U4uyqx"*ʡvlC5ިxxŃJs`Vm\clTf3iwNl׶ݴMnc3w<>]لmqN `TRiyFxs.q|r۵yyo띭}w8>9|nrolʖҵ-ˤe=UΧ䋜o)`"<#“QZ2\b$D+ mk ݾKvxr~Kqf(/]p6Q43` (; e /r*x> ].K< ^9e>gx:,fٌ M`tWDL+p`_+ǐ5|U"wxP w`EĄ+͸EQ"\!dAל8#P ܆Vk=!㼽ay4gTh֩ȑtG] ;z6& ,}sQD%IV%~pYJFii~Nu?V,'ZBsS` 9}yt{\T_b޼1zDw5Q]_Z|#x~sKn)$U9 48U*婄\C"⁒RX?"ZB =zOᨮFgyfG*˒V{3f{OBlMz 4eεFO >pZ`JUD/y:Ľr y̿_ # C{-4k-CF(^ԽfjppQ0f|7\^a3d{wUҕiM դ 0ь]}QNbWT.ŪUV^+1\"h:еg=Փp>j -b oЫ*CH׵Gh(MAcj1:QLtwxBOg tZf݈kVߙ^b]jP!SXIsGN/l7O3y|-0?a LYB6b>@p-3(.7RFvsնD7ó2?YWyĪw6vXhŽ]ٖ eɳјJgg]ȳfPQ%L^`}a`aQ PD0÷Q )Fal7Ls:q&3sޜ0e \[%%I8ù s>pٴi ]ʞQK @ ?IoUWp㠻6DC{=7ff:47BsP u~ڪ`v? lo>mnVGA '&:n1ߒBӡC U(| YO"$=3!Q2 @ׄBz=HfX0IF)_u@wPlP ( PC2hM? tB"A kSRsӚEs@a=2`8Ȩl3q}JCHb >$L$)^>8qZt^wK-uD'3Ÿ2q'vABpaRNH^ɛB~ CXHPCnnDOZu T 52^HF"$W셺=W3uЯGnj6{ΆF.f#W'~#{;֫e=֥?:CןdNvå_…VW.D.rah+i 8Jc=a} Xa2bak7lcwݿfwܳmЗH=_2p5YIr4'jqbjQ3o7>xDxG#G퍼y13K~{ԷofÆ_$TT.nTwR7\v43g7p$I42w7y Y<=Aߎ~m1[b~(h-hHh\`%li<?"ﻝAtWΰ)83Aq^aQYpZӀ4ۥWsN)LjK$4%Ygu 煵Dğ |1SPk_yd`ZT[0VFr2zeN K<׭EhJ3y5YxS}k]|tDP%VHEfuIcQؘo1}c%殺9Us0clƐfӧveٷ͙.J[}FG]z%WPt!A|BT*˗$S^X`EаtP7)r>0Oc m@o6Sm9`ߨIvV8ת\+Urg̬-l/VʣBYNxBKdń3_ ܣگ逋"`~ǸCBGGAӢñG%8XrӜ+wcNg3de7 }|aQ$G}%@~HJQbB'Ry"es8Ba+z|tٰ֠iEU9H.%:!_YW˫mks{H=%Qi/dj )Բb-in({HWFG'5ԗ25e;8a\sI}iqp)2t|b ~VA `T;!V.J亻r'?$ K߱!u="!{KsH_[p"$bP[*( b ݜB~xmuSv%2MYY^aS̃$0(8qKQ[Q&']%3ZZ:WtCY?֠ȺYwrpnvC}V}^8vw֕z&Vk}j15,(-aW¨/U V]uTz>+C4-(lA~*h7#};jdEqmim2Gi9%5\y볿_x,?:_/aa ճ`>GSʹ -]=m]]@^7^/dٿA0Xnb>/!W[cv 幷%ޮB:B:㦉fz~t.tV.=Q7![@$oGx(3͉OF"Ʋ9u5ctmim##?r>o<Y, Q}hPv ec@¤b=%F:ފ] gBgb=3) ΙmU?nqxkzq 7/ޜS'Xc@ v>ʵ sH:D&u9_[sc>oχ`|mq2oTh3q6٬܍~Ivl?ᮝn9~Wc2 Ng9ឋ@e.,x p iq6.a]xj_Ǻ%,e%V/YUKʥ#LyFr6#Y,/<爯1E#T{'trcIICm׀759`w ﮃ^ł_9}PV )x=χ_u1>FH}oM+@ lzx> չle D((`W% 1`A,H@Dņ(< C-O1D!ODQDĂg0;=;{9F 9PY0s C Yҿ#DHNb:D X ACFr<(g3J,Z=X=OZ8 `] h%+"6!j&;@:5ͣ1n@hm }k7jGK(]48Zw }0`W.e@~5Gn+jM :kRsG?:=@ON}DoG=b{}`]$7bu)bѽ5t?+f 5(F?C?b>`hUŗ`RwŮ`0o4H%$"H>)k xCxjth(m0k0QLɼLDcOWI%KrW߀|ExNyn@߅BV5ջ ]x)[,<:t6ᑬt7J+&BZ7pC]h2ehTsE9塡|(T7Tj :U3PŸ@7QMVen)wr{q]yMWՌCkp^øZsƝ{=fKm`f9/c)QDy P+Kz?'\z?#qnU듸c>;sC V}ҮBܾUXfLXD%L3lw`φ1H6G[g\qǜqy,wy"y_sW8-q;-v\#,s:Jvv:;9:wlqfLm|N:h{u A!8bnqm* [u_epKؐ**2,m7֛l1l5)0.7TJ6 W\:dk\^V2Yg`(vF#9. % }#cwJFscS[ŋ6-X f%YZ=_ڽXU9 ֥t'+mZ#PM88>(cEV~O8qT oDѺk6+Y"ʐ-ʑg{fzmS,maeye//L:}?>4sЬD}>͟Po ;`k@xry`A1Zѓ٣L2eit,ET-RBg}[~=h(1:ӑ (X2 d 3lj2|/N&I I?Wbиlqr1_5׸S3Xejf<.iSGCp" 80(ٯ[u^ȉ̘AȈҢ}QXqR9Ӥ'S E ]|j)ǻMk"-&1sT?pjPEq췍Ҽ3NZ,ҿqBj;(v<.@0wlpvL8!f)xy\ԨLȵ" uyGEuqwgfd`.誈i*e60 URUZb2XYK(nQ@M\)GO-hknQ999s{}b<31=uO\u]D1D[~:s[<ס='ˍykP0e P0I(HҜy2s&3.N#56CiuXShvNޠGGp>36o_kE QY|7jdYc?4bIQ4I\tl-4 6)1D")!ΐc/T+b۵ \z/NFŋ~>\3T`'ٔuy%&G,5E^rR!+ea򗤚a6IѶE $}LR¤r'Vaܦ 7w 3wY`%Rf5Q|'&`_ԥ;I 2ۭ^8cGbt8Nşi kܭz a5_b[7 W`=.Z ׆]4T[]Mo:`+@. L p? f' iA̓0 8 ׃S {t{Ȁ>-fn)Eϖ:4@ro9tXr0y TO&`R3`Q19*hZ]nusp2Nm U{0C{2OAy vP7A%PJ^uqW}@w&cN7sG80u p>-*ka{l(H/xArA$upup}DwPA;6yDt3=S-iw8O.ձ]#Zr_`HD)PY^K:_KFn )kp9}5O= G; pKŦ@ ؋+p By:xyDM?} :[KWO21 F.~EG+#ɗK q_po-~#nT]:˪^nb 8K!N>C<O}'iǠd[[k;ϯEf\ wNrgũ!p/394L`""}*/@%Spk6\KÍ8†NQp: jp2`9Nű yy9t>`:G}vm(/cH?5'Ip?P;2z4.c: 'i8ڍVW0.bfzWt[=h/ n{h˸_E zyɓTb5 O7?OEOHhq`t Dg)`Cʘ!]Zv{*vkphsѦŭ!CΉׇ7OZ4gI{Y*w}? A/zPg&2S:Qh MP3}:5<@SnT6hZ4uuqUҠ%YVkNq+5WSHOQZ*HyYITꩤމ&8biޡ'H}1 "'b{d86Gji`6D3-vv]m / %^^%^DR[- & +[v\^'_H {BWG7&3ҿ| )-F{lM16ͱhIbƤ2l}C<@,L\5G$jW3NpZzfyմyQG}*.*D=P̎NQ-xyO |JOi:D'mxZѬSQ7uOg x $>[TujZ*W+F^kSRΌUighUjP yj9n/L]ns!I!X2)!K CmJ,S,HNe'e%9ĕىeܬJiybLR^[(TĻ|~$A& \9 4{IF ǪXnZ㻨1b12h![\npI%\BZ_ +/7+)ەN}?&zAI(^s?dN~7_mSJ<ñ TMAeZ$Sa2s [jfKS\q7K]*Ӵ'Ԥ1n},)F??2 J/W袙h!kS.s(N9]Q;yIq#IlĦ3Ein8U(1} $pGn?cUk(b,% J,v-I.. Eu݊#ʘOʘA'GHotE,9g0@X3}9ݓT84ɬOOZqIP/y_,*ʷ8o{PzN-gߑn1>c ӧ#% iJ-,KRĦwIp^4;D!:gk{Re܋$$ӻ0 Lg6)C8cl7FgaTV?x B\,Il|ଥҨղYeY&rM"<'"*WB[+XIYIoR٢M^s=\wD\C5`0D"83ƹBqfL7JHCvKCviH#iȆe!Ԧ.e.I ^ ̦{~F`8[֘B99c@"u(AxI$ %_2JF_Tf!شzS۴Ne*Kv PrQ? _H \ la d5i!݉tOR r+ZJWޕeE9X 0e,sòb 3КB[m(xuQ!b#IY}XLa[8 l5N /xF6#n7LŖ-lڶ* joAe}u͏Dt##s*g16Jҿ< pnPBUNP6t>2 kgBCfQttR@Z| 01O'06 z? 'Q@86!=Õx-~ 0h兠V>xڸ\[ 9/G0+"<5`#Ha 8iAu#y㼖➼ ŜG;/"WX_B_-'{9ȍN2I{F(;޾^S@y\|N u'^5Mw6'݁t$jV; . ={\\ ry =f 0^-z~I8m|E&w͜>ɤDtح;DM"P2$ydIOK exJVғ;؀DW!-tUU񭸆2Gq?"G@ο\!/"o™89iͦ=zГQ3pkMrpqUFjFgъSm$3‘O"%Cpb.đh8!x ܒNuY"o$[ TY:Sf*/G|6Eр&E :=؝~@JDd j|<\5x]7\uK18 Ψ)ؐ<޷=||E>86pcQgvǡJ? `>e TNXI(ћ`Pl67HCNI6ܒCHrCEIίx̲\fimc?p}a2lEa$&4lLY(6COBao/}\)A55J .{]8..]n r[ۊ(%*XԱmSӦi3δv!mӴt2M3Mil/2f9ߞ>f&mJ`OfO-'_Ʌɍˍ "ܱj}6p/{Vp\qz܊5)hF+" ӚjLjIMs"fÙ!v43gNsCܠ"\4wYSe}~@DPCܦ+;t/m"hUc*7'sMέdFNfXa젶 i{~0ק=hgnK.UEg_  yyBrpeCmnNSgcDǐނA}ۘ~#ۥ悺\noӝQ ~+BY_٤+Ш>BIN1@QD,60aL@ش æ4g"dGٌt*tUVG5U~B$Zʜ5!M^Z{&Mpݵ6W&dw*&]g] ] +"\F5uWep2CiJi zE{RpqbS#uEuSnCw}jwςb_c٘B5Y3xwZ. וywy_sjJ`&FOy]7Gif-PO՟ f"1j=d\?_T䴼n"[n~i~-J#0GLQ;;ZPŽ0wn)j2@eE~W9tYV2s܁wyu65WGyu7HJxZ)st~P@1лoA^nhRqp@P>CfdJ U!#:¤zq65qMMKr)=kJu.ӞF D5-ʞ[ d!st#2ƶc8ia=R|+,a_؉pH0ç] M&)|II74eָLZqhcq=dLO ej=N'$$O`fbI"qH+FB3sH\3oFH28O1p#Mύ!Z-v87 dRLL=e\,'`f< )H\8شhlX|s/#~qxqo n=<9) Ch_$uh ПfIH^6]p) D"\ށX"vŌu+XEJʕA|-p~I|gėPG@pS%gi9i%ҿL/וP1M}SQQB_CRJSNhHER !|dB29>eȲZfǚ550żmw\]繟њ@ҚCeSeSE؈xxu`E D994|Cݬ`@c\ 0^_o !(`$' NRp>ٜ69mV<Z[9ɭ u;yr)ɘ+ƫf0jRӢ P676 }@R;Nl_lL:X;:8 u'F7yۀ܋ouQ`= PSy *_6XAEl<sDw' L7;0x0ZSלV/R"ȭN'w97?=G3sǼBOٌ<݋*%_꺑aуBFqd$$o+%9V)6 *5 Gp-'.o Y]> C+"/NyYG(2ꬢ:lΧq&9[<`_Gz)s 1'#`uQ/Z)ʤN`uSJY1ks4r.f~/Ȣ!ӝ7:WGP3ٌV"uC.b,lN%3_gpqoZ躙Y<8I + ᧾dJQϟ0ԊhI>K\P\͜E140M\ts :k42JC斒e.F` J.$A"gѦV84%^:e^.R/NZ*4؉zzu uawc3vE= 2,wwȍ>6^X㴱;MI(M"pX2 ʏqPze6>WNbOr۱t?63/QmvU揱-xN,+? bIaJ.l?=*q|]?o쵘ݖѨ)nyfQ%*W`U56YQ1 ^GXmnzxj3%Gyg{GFhh:!m3;m}PcjQevlMv`7v9Xgka}9VoE{X^nA+'C %bY(zԿ=}bi}z5 56t38zc?*ð1ӱ#9JYXR<,u*BSPۓ C%(Cg( <'bg$LCRimE/R. aǜ|+W㬰@=ծL?2ԡHWO,TcNiB:[H+~vHZENһ\b͡\l{Jza|7[ +Θ_!90IB|B\`/.> \/E(TL : <&JAigV29Rz)d>rIv!cv RC⎙!c1# !a ؐHĄ ѡIBTh0=4W -mSL '-kzaRYA#[]dK3f H0$h\FFhM04ᘮiBdx0%|09_#M273(Bj+7& "0#2L*8y2T2E$\Ct2_ۮfFmo^R=|yߔ-}ԋRR-)>Ϝ"3*{$efEim4%wW^zQM ʶ&fPndXVL#1Z[W,2Z2cI>&6j!<@ۖh!Y>q4M`,e,x 9*#fT{RclO8MIE,%eF+amڭku!u j[5Vm8պʭVU_Z-mߺC[[7䷦A-Vsy\۾HJ1eRl4^kЯBnfs nԢ:D~aj^)K`eổf+]M"ˁ샓4(-wZ^;ir) 㞓nwF[Zi&sMk.:⽏B8jijpkxju-HN~spRb]05g9#э܆AV xE{M\0pvƎ4Gh 1.::6zIù:bQG, r/ֱ>[#>AVG%h8ٜh[mӝihml҉GccPϡ_ONIt=.9_9%tzuR glf13] &;Jw>%}iBPWf2PWIU̫8rf`Db405nt;xZj~yl ҧp>HKo[ȝkrf>7vߐ@a5쇃L  B,$B&'fѿHi5\Buz}M=żtC:~5V)@C(M44sћ 4棱XׯuSDg-:XsE]>c}X+]`F>/jh   M@'_\h(Ac{)ezO=lK59cnE鄩zj>^TPnBHȅ@B.@!B- !"BAQDTRuκεgzvvnݥ]9o|=y2|k1;nmmW׆p%f.Ōb^pe^wqbpGX}qQ,MB!R}[;q+67Dĕ8.n0np̆vr|'p"~b!MX‘8p1Slӛ+,ejwѽW6\ڔsxiXJ$+܂d'wc.#2-޺[b_77 I}O0vG1QݟP{WH{1jm }=]8c,Pxub'k&j~GIF(}Ls1.è( Qv 0 .E!qbz]BgNtW2)ZXKM於C~ʚ%X$|@5敏)pS=e勔Ǡd#$Jr#K*C@ZԂvenx:) -f$sSk48?&"fE9OO5_{Hcq2Kc^2F9)_<Ay)(ѡ]QVE9*(Mp+Фtl ;|Us^lcQQfU=|ƌsdL3NY)GQF@:,xphRRW€ WzPW [jƙEsjN1Ǩ}|H@1jO'Pݛz49D&N7@9z_ЦG t|4j JQU*;,:7:?L>fԏ /1*Go6Gg!=GrO4\Q|̒մoѽ =?eiѬ_> Tx `5\@mj#5uiBuc:NVefZq1^Tr*L#NKT֬`o+&&uh<͔zSy(CC xIe_3LVe(%dtSV@uʹ[hUIѶ X6# D(ЯvB / ?02xmY/sd?q5iݧg&#?E^`!! rB*d lnFf2SH/!-|H }z+NRi2Bz'6@m W7Dd;灼i06@0{]1K%5edX+aXo/m` ƣP;612@:Xvp {KO"ޣbrϯ.˥*4q~d%dԳճ|$$;G؍=g~Iރs{Ecpnk*>'͓|]%5!qw4V BB%}lN:PBp$aIvg9s~DD$<Ɂ' =Q%_BfjDd{=YpN')|FLN3,19%]`aB.(}INPWʤ8xd8Du:1>J;돟Ч[o pp p&t;1({@}>np/p_b?'v5Q5M+[4[Rjcr}Ǯ{GﱷEsS{^ =9כ `.AFhC+qrCH_i!eWk2[EB ;ɳtUvZ+~~vuGMD]쟀F3A#bÎZ̙m e|??[#(FXI 5hHKS?(4HИ9hb4qR<_Zق5b.@dP+^?jFؤsbguC |h4)ڏ$/{;vk.rrkmOqR-Yۤk#ވ ?;@_e.hza}D Bc>رlÎر;ꔏ<-zUv5ZVJ*T)W x+>hv@Iy _bh4ICgV)B^fUllF-n~TTj{OĎ\봷hh{NC-U'5vk}?UV0īܐe-5LbCfaJh*w\*v:"*p~9.ϔbUnܜoGEچ{hsVDh_wTb-pMD(9IQ&1S9DqpŚjdt/ a44ztc-Mh`yн\g̣:0+*"EPEaeXT7( .ǚb&Zq_c5֥1xXҨZMD? \{0t^>|߂3s1TG9y%41W1~PŌV1V$ٍ6es[2͔-WJ3-WAMJ`?fr1 6 k`T78bEqgO9+h`U9Kq&(%a,pFIJHc0'+ ?:cx#%S3=|K!1'tTN쉽/[P%5)J)Iq$[d-`.s\ŧ<+SJM2ZbSI Qg[)#Si)ZdQ5DJH5ʜ4LiK+Rm9-QtzƦoԘТKj0;1Ue v~ۘ7m]Č~2g V|F2-cY1YVEg56@cehKoPxve G r+^eti)̇ ߶LUvyWMP*սj4ʳrUS99~nբf@ pWKXN/`^ @8)a3/ffl^˹-~**uv4{Wnuٕ-thFt2K` Py;Nn{7M.v77\ĵ7TN(WRjgpG˽_&h'?mM^!A918P~!0qGBAlp.|7ݾ\Gx`K:9:A$'1 G f:GMhI ކ* ]{.CvyH8ZZg8 U|J}'|/Fk~Eo#v{n;tk`3?M—Nñ=]|m--M< W8/t?úB9sIm|y=C魇 ЏF{ok:KkOB<u:=K[Dp\џDlAOЕp@F=+1ɤI *!q|@#q8մNjB)odJOXWGta(V2:h䳣:FGqK]k!*WmWxvjgvBm1<{/H.ΐ}"1++YO䱜LYvNATúuLM&آMG2ӤO<JpW0`6``6` $&!IsM4I&kf]zd=Uuӎv6դQҺN:mkUv޷dz{>I}R/xW%^սŋ7Zʥc:\G&dQqXtS gb"㙏5;e2|+ O =.V%?{ewV,Y ,de#l33a*pN79nek4y g((FsP;."7)R.JŎ].%Yˏg m K(dXѢV 2X4Lq턶GIPݦ2=Ke6ҿ7Q׾H_Ny5K/Ib$SCrM6MNJ)&X:@w8]eos[<7C_kҝ6GYyҾLh_Fͱ 3k6Tmqeioi⧣"D{(Uh:D,xlO}fۯ_\DVyFWf/k\2,'XL5v IM[aS4,d +48/QxKEDd'{VwQi> fѩ6n5zqmIޚNuk>VֶJTzx#f(-Q[仗G~C(7_eJ"(YRZ X;TvPљN3eՔ1[(80EQ`#.x O~S U..HgI*1'k*j;ʃ(`KO>=&z(쭥z MIv Y =DFۤ~&~OF'dDwK렴ĔDPKINA? L!w("d U9@pA҆GI#ydGΈ$ ?KŻ$ }*wJkYEHM%ZcUVQ[cȘ06HD:)y$OyZ'$bcxMćOb_O7xG?#~<Ši1"ѡ5UIJQ٘U!}z I$m8Ms`/68e|/Hu^dD~@cL<0""2 * 5"(Ȧ(( (8* +˩₩1n&DQc%i[5ǦMjԨI44>99=Ǚg}T:++Hϖs''- ŏ;q?>Əq)S&ժt"_u~uyzYWz+TXGO~>/~طb-v7R(=zB>C,N)V|^)P+[]G9DFx!Ngu%yab Qh@#`52yi>ZUƏq@Vf*%cDuX;;M,$ǩW5Ġ1 㱟LVUG$oV*V[rcգ_Ks4g [{/^g A' hEc)hdc)E ZV,""[.v._iswr# kG>>wpelwUSVw JhYG%Vu.ZꚢZL-q"|Y܊TVjZ֤y-*s?RwTcxJ1lD%G(1,V aAي /иrF,؈lCuR#~=;iAo m 1 ǽl09C"J (EӸъQ)5UkTtFF[4b0dǼa1|`!vS\7ya&po K#.M ̣>0dQvMvD}}GEepcĠ`Ԉ\Ƹ5qiFkUظ/MjzbNs5MSTk7IOsf`f{{K9YeIPfRIIHJWzrҒR%SJMJM]j%7)MG`A,W}́z@y>9JTqd2јTI)& `ҧ)1ݮEXgޭX`>x7e8نV7m\30*ǔ.SR3(;[9%ʩVdLE(}t jK4l)w)We 7v2l {Emg6k|m~sn0(z8E BװH~Rr_&,K8p.+*.]tqíAaa= Gw1]_5 ͩPFs([\!k\>ZiJɩm*si-䱎jb`;6{[ Vf6SDEVFr{ 6xh$2.c}cc}ǹ}7TGKH1Ia1y5빑oz v^x2 3#jrK y36 Y+0;g6~K8N[ u?E\vih2@o!ނ18I59͌# </W/RK ե e_&*F;Djǒ7pjY`\ U \eN>aFї2gl MVżuؠu <=w'-]U'mu}r uvxa}k}Ӹ_C<ω <74}tWE/JD3|t*Ш-6KANw}eE|y\Y"qyW(29?9<{=;BDzQDJ^Gt<ΐ))y|X5<\i0w|G'X4HG# |4J=ͫ O[;i$Nb''sqbױsqiRM6Z:umU]K+T(L\Mh B6&B Ć m0ډ3??~:w}~{cc/V0]b -|Q_75O op}$1s4WG :kѡ\i5ϫ~j%?L FX0i*\ъvif/hGɋ*ɒ5Q&>d eEi׸?-Ye,-5jԪJ-ЬyC =ij׌!ƔiM5a<NjĮ1]ר鞒ה0F,Yڬ^FzЧ}c~,lZsLf1;5mnДEami21˘F-Jn\U c>nzRqU Zju~?>./8l>Xz{f,3qږ)Q)&iU֦-,xwnm~LъksxUa WާyEit-<3M2s36{f 5dw*nנݧG=9bVr\Ym(TO5wU:koÇgZI"r=I8ce^FːH_mUPY^g8[R&Au׎*X;EuTo͉[=?kh=Rioޡyd,}TckDָTߖۿG.Ljj7T2|[/iW?ճ@su~NB/ ]m|5j RC%w{jc@霑sE՝GT*^eٻހ_p7ά濏YjN~#?yJ ZUVnTTeOLCS-isCO,| $[[&[=>Vy54ИVA:R#Շ}…rn1*bQe\HnUCe٢CFS]C;'Ḵ{Mb?9WY73hzϣ3N Aۄ%n໣RU_*KT>`RـUA6 j`#e )>s2/]_SIǴ0:tf|0^ B-'F)ՃRuPAED6$dLeHKɘJ 'w([*H^T^r*7C%~(cFgJ D H~hObl3ɘ*QIʤ&*Lժ ըT@aتuL.EL%*Pl܎3% Ce{ˇvLJmϳ?ݿ}" JH%:bv̠RѰ$H@phĈ`ּ>5&ym xyX{g(b5 s/w)1WΣ0JWAJc6ԔG1 #uơK?C"<˚eße.o-q3<{>Mzmx_ShB?ʹ |5[By=g®r'oϳ.0gK2{9 2{2r{ 8|oaׄnZr1xvfK04&{CYi>>椏 ~q>J%?A۹B>zƸ%9j]cF2ur9ACa?/~곟B;i8'U9@mcAg|FW(ćW$ ^~Ea{3ظ!'}q=/XRl $Ip.G&& ҝjKt>oKOlH1ӝS{7$ۘ~S M̫2ґZv>Ϫ@VOS;tF=ğI |ݞpOѩye \0]׹ i"'kL>RXf)'Z:%t,ev+-H|';!.'v5LqTa'&3iB/mt9.hXIdn9L?Ev( ,r5^qOCr1/$v9u&q'-[|c!.yds.3: On1.̓ي U2E|$E/"|,||\q7˺LOgTT2CeO8[S6[.R^/i8:4D# <4(GJ31yJ}P\M曓Tp$:`v [6 jV^?!=8-:qHCh(fSwԫMԡAS4>. Y2a ݩЃj =!vA@{ql5[=0fO53\6;ܠICtgUaɚR{Xi Tkh79|uq 5D,P}JEnGBTaT,5VŶDٜ*e/Hy&)7U9]N%}Ik2*#\gsó֣T= W|$^h)Ub{ Fʳ'+מle'I.;FY)LTc|Pr:#x>3zhL9eHc_#yVR!: qq)ˑLS,yJO-QZZRL#}R\ z@IGeǕ6|W<h5 ћȅL|}^d+ W\QhŔX]tȑ_$4(c,J*t=TO\K%7MEF4 gR]AQg]wEЪ(* -, BmăD3iFUi;1&ͤNkNc̴L56i֣c,d?Y罾}FL+`WJQdv|dȕQ Jv\*C ~;+ιOcqX^8V±`>( *id_+;IFYIJdT'[y*u)ڋ'/ыp| <<_h&q;(@1τ;~$J ~dʼnJ**@0 :3"$ * !yURxP JlL_qÿ~Llu1JXbPt|R.Fz#ìCH Njų#aKgpK-/p PH9ĜE̓}O?/Q_µEgKO F+k+:w%KF.(\/Qu`;ϰ-DMT\~vPBsy&1O _?f4`9VAZM.?Ppxs{Ez3r [d!m\@̳p}jΫ)$C7XlaX?X6N`LM6s6U|RMySpw+TQ"͡|ի^3uK a·A? XWY q/O=r, w}qKCM~'q~g<>,O ڙzb/ku?#|agD:a/Caq0&Xku7F4(8!8G䠿&M sA ";`4"hu&x`x?NsfO8)w /:r΄;M6HhD9pɈH#88rpu\,b%% ~O y.!MwAQj@|ν:+OQ8|H❧I~E?"sphBp;C->Un3o>$}|QX5=:7j ~{=Hj=k? Ux3z]W]Rt+pk>\P\fFi3[GP'^uz|:z:~CE0-{/J'i : A ƸE+Zd$,%ض㷋\DKè!A6]Tyxscu9/pޏ#N[f|a Gb]m;V]a;l/nvS<7v#dr EA+|2;17bۊtf.v#ʎ^DZ=B]F yBz}d%,ã%2vb\lQ*'a{:sυ.#U{~=7QBy5df'ީ~.=$8#`; ۓ=beد~ ?:CZEKo rzSL9q,Ǭ`#vpFHo~:b&'2B". 8p@wtұkuԣj .3HxU32_ Vq G-*3VÑG&ȃceTY 1GT5Ii De=G(\jycm+U5qr ?'L84^zJKXk'/SIF-6X3k,!K.l-HWMbHQuOzU&.UUfRqJL/tBEp |'6\p-^~w[62UcJӔjTM3Te|S**7WUV㖫hjͳUk}Eso*!=pm`cmzk.|q⛃SbUeMRŢ MI*NS5[ֹ*ZS;IyW)7urR٩O+fL9p{HC U |w*_ԖTRST:A575Kslʳ*VDEʞT5#}2.5-cD55,! ¿4`$|e}oJx  b I5AI*;œVYKfnVbUQyUۺuն]ﶹ]n9 d'y^z|*|̍W%Yety-Y*R OGrjU(Ek &-V_vl4~PVg~”߬8Ki̥*PfYI(/TzT) jhQjE'Uo@ɾA%;Ċs2T\*>W?a;Rԃ|ǤJ pϊ|THپx&')ʨLiԪP*JnRbuDŚXFwlU|^U կ+|DUݬmo W TP *1Q <|.HF3ńٴF4P(NiO;JN3X3.kᡖ&lAĵ)0(41{$f[3K7E,^mfv)##ψvl/ dx:4z0^oQ&R1&J ȵ Ny=/亭Mԃ>!g}6blS|s>imd7yp.]6E,`c 5YQ>9fq/r9br9c/[yfg0% .mm,o:HCYk7f-Pl,`'&'ߡOQ!zt~"'(~sbϫ5*]Msv,!{_3hl<&Bh-TlDŽ0 ň2=r?F(8 a:tPuVr4%-|4.F&1BJg蓳q\E?OAr3!pFpvR#<+;<au:Qx\(.A]6}fJ#+{^8i=syS~}=*:+G /P]Wiԟ%.~J~B.i\:ops0^/c_>Q\f 4G5t̻jL?~ʹy -JCxЙOEh47jvP}hũ߄3,ji0)(' L5{ #u̼M`pEWhT՟W<~`;۹v0Ŵi%mx} %rǘ as9jj=7{L`e R5:%.Z;}Q`O#6Zm/u؞{݌VlEݥ Te е/iVқbX1\G.t욱k.l{]Z쇰V+#]Lb Y:1~6ktv 5bׄE g?RX a2)snM?ӳٮ:e05&9(Fd}{\,XH.&=Fڍc~t!셱ۦv,n/f:z43UaKH}$A+oX&fp:9/:jQ6LC8JdRruaĉc;ǗN8NvlDZs:M$m״ K֭bBJAVSV1Dm0؀A h*h6&.ZQPG'e=:3Hì1V*f젗 c%Xz>A4lsGX 㰔gKH ;;Ѩ$:u42to>.& zg=;6%ʯc³x/U|8fwcniL".|5ը\nsL]:Yuv0-WxZ(m٣fA,ǔVr vM{RaG^{jSWKVZliDҸZJJ[;lWʺPɲ1%(n۬mjS" ۧ:\G8N 6 CC7]'caVDY]-vJ~%uJأjw)UԱ@ 1E(llVG!~*h<G W^k[KBzNUy9-粼u7 ;\MZL3v@gi%r1O5m ջ+rW]'OWT]HU+ީJ.Uq}\Kryr{oj'荓@.pm4$x#FE[תסץjWU DJ[զ~UT㟐ۿA |EFpJ偋rPOtk#Z!kR]'D~vy*婩&.W0#gGڅ2j<4)Gh/òRYcm݆]h44O#"YePP\u9rWɨUy}4t'[d"kdlUidJ%#DN *\d ԿEسA,$!=P ˀ91B4B6Lֺ"og4t@ mM@mݍ>T𚱮ib8d6cLll&qc|-0'3/<~w4\|tzFaɪ{Yנ6t-#Hb3ı8VjXCc1dOT 3oce}~z.hE75L\=5-Ch,I5$so%{sIFMı817v0&;XTVfH3׆A!s++z ))"ö[/:@ndwt/ ıv?~ޗ}S) kyR{꣯s"!Rt{^sk^nh Ƃz8K!Lt?I!q8feep#TxplCN.a0UXR|e>oH])a0K$SgX'0ٟq%=y2ղ1@ۏk#VR+{ @^y3xޔT'Y{.o?$ %KE&<{ŋsgW ml}y`}ò{ސ͚:Lm`VKs%O,~ccl:W {ś4썓dŧpO/yC/s /d"oGG,~~ͤyIKLWW^/}_%Կ,jg'ހ Ufyw?6sZ) :2qӺ{Esxq~&̳gcۼ8m~v|;׉8iM鑶뵵)F=Cݠ$@cL ILHCC􏩈C$PP}~{<$% ݜ73 0(_fѯ=MgP^ O߰y ކ!$=~7V!Rd cse e:#h$>+xyK+Dgt*sB?Lm* у_u]S25t,v#Wȑq?>2S{R#aCdC/6k*< 3ϋJ\;-[Cw6Н@wY4:0 Gt7)T 2d V9-hm[=c0g!X=GG xl'[p3=ѲЄqQϰǦ![[-&v؉c'vة`;fL$GS\VY<:ށ(Na |ayjiȓ*ʝʕ3ݔ=$[愬epf(Hicc{SP2(:x$!(*n?/UK/w6$gGL*)r F%O9s* rg}-ckl@%!4 AhߌM-]N9K-uma*$MG+],ljj@iCePPo)CН$PnNS!6J@e4U6]?MS'hu>[w4qu:@zJʱ{-hAz<2Lrr®Y~ΚE~A!ah66@A<0ǀfq&m&А ឦ ]` ta/)q ĮQaE{HYaNaV6 3]Qg6{9d7l[ Pb F *e(P*SS J/Pʥj-2 ʴ:ڱj 3Hm-ɞt;oel?V~YpYKbr5 c̉ջc,NY{&Μ&38]p~ᣴX,k:gHL6}?ѯ' v ?mI[-~x;gr!q68wsΕΒmQQ]·˨#rs[ 7c?}&{vdVĻH"8sIKi&xA;.Gd##h^e~WN0?HH3(qe3~VpNEj'[ٜ;nG<$H9X< WU~H<^W^ef\. euqDINۿ^p᳹ϏU6K<`,D$+5>>ɿJKb&>f- | Ol.>IQAaM2z 2zQ{u΢k~8 p ޿z]uq-l$.%~u9Gem~~|?D~bz":'~BiUh ^VXe]SNڟ&hq48Zj%v؝lj~>^n.NC)u}v!~D_v<mv\pǝ;vd`IЈ"v;;eZu&v;#bl/"Vc(p< 4z"%kЙcp_/;muiG:ў؊ @ENA{;ӱ;arXeQÛ rW+b f8S a@䩾";=}ll>B~ *YoaT1v|*8=ط{Lcz\cQlz+۱ݍ>l`o6 ;s:>GNU QuCt~1lEоkپ Tc ~o~;@VdjYdg:YG-e:5c_ ;~σaWuMC,lr2ژT2c^y;u£)TE G7Y.wmkUh9WJ4fy$;B5ur%X| EΊ}ṗs&o/E̻,HK}ܥx#+iժDb񠂉jO˓˝lSMG;lqf܆i I|HbxSGdQh- ϻ|Iy"QX+3SD~ & y24Xr5 9gϢ)K{caq+X³Yφ$/"\Cedj(fsI>'ݲ=&=#U0?;ӼMvū_nF5#\O&~mXflؒ! ||e6;A+h9/)>O&d\25 r73D V:HJW xmǶAlcoC%K"K+>|pN+=`hiy׀)ޅ~F5}faX5 ZZ" nUƱ3h:Z+neJ;=HYB6BIH@P !Ѻ/NT;նK2x:ɇ0p=!?}f^LRpφ`@Vr@G Aw"0<A!\ŜԪX<71 1 '#hGw_C0" 5m ṫ` ",B",BPGbP !BpS/ t3Ϟߧ"$/0` %:BrXa`F6;XApٕVb\r>i:_PK -:G/Ґ9c+.q|h"|X ~5.5uбFl 0a|x=u04.zE4)x C$Hl- yױ;'jn i\ W8tl-бk؎nA pNlEMlaY6{ר` Y;y80_w97=Ecg@Ҁ= бQR$Ή {P1j` B΃Vݕ Yk`Õ(,7U U+'F|` ^EMB@n/+iQ'B/ paT/D;C!XB"0cr>Q88/l0݊M?xy~n07|cǎ0q)SMs^(d^^2l/WYn_zWl۾ܵ{"ވ־o|#G?>3L6ğ=w>1)BY"D-U5ڂ¢CiTSźƦffpvv]|nܼu}ŗ_o~OD%}y1<\'_ gK"0X8d$ D0QPp)#`@L6-F8n#mO@zH(=&c̾dݽz~x FEyy = % G X'$`(,K?W-=C o"[ ;=Qo;p0ȱ4Ï?!Idr -bXwAWM1 0 z޻}_>xo=z;xɓOkMuDT__ba~CٖsJ:CR Z G#e&\WfHKi h0a@À 4 w|kfdKeUh_ݯAųs94HASe *g)AxӀ n_ToO*HSoTb.W]ޠZA Р%4(ײ3n膆>nE$YL!`*_mԝ/QsР 4y"ySIfuaƹgc,i0,5pCu~S9Ѡriȇ۝+]xWY"Z:ӸdM3^Dv 97V0N6CC4N۝#>1tdBG*@C'ie$5hͥotРUrS!\ʖrz$N:Ҡ#{脆ƒn#Hi КʷkJ A˱)sNy6K"cwgI=q:E+6 Zg Uo-/4CTРa;rV(ՕБu9'_4qbf՚ *ʶ̅ڸ|5ǢT۳,8Ȅ#Eƾt^鎗{<6XjwУ-VZzQQYkF}QLVנϋIh4X$&}49߻w?cW{YE˫}?Q ˱lpWDL|rV\`ƉмVmӰi4l6 m{Pdžg0|ǐ0aV]ց灡F!ʺ[Kn۹l{`?)`oh@lǧ"sf\޼-RtɌ)Nm-në= 5e'#1=0htHh#EAg"F Vh•Ibm0;;6 7`2>A :SvIQĢU]1W B% OXoL[n` `Q/c×hޫF'Jcs_+!DtU3(˗vjYy`xN+1™-x[VJf AƻC),ȗfjkۭTkëK/ck$fLGz(6lj;^i<)7m}Uɰw>&t%4aS&Hsĉe!e;l[԰0ݸ/WioƮOW}/>{cI_ᜲks,p!m,g9@Ov.Rgu6A$Ⱥ[5X=ښWǖͯslwrl$&";$&,aqJ'=ʲ[_vwMæaӰi7X?ښc˖9_ 0tJddD'%x:,&rA>'>\0EEh`NӽGWpkz^`x +Wc"R,Bq&<$Lci7_uA[=kV};Ǘ/ b$fǢ* ˱\PW@i.wEfx΁HmjiHW#-]`0(̩ IHL` HwEĴϙqrxsvB@E͌:yn8~ ^I3mfځ6MmҔK IJ qCwI֣yGﻭѾobKl˖%[^ p(t4uU}\?ɩk3Xb?<1{B1 )ʠ)u e;5+jK״4Œ^S5x{z~q_=a8 ie/ŴxXj(Q@ӨʨVf =[rSPԤtuEhx{~ {/ͩ0/!=k[8P&ڪY V $7yMRULMogn`##4n%ubD@tPf*haTIȚ^ʸ,oe>OUq x -"8g3h.PԗMЬ] U,*WPW2M~K(d+\+x{ڍ^o_=NioYz!pg'ئb Z(e^ik{dEDUۆa}B{_k_ӜB3sޔJ(6y %<$iCPMAcqd"mnf:p~0HA\^0K Ì*QJ 82Eg`*)=P3؏6r[h/w`}o羣=\[u᣻nj:|ͶoZp7ȗ|ImKu:mlB%a50as5ޱwDGI^{Ivx\/$ٝh cD,IFIdB#mZ47"TՁ>m3V?1Yiޯ-:B}Ky/eN(^, юd,A#$9Z6mtoJZmio=aqS5ݾ|OӂSacO0.v8hx'#TQ*LIHLʆt ޜYޖ~0˪a аm=ć“!A)# xB1B 3QFg2R!@ R`, }owYr6[iì+auc71'R 9#lD}qNܱqZӝNUzuuk@zWEAAP I\Bx $F$@BȅpAEVԺ9;m-ʶ?*9M8bɢv:jh"(VV@ߠTei4EJtLpavwk}n䅜4~1+=n*(NU <L;sYINiBx6 _sZfFGܰZ)HB':!TUr_JDot$ H\$\VQ"Fa]|VaG ^j2#(Q6"*r*&!i"$]0 k A]0ݺ4!>DZр/rz[IV-9~`qL45z]ECmdULDD](ՀOICVt^DA$"C V[+{$SL:Q 1hG 5M|CF^kʇZx3UAPi/  n҄di=ۊ~i+zd%C6@>k\OX["d>Еq]iB6gx;iذ% gd9 $*MM//uxUakfR2ȕ\o`*X( 0,OƤAq.<1*; O[T{j8lQƒ .3&Ba:A8/ W=hS g4IC΢/}ڐ:=kJ]* *8l]Kh-nH6j &_ciS 3Ҁir`xaؚDy]Mݧ 1M&o Zr-s.j)kjTAAdGO۸7`pHGܤM$Հ!o?f*wm2~\?h2b۩z2lnʯK @1'TYY0FG)2UhӲ4`^2nK֬f{}Vm&pҁ-ZwZܥ5UUz(ԦMjJ m3GrA A%h4 `Z ЭlVy1>g~ |y؟~uG? ӷmHozޯ'|%:WS 8#^87Ѐ`SӏT]=r{L&u~C*gN{i%8 dp?3 x \aheeh jOy`~RMOU!KrUh>Du38lj,J0pzT~ޡ{&`jmյk˦t˸("R(HɼX&QoAqq˓2,ah6EeX=7eNަ ;63e0uOɧ4]jnH"QRĀvߌ帶la,/1 G#Œaܔ>ehi3~1k<ʞ1tȧiPQ'5D^LRMl)l8q(˛G| 0#xeX+)z 9Ys{xJ1?o'ud^H2kq2,9ʄq00|hahe>o옵fϘ+&;jpQNj$ %h>鵐ifqfb5\Éߊys&``1k{ڦ4vTᢁ/AɩYL"2B5=+ v:̂*;\q`r!=\= ycʚqOZO:ᢉ/),duPbM97Fz\Wjz{Be7&H΋ ( un̬uyP>8Z?]'[E(fjY1)QUoh"^jN^l^$oGs4o-Ҁ28>u9Ƚyhlu^sKO3;(jzIyD. As\5KT1E7w>u>3mu *].NQ!iWcZDX ޲=7B^UtpQ+.hD2-hM;[l'Apd:d;,{OHgpj]<5jT:hCjJ ]QI%d@ [[ߎA;.}߆w[|pRB\G;A-٤}SKUT*K0)!D=eRoh`2xo.cxk{wt#;]ds=c?bv> k6`B:EM{MDZ"VE Ӽgwo2oM{ ireӇŢ#3PS }fj;8wym>3tE`uÅzAQlnwG6{xϫkE7]HH ~5_8ɯs뜀gq+>~?>].Lm`=acܜ>"ˑ~RJaiVUXaS/%(\bxa@ @Յ e nH\tzK?Y)ƶX f#fHvuqҨFą^DJ +a]XH:$?y.d_Y«ѶOo~~ZJ^]rrj[Eۛb.A\Ԓwͽ xYbN8ww`{-CplInF'LǬ/F>-/,zTB^O>{.V~1vtnYHI׽{Bc{C: >gώP:}$%_z^US~nˢeϪq%kҔIe?R˒6^L|,Oxri' ޥ^y/ >9}Ǿ+22AnB:@$dPɈğ?Ǐ۠d~u9;3'ܝd}/Ds;d~>O`?T.@WY4v,dG$xPt2\11 ЧO| @<(1>0nN\x??G )eUMuƥ6-k8b#S͢v횮馐J~Ү*`wo2`i(`!8):W@KD|Ъj){g3Wzǫqdq 1>, Ay-"8YhfNS%o_%B)X7oǶ;LyeT;- DA  p[ZT ͷ4zS>KkL7tDa 3fY`l^{j{~8 &x@ ?= R7 EUne2^dQDLr9I[M#D%@P؆~?VN8 o @A$o @ (pM@/6,qkًxդfu㍼*d %vk\Cn\ӂ9Xgh ?)lń(9 R7DkPPqKf9T$Y?. c(w 5A3xی{6gsv` ;llHklԪa *,ђY.I38aOr791fkpoui6ٶ0 ( KJlK-Xo;_*%/K8 P*cK3\iaY< r|^|ǐk2L=>_USI;İ 6mNH OHT$+U=Td웒rl+Z3! 6?9(zI!73`zѯP^e-'ڜ2a@d#LҖ*1:HFמӼ(/J pEHy,pWt:;7 ^)m.3ȷ '=Zs&6qg 6q[ͷOG$$_py"!hgT6! !E f_+Rl.[buũ@36.}"~'>]W6SL 1f񌒢Su<*qOhfuqi6gAm8%h?w=Oe4Ĕ=1a$P[k匭sH_g7)hv!oFVϷ0&96gtdul`5( _YT8PG]s߉5{4;~elH&{aL0Ejm<,P2|sszl e1- ?N٭s׏oPʝ~w8 JW14Gu'C0VЮ#ԫ%JFWV]R-fE`%la*2 & 7Ym((C U5XB~dgr[7h~ }hč87w*A?:Lڞ64^or]҆Xѝ&jL/RiYvCA)Tu6Ae} {48=?pkbPVg(3]BGiK{hnzicgXeTCP T!١} փNt[>59w#;vމ)/)+F $ev+Ӥ(󻒔.RPtSj]Τ eGrJc(D 5f&P}j-~&swl&n.Yh)YQtвE~Nkbr[iWra;=VCjRic.TڄjP E &P)46_.K{OkVW<>D:Ewa>r:lHd(qm6r[uKT[|ks+AutpP.0Vhaf' ,լR:!]: sep1"@L)FK%tەYݑ@ 29!kZb.zۖ7.nޭY["B>ߝ1cEGC z)?"WWc{5: DUՄ/ jDA?iW7lZ7ʷ;[%NJd&Dr'IY\hR60r-ʺ6WC`}UI$P,1oDAÖ/V:eņ-`,oY/ݱ)|! 1iTܽشDιt^73h0!-/]6(֣5~c#턉ӗR05nl:CLy! a1Q_sOq!)%5#03g!0̃T2^6:ע4C_XW L: ip='>sCa@Ci4kP z#T=saTؽ;`fVg  ;`xN@vvG! R\!pJCPy8Otغ.̾߄?m?.N8BpDt=~8+[Z!H[Ck#`X 0- - "dl2.b" >c @gaЫ\BXK&=ה%?}*_Ŗ͐iŢIbhX<" JFA0(&~> C e Cfpc/شLVbJ-?k.A7_"NDˊǣ%cƒ1;;AͲ^bYgT2Cb!,OK= yЫ7DvZC&3O&L%Hq1|4JYqZy->i':OJ|C> 1d#LĐ3ѫorٔTÛcM'M$cؚr]0IU=uf# ȮZT!΢<0ZOsjӞqkuQj-"eA` @XB$d%!@VI %$lj@AA VG;ߙuzݼ٦$DbRfw9WiQ^cUT-U3f5URmJ*0P 5ṗƝK@ޱ C?  ;61|3$-!xUF1x&(bJfX,tf(FނOg5p}o1(f|Sv/%V})$;͚F.MeםuEmvC'hQCݢYаsh],^trx77n97Lw@,Ddu,B %k{=eե:uS.uܥʐt*ڿB۷/7&V,tOmx} o*<^DAxbyލ0>P,8OkĸDT6.HO:{9F#OV{xAW~%=3ϭ/?ulmWۂ%/=J=:U|?HdeP2дpy7g3w{jd8⇃ȀX <&(Gdl1?Ƞʨ13?3vjjqBn8J:j`G'`21| ;7`&oPh1G a}C )ȁedD#O/6 P{]䈪F (䠀Kc.#KqgKhpu?ŀ׊@ؿtAC}"c_zAW;(v@ہ;\BPn  :w#-ya~ C'z6 UC_ B 9t ;{p?*NN& n nlw p?8_QC< Lq;FVk)+>eRƜ%Y8ωgz4Q0kMa?M47q1콌!} Xu;1pC:b`!7Ey!%x„LiRK33oT-"֋2$+Ill2_;$'I$ʻ厐7Fz, \ GN-M"EǚT`R%~BL&6.dN(&pG~H988l' +]mE P7ȌE2&GrpI/9iγ"Szx2*}L|DjP'^81Nh~ʾ}8K ii1U vp9l Z$N0gy4x2L6AT'f=$7< Kl#&s)' /S՗@ A N*1hb d| Q&O%xΗL(Ɠ+jU) QS4w75}M{Ҁ6D6%h'h ĈADA pm|("F-lTže 'Z88kaVmFwII7 i~~~}FY;A2 Πq@PB ^WfΔT! sF.JsѯzJrИk8W\+e^_4 1b ,oB! APw}A"NUqSJxBrR9aC۴s%Ime]+nnYfSV)) !cHɽ_oCP% I/ ֔J zP*5aniԚ>Z*|a98fkz.7q{ʹ=O@dA (F0aDY0H R'uJP ;-ִWSXmzNf+2~D]nt1k%~fo2 0~Py]܊?K ՉLMeQkj\rU[kתKmVHaыLzqWb1CO@s0 &߷uasQOԑLe-ZyUqR+ Ygԕ[j2ZkkU6NQt.bA&b#VgL{BPz7CF7}V3GvHwVeU+mŲ.5[4my6kR-4UN#rH|jx>A2 91PRo<݂x.NW@Ʋ5΅ʃvz!0$lŜ KHH"N_Ԥy=Hzg04Ay,Ey٬,G} "}bg}OXeeK'!vD _0Yǩo"ȋąs^kJ86׍z99`t2~@2ȓCByvK߿靐E?)ԯ&X׺5\L^sv:F"ed? ƿK \⇻)t{]ue5yn4nq2ueI 1@&d tGeɍRR؞Z`nvb, S!O" Hu rK}*e:.װ~vxcOѥ$Z"oieLMoʲ@[ F{^ ؙΜ.zD{@,D۵rZ ?8rD݁A bfL6lL0V;f`Kdp3% d 7 l+Gq@#[8ko G-x ,=j] bOrT!H4dT2-pSbj'tC>ZMISs?Ç k LDFr$j@#H$C!ױAU&46Aw'(vGUNkp+o5SB!JbD}ӃP*CD}qIE3 aQ*qGt7Z#`&gV[VpV0wEJz@٦ }}/DІ.ݐr%`U 0j(6 pUa/S 1f-u%o/&|E@j R|iA ~9_y" -c>CzϐBT0Bh2@EjpB e(;`uzP/R e@SWI-A+vw>o/e<{g@|˚]b={ǖ lMi24kp/70D'^' RʚBka~mg}#|%#3a&ϰ&5==-:+ZQԣuTD+ʅuBf! H,'$!Ҡ("e(U(Lx@e(λO}s7i /l>BG/`X/Ш[ DՄ.3#6'=0] 3ĉjқ:kci!i{JFӚ0#NI@Z ݀xr 9{"=qH{\v[laSBzYF Hz1|`D>e1̦X 5Q5P7y7@?H @O< qzܻ,\>5F})b_d < y`ۣpnapE?tݦ,p89 ٹi$,~'<=E3ch/qǘcӬ*h䥄gx=?1x~M\!_;_[ 8> yȷ/5 Yt Ac|bIo#e\=;0 cÑ͢GV\_͘>؇:Cɹ>q%y?h] zjPo4L A f~ 'J8=leC5Q QI^M|or=񁬊@vܛ|ܛ,`:jp!ul,Ap#@䐏bv/f<#|`l \QރR܎V^N9OJtQ'i= G,`Ow& iנ8 `ڹ} 3 ѻkJ&DD0 GMIT: wc;rjޑnct3:S ])lG en G `2w, oo~g1Ag[$KiPyRT'5kkCWlǷiYjl|(9Uѱrfr% 503o':M,s&[W8nR)UK]^6a֖ 6X~%dgEl|AWIg)E b K1F|q B̳(V=1mxCY0;̂c&εk\,č `rlLjxcWʴ|Yu6NQaK:|a6.ݮX:ҝbMf*7CIC<\:W{}w/<صSS~ՍuquDPQT(bIl$$,D*0:ŒZ;NZ:nǵZP*2)UdK9}m^|^K.7VzaZjBK5}F_\c<\mzGiafӛ0ܻ=|j|4쳨Ǟ$MW?l{I]voqf"k[եm+UnzZh|:^Eh[m[?QIT"bŋxFR.p\T*m?;1te!WrΉDyjx,k#]!ԳQ>ňX&gk *Y>cȎcd%rQ)#5Ңq+QhG3bwF-!?&H#!EjZQq_qY_iRH #ܰ8΋ŊhM\ sp1nq9fG!~%d͠3Y /RLtFkӡ\Ob ICo2 : Ʃ:KayU4c&ϜBp,4? #G2_%dBR+>a.| sxF=qs@ ݄Y0)։AXISQ-~bOqp?;"s;TR4HH6•%t0 `Hp\"b4GvnM-13Vw_,Q1_@? `g]!gCzztPh á.r=3'CM*${yCBEXtY m Rw26MV/z/钼vH?i3 lhS`¨DFf(Ь\_ܜvCrH1D%3O ;r,jߥh@aEvy7;S0 A1lz, 8HA6 MPnK|bH- z9DWUB𘂠z'~٨]BfoU A %@ǰlr2p`^cI<BW(w8 V)%$uWT5!zJ _6+_(ltrH e&f|U7h2}`t06 cP2A J$7?OCj!L0lSAG~DuAYgV\7?QtR6?I:?K 94d0 \`Qr$TOCl6Vh%o eLpq__ӫڣI7?k~"-ցjWuDd !I 2 hQP(ThI ǭ{{̋yy~y$A'b*37EmJO%\OŚx4C  b'iݑ/f F}KF-%:v22vfAi:Oǡs=_H`0Z:*J?,m: 20% qqChmݨ6foT?'j݆49u NU<*А^ _b`406YAP24]f2e\w|D x~j&TxXp%=6s@4j rѐǓ ) [`bc1` i,p<f;/_ |A;sT!5஘I 7X- eI$->CX?\Ij(cO3 4#76N0 Zd{߽\ml׷m#šC.9 !ƶ˜LV]Q[j6,KeDŽ =<Àd0 x9h@ZjKf{p?pjw˓S?+<ڕߡcSX8Z-PKj~!Bl0{R2Y:=,VGr=/mDP\s`z[k sBfjv,t^<{ j]7wZu@E מVET$xb%Rν)S $"B˸D5ŕhڷxHGz,߾ோ;^5YovYcS%]7+Îj~jrXUPPl,S.)Du2qrgH\&餢aH8, DO7"@@*,XSiy}-z.h umǟѨ1yHJ%e+f% b~jږʑ!K餈tXHFy1_d 9i9%FWa`FN֏oU6>\w1ҧ"6TU"Oe!<32%Q*f<%Ii#b|TȖ 8)GjD́dtm-,_tmkŃ]_t_w]|`eDAmLpfV"tnKR%q)yI㲇%dՈznLHK B@ 6X֬6c7WG0}wv]:֋5-a9AZRNV T#$Jđ%"\hrLǟ7J#rn<[%/sڥY-xg ~5=?Xt,S~gZxB/sI$4IŎ gj/C5z*4 F.!gCȚ0 -Em-xlۀl@З}pƁ}U7ܭ>"Ϳ{IŒ81k5Rji`MK vXQdbF0 v<[_o7l@陣UeEmz]~?hn/$%8vC2]$ow/4WԀWKկh!Ab;,å` tYk24cGfMcݬ?Q }#ف!'Gz6⼆pq^o 7}:Y0y!`XNKg j,eUL9or^!p]/?4$BQ.X=㴞0&+Am;2]>0GzbL;Z hk ,A}kPdk-[me{Vg]1f=Ϝt{jx&{9:jo|}{׉ϾGt~;߁pF:0Yc>:̓|ޖy9ӡ7Fy:-p.]gQMy? q .,* l!!!{ I 7kKGwKU#-X+:uA=zL[8 B|潚|w]=hil*5{.]0wp3GN RqU"֘[>asbOn"){>G6bڸ-Gx}HY|HC4ЄaX(AQ> a@TNq Gq2͓$ߡ(2)*%`8z dE!; qL.}6D3e|4|Es262'aqh/Ȣhf3 2* (\GAi,; <As Ru t:3ALd> 1y J ' JCʀÄF KTaP-!DXK/ldAV'ɺ.g Ivg|[xbd=xM4d'ѡ`1IgB'^9pGCI<ے!ٟ tNf@x&v.Ywg!>Y/yB t&xCȀ. &E [D(@/8nBܖ>BE<C!ρ ُQx /(#hPy#o1&BPPCUꓠ4 ʝ =GBH#3 KGR9 &'}HNJ1&QOn=[}KAݝ <Ϡ#4>(:qLT}å A1(Iy -|v{8TgP^RWhʟk4Owyw:?.)4½a#*}P23L}*QhAd$?ҵj}jzoW ˦QӅQ9g0"7x&XśU@|e渱jGʰs)wtuV+neEc88ᑾx_~aKyrpf.l=tГ|{]Ċ:&N'ؐ=ա#1+mWU]GF&K_ n[nZd(0[mmECSC-_zl/yAo"ؔ-Y#zY[|%+p2\+9TcqK?gK:-;,J/Y_8Z4h 8NJ),9yL~#d+ȷ.ͱLlK2ȟ9( vmpo]_JSMk{As_%Q{k7%γfGpYeM>'( dȾWOz4̣a[4;Yp؛=n[m .ѕ++ۗn)ztAGd9׉+eU|Yy+׾ʾݮ~.'0FfQC5&2%?1Ad袻[~mC?h9|{ɉǪ]]mK:j\]Etm_Wly8yƟ8H%CESf_˖889v!5dl!ҴeFiK4L^XYA@3AZ6]MDj+.;fw9&G7%ƞgTF.8M$, %tIIlb樒I^֥N{:+vxof:4 kRe i"anH^lYXVt/#\Ԉ 5=/%z*"9z&,9j649j>$)j%=֓0{"_B4{YS.uEp@ k%Y5_qOfKf|Pw .F &BWLxYN\;.v% #<{+UͤHߴzrLNM~jK ODdg%222YI„)x䇑 ~d7*a:<:~7ǎ.DDaDrxY~nSћjᮽ&ʷmZ_s2P"wZ~ܙ *d 8ᇧOq#Rgy)~[& `A O_B'=q/n&yd,@؆%`mY`Yn`ug=w4{@7|I:H5 ?BHI t`{R"n>|bf/s/m!?삐OV"xF`'!,ɹ 0z}OX ҂Ag,7{Ɇ_g"D.ǃ QvGlYMtBt"s+]*W5Fh+ !:i__#;?=G+b `>7ҁO=3@$fAb"h%[WWGmtp:f}6aי D @+5zq$X?r'j"Du"֕ S g8@> JdHJ[Q+<: D3q,]bk,d;2{!8?Ds3듀UHXAPAK },N&-*unH2 _x+lƴEwÆ؃Q7Q9/9}pŀw3Wq>&!?{ԯZ{d>@V#֊ArArUU=,7J$6^Z^%s^[%*7!q+C;Q 8/DN&A-d_Ɠ|Ň-֑{@w. …lٲt[R["WQT;KRgIO{[7c! qe#C1$WLhb- #G4g _4egy?YH_κs[+▲%kҞ+o.J{IEeW@ܩj$>đ|)֑6UTN-g7G8/yZ\ИNn}%7,ܫQ=V!Jy27ңv[V-@g_Bidg'=6M%sz_e_- ~6K]nt^7 r 9戞;O?O9$w&8|[ٮ]ٖ2h[ͩ㲦ԷƴwI dgQ@zlZhRjwZOkCf>VEuv$ٳ!}*$\KlWv#Ir8}`ZjMk귚}#ꆵVE}Ƹ|{[)!yDmH@6o<l&} ԭmݣFyN$,P}U.+*wWdS6g4e6d\Kٙ٫NQdsqYUDH$[G dΥ‘2VrG6O]m5n6;^.{vW6g?h䷙6 [ +eyU; jks?լ}0RiN0-1VU0.{$mJ l޲T͡ p<߽Vԫ{58xthWflYWf6nIY\#-lTWO0vZn|Z^03 iMqTU?(˷y{)L|28k݃(7x_h {YGՌF6Z Ě*yeNfSkʦԒ4Sb:ST41L a&.&{S͠|>rǔmݭ%"J};uʍbBf\.1M),,ոLZ^ُĀ>ӐX:)(UƔLV&Bٜ3(CU沧iFuh:'ʿ۝j[W[Ģx=rzSS nW&./fkIiViqUX٬5X9SY׺-CuyTe4\ѪuMBXEAaIXE@0qWzZD REAPAܵEܗ#n=3v cNUԞ,gg|~zy}?ѐf͂1=ŧoA4ӵV+ok2?mW{$QRYk+;.b}˶S"{qIyy%w,>{I@m˶\6E~у*!ݮ3FtmuM原Tյh'ly}OqOj# Ǭ;&a)*>K_X?+w᜜}md}=@V^`O2w  Y٧DN6 u1ֳ.3&sՒ"/jT6慮;TnuÛf=,=sӪo2/ UYeCswFRևD"_IUǧ M%S,\RU\,=㰽CQ>wݩy'G,iY5-yc\vSѬc{SkRNo / Æ/?R>*FGRGCo#zTFtb=tG_]ҡkT%^ 1MmDd+/d/>08g6;>'^:1U>>f6#9(TѰ臝Dw]۽j/qTyÈM{\]ۑފ_q3m,k |VS\1s6zڌ1יӣ vyŴ#>3D]!h`?Utr뮈ӖO}[8:>˼&<ت};hVFByCx]DFvAu:yDgD7#jnfʯӖ"kNkzżr =ZkCO]JOxVcz>Fȵ=U͊t2T8w(C@u752ω.4>/N͈V/y/eTFWfɯfOxdחa3/N׷!oc.܂M |{FD7$/!5Z!Dul+Xvv'_=7-)_3{p~jZxY4C UClw~d5IJAlbY?hGXaD|K#Q;#JÎ7n:Z(3 BHc?d`l.ATVK\_0l_Lj*P5˿C)EpVCԿ.4YEjE( "A% #@#r A("HM׫XVG+VWZ]gߝ/g|g]ך$i VcjD0!D hzG[Cq n@=_\r}As}F} ns[x ϫAy9*Φ9|f9DY@DB(KD*׌F!.mz?2a4;Na1vk ZC狰oR # ~H{/px*ٽ_ LJjٰb׻ͷ=o:~y_#!|\qw| $|ÃQ>P@)wusW`Qn2#5hyR/ף5n3Q-߇/5uM  N :!x\$hB6&P(APo8.S3)mOEHd`\iXf6iK'Ed Rtv阽';' :>|$l*@zg!U 4S V, =vS^jR \g [ͨ.Ǭ="w99)xOHKU|%i t D0^y(ewE&:bh F 0$@@)=Į%Ωs?A şS~+[ovlLqɥgr"2.GRIZYEࡄc|;+#vl6Knsc$SA j)0@7b-ǮȳCcSSfz3%쥓a㹱.#->J ;,3*o&e=d}06ߐp]PW%n 8r r`d0q-=-@Ѝ}M>*g./.qL'꒮O+IX") ]E7!=*nFgfONTF*=ERώ\>fP陕}z;D/*'Dˡ9a~5i(akRe -D}/ =˷Duz|o.5-Bg7߿f6x@ wqo]GSI:mu~nG߶a6޲z1hQoge!̩R^[.*KחkUM/+(L U~P^^Z6j`0pXWwT hu:yMt52-&bEKh}]m[UM6]e_Q*P+K+njQ@ɵgCe"y;B;9S w!!tC}fh@nj ՔUOguUMbW]CVm7ϐNԱu/ D{X[~|pL[V)DBwNc=fh rͲ]5gm[Gn˞YʆܠRzBNQH~T Ș Ht@ĖZYpـp{C |i/CC._-+aNn݉[S;mŴݭՌV"0G)js23^;B|3$toL>,u'{RFj+E^O?dr7 N07]X!@*Bw]Ad Bc _ݤt{+k/7ZT_ks76mDna-r[;~cx|D_|J>KˎEћԂEG->v8T)Nв@]n|;)T{s%35q0Ͷm@yW5;dd&GyS-<D6zvc_֍Yco,dYbjmt"\8\ۅHMkD Ds;^ ,4㹼~ocd 8= TxV{ .\;vhH5mL¯.CwC׏ma3>^gsX~G[BQ(e>*  MCraxayFc xGaw$xKp' l`3vog&_$*BM# |Ʉ@CBZ(( *.\,\ xH` X&c ࠇW!fpU3+l?D"\" Hų: Ix C =q?/8T 籎簝'c??g5|M˾Erb(xS(b DZDhĒT /j!8K"f5SdZm$=m2] { -HEbfy"z} ];ҏ|!iү 9ꏨbD2wa1xd] ԠkyXzLVG'zB9 q h( F|?b2 ?ɜgfn3~_r B,#dX,TzGPA}1a4{W#"f2ς友#; @vȨAKH?0q}5HpvE,UO ɯ)cI n e@t 1W͈1Ҵʀ﫧4OmbEۄ?+[+M:VHiPv}>dj3q]3r57`g0o/iK9XߎM9#sdkQ5nBN y\8 <; ?QB+ y#p!uNxʶ [Ÿ] X&wg<%ݫ:0/<8S6|n:9@틼H뉸Axh|KD~F!ZS4.y} |&t3I l}#fr+Ȧ0k4f,9nD$s& J{jUwQ1k n$o<.x:rVȖQF"vIv$5 Jst0k울 NeNEOU{JX( Z0D] (ަi0E&pJהFߍyǷ ʣl2v2&%ݵI ť3ɵD K%)^U / Es !Bh`/ {o. c2{WTKEV}9{[I rU:]M/6 %}_7[͖7[|ĒC_dD[ :U7JHu!ܪ5*5LNe莖˜=jС&K<\YH)ʨ+d nQnz 1!Y*bRSv10x{J.7[$5; לvU< uSTbt<%7GEϒ׳dYa$8̯~Lđd"412D Xp;O눠kXMaщԭq-5ǷUWFRW%TVzeRkYE;')O'̝{/!s[Y)(J"j& pk0hkZ1i8f .ZU*+{H˔Ԥj<|/_|b +.1]$[=gp{W#vVvYB{>bc'ٸQ9jU#'!@jYR.:S%񫚙'+|*'88|"*;R%S"h5[KLqf`34&w3T1Lz-#6-.Y(l5+ȼ&WdC#- n Va#FpV#ZX+*_ͿE{Wp ``#6ფ!ly +@N{Ss\»JC:՞A=q;mAԣ͈zL(Auy{oq`w0@-vвuq1Q -q/xl#GN *v:s9>Վiq\r@ o/"s;ٿ}52GpsgN kdӻ iWRX0o39jUmW;'2w(tێLݒc} 9. ra ut 4|$@MH3v;b=IQ>as7[MΦ[sf fjvg:`Kږ:duȎ1{\E+WwA'@?@ίXΟH m!f[Bਞ_l쫏^'1)i}g6Ky+wVn|8x8]Mh_ο-3'pC"HvY(9yѡY&/J9hZru3W/~,=A}ny;P gD.~gЗL{(m# a!: 5px7?ՙSa20 f`FP"JQ,X"q%Uc jtE=.Y{uƵG"%( !;O}}'~$~0Ofh#v^R+uBW e{; F;m_ x(6Q}اD֍"j)]5GPps`|(|H?-"")bϏ߈5X/v~nH>6J-߳* .C4'DD8?( А:H>0ZArCOY yJLX R`Ev%,M4/q-T{cDAD 38Ӆ㡽.Cw&]mqm{w'♯E^d֬QSzɫly]jyh'P=9]}GK4wV{Ju#qg|&xBSFӉПHD1v( Cjxm#TFtfNLPɮ+( }߆}fDTDDYaVePYM*X&FM0.59Ѵ1ihKs޼[ą3r { ʏ2hnڒ۪1Sb_ǯ*Ҫ=RDna_Y9sMF"",MB0R߯iPQt &VX) wj+\ټwIl徼Tʜl~Yv)(NBQj& S(Xlaᮔ^;4>#80Pk=uL{Ӽ/xE}ZhBg./c$18%#p0U$MK]O=O>d(NGQb. w`1JD}P:}'ih`A=hcZU4u kbMeՉV9iҊ~-FX_r'N>++D8E; QB`4ԃs5ԃz{vH[Cje-ZEM+c-$u))Y$TzU7 Uxm];xs6pk bJsS 5PH3@/*Ʌ.3rev.+k_ٶ0Ӥ{,wdh9(w辩KpBr_:lEX z.,^.Vô6T~GK5=Z)GvMw[n̳>\Q缮kD{xv;a="zNϤB 4MC rfh a]';m$gxF[bFl6_7 o7䴺)AU輺ɡQA5h8AzvV,Ns!eL83 Gx*NgLбB㐱Um kpooȱ>^AwP~1?OH1Łi=3LL{յ3OǨޥzZtnT!ACӷyFsh"D3\p-Ds8I?DMy`%6U" lBgE b eJ2L^U++fMOe?Y-k7g]ew+bG)F)O+a5Xs\3 )ς@x+܊f֟btRk(j/˔? 'ODT up~ `$lF򙔱xV2eы,?xO{*PuAo_t?_#?%7j`X~|0^@0WANx絔Ahieޞ`og?hΓ|9g|Ht7B|{`'  zh%hp440ppX%B0H1Bo FʗRQ>= X=Q[LɅCy+)hEˉH #[!`|E~\BAYpS8RB7(ˉ ro }bL x`B/Hb͇C<hƠ3̕A#z jAM,H`Z&)&5t>2L$U)}~D^ KK0hȠ ]̝ACo l`rI$! 2A%r|INeJvv :2hOZ1[•XB\RJj٨B: Bw,\'u}GEugqSFA"3u DPAd230 ",BK5ZWcM=hbY-b'su߻}9(zy'V&q_ Nq%]ev^Hihde-r8hQA:'hE"[|}mqBLb?ǖ( zŨ-,rw( e}ow?$kxo%7WCgҋ_w?=߷{'+E;oKQܒ(['e8s21E3fNPxpz]8oW.Z ?Y̬ Y 0/2]7\ g'\e /p@w$@/#@oZP/^z~>+]}A&ݙ;U'Eb;w>3_q)0JƧ(:@38]z~@Iw}҆<4{~ެ>;ܛs\Z&Uٳg7'dY>=x5qχ&G<ޚ~f

#z}b!\ C a ZdC_E yN68=qh~y&sL?ݢ?`xOn>A]gwd-MwN6]V@A`Wal-pM9G2p:ҋ},b>H.p ,ݨ?$Ev/6߹r{Z6A[K:K7]`'QkԱO/&f~e%<疈JGT؃q=ѱ{#4=]7nmtۯ6lM%YK#٪w͡hOPc8O7cq>_'d$8,d_۝P=>Ұ;.AԵ$lSlEGtmMֈ6eY˩1sC9z:N(#5hWұ0e7gRYp" S'g67c{g7'upKJFu=1Ŭ-![ܪYĕ6/Yn"UVѩ6̥2+yy]7Li :Ƣ8н}I ڍ0۔)oS1ņ,؛m ;s䬞l/^g\Pu1$U)&uMCR.־:acE|sejkQ)Wjvţ3q$2 ÍxAe Z!3|gVglnG^[΢ DY f itMuZ<ʾ$ɱHѩII'ܴI7r/Z52ĉȴI0.x82LcTe} AO)tX6eiʟPj=VٵuZaIBC]U(ReS*,˶I+-K5;w01E]#.BdSc PFF 9Pg?\Nay4;ʛfq+ Fuj,ĚqҘFYdNʊmLXŠKhLX9:RXU[<^H}ݍkW J8 (8g6NZ`jNmzN?f`afnMPEESkٺn]6eyZ(*X )JYYػہΞ;0}'MZB׋ǽ2-c$)nJjG%W?ō'=vpUB`J56<ցYki3d^S`gꪉ~E+߷bz + |NXc.tsȥձK,i)X,1$f=baoy-~KU^)5cFi(ޔmJצJGxiqoMnx$p̆; .X$lhIix^IUDnIcDܵZ"sVIdގ5^u+7r~v'l3`Jy*qEX[Qsl$S}Fna)kֹ9[V̭3ʮ؇-%$}0=5P-gťʁi\&TwWQXJ(W wݣwy2df3]/ӪKR\;-] lI6h )wHp8_\ɞ:P;`yVCNdQ7F׍j)3u{&կro7$1T(c1f`6ɝ.`2Wûùf6hXt$ G<gSFcwAUQ˴2-Z-~ˣQ;"ijro`R?PTY@Ƈ& cO!g|&_$#%;`?;}MCO"h-ݰ} `;+BgDi#3~n`k/b݅ F I'3@9=.ak[,m03Lv^NOй^6Am?tuނvU*3N5?evSO Hflo|oa1:w4;pPA7 -`s̟ɹ2;ك?e[V`'` x@7BdNqL9ćᇡ7\.,P.W/{rg̎ X>̽o,v$'ehB| CG{"$(C iJ0~OzJclr}jO][B 9 <9Sb(T/yf(ў:-TDA@'/R'yN[ߛ3?;nD$_}š-&¸P9U^x<~4^.0#;ߟi%G\ )PaI6Re١Ԫ֏ k괶MM6ѮAbN} :F9UrꧠǕiE`_PKufT :kA+i_ !7!q6Tt-? A$b@k"q$>ǫPZ%vٱDX}ب]ti;֨ڹS+D7Lj:##ݢ{-T3$88t%|t$ˉWӵ ki-Η=>wqڹ\wYsssy6%6{6&]jH`T$>5@| q4Ay@+#Wӝt[ZF⋴dډS5?gcb)+ )yLeKgMi4Hm5M'UvSUX*iIXgk{YjveVc5 Sհ|w cemyUWo5+ o" JbZE( K!@k@E(޸junkn۱vvt;ad?=s9s߰NJbMH k) ^ ك{x s%' 0!n%&,%^JR/5|ϹR3qS։ةPG2{4!xW!s΀e$ kg|¾Ct+J\V卵WI*9}V8=0MTL$[ƒۘI=!CCY=2/.H]r³ זDظTuYc繥ΕAt_fMMtfv<gTF0즎Їyj^]w!S[lϩ mn6gu4Caͤ&s>*Ie#YBCDHYCB>9Ήװ{^.p!g 0e b GP5&0z ޝ,}`k~ I_Zȭusf털\;')Yh?P[xJ$  |s×jߢ7 A R7 `LRʢܺKeM "]`Ȭ3VVs͆v~YQaIH?+)/n(|+)1"4#Ucpу. {F[UQyнŜX[W]_]j6BJj9%m|cqP4*Ht+rޠ5~#0t`aB 8Y0O0{Ͳny\VQS (2UXEj/-唞ה^dޗd3MD1AJ^W%fA=X4By#45Zѫ ޥ~E@C]S_kͭif!azSz;\Yu:\YHUITf"P _]AxkC?4 `Cz'f,@w ;kW j0\Ž-nؾ$mˉuY [uMeW/ة)ZxM* u]xpNA{&q38;p;@57h~D@t[ۛ NDn^>pW BCȃz`uP y2cc}8ܻy3itu` cOx>>ޏ;x}~lFຕ@Cq \֥)bJr:ɣP-g< <ܗ\;JܖᦼUp8^E' 霽:'8^vMm -,U)Q٬jifM~/-߿-4˩ŸS۟*p-lQ犓|P:Ma(UOUϰfRn1MPm6MWf7 l0Ԭ7m\keYb׭Vh %? Z+jslgXgzj~:J[EJ,6PnLW . )lڜk\]n^bԼfy\d\h,7W9aSs\ Nq+H eu-??;w WtX1QcJejtȴ* OY4KTh;7h.?~vP}^P}n#~zБ]N-:3.mKvʺ{:+=TFiXCEqYZX, SvfU6zY_L.4W:~Frǜ !{vziBЏdO%⹷7ubM7gjHwP,,ΏL떢u͌lsdvq);|a\NwYo _G=97Y#Y.{{3~,K`E=^&W{^VocvJ4yRp }بR=9$A_ٍCf =s c;eH~kZLtNr"}zpppc-4CJbe6%%ppj\&#}YI %)֘ꌉ!;_3T#R4b JIOde7 1P,,.V:,UHA@*`-k1Xb]QQD#UѱrԊ:k+ڙs@wŤ,F/(GFWύ8;jSxTQWc(a>_# }xk+$|dm8IZ%BN(If4-yYrR"!1ba\eLBUt|M,9"V6:p kv A>0^舶Kgųf] ޹>-)9;r=$eѹ~Ȝ9aّʰ4$Khz: w=}lIV|(fYb.sFx <%!e3˦˂KQ~-'-Vy[M(Yc^IWؒSڎ]*lH!)6=g;ؖm^!I.I}*$BP# `hKWjlҪP3yU UeXxUYRzVnQyTWW+>j a^c{s2|s@鎭WU[` |7q8P3kH̐ Y I{6+1n2w55w1lmxk:VXX\s;}FZ:K+* <moԪYG]׏[\?Mx,i+q1K6HVȆjdCLN2T+䃶^7τ={tW MDofm]2 kPO  3CwǀPosc6.C}$NKE%q\[Hv l#z,za ˞u?0 &5M:0h`<c=F`ӒrXBz\U3X>"$d382;s `. 00(лв]:!e mv0o E2 N?!kvN}'5) i{M'܋HDrA..iT5/Z\/_\JyC2h/`pB/뭐yO33OW:赦;X_*8kx!v7\[cی@77,]N)KOgͣp4x0mځ=jz/ȏI~"r~T<</qC.נ(++7&F,(,ȲܖEvvrY˂+  ".!xCEh&Fmc6If:i:MSM[vڴ}z<_9y>|e >X6e7pmŕOK\@$ dXqu,xFVe *U-])[kkݵMp={aj1drrr_w~ko7CfC $r"CkKGmoWkqKp/4 nRZ.GRZpP9E;}VC)g~֬(b}Bq}Lq==WΑHH둄CHW ׇG17r}G͛`!:)3aNi(-)>)wfi^Qg2z{88w}Hca kl!Mw07ߟWЧ>(U Qϊ귙.=CӞOQ[2 $<%b޿{?@ωlsc9ʅ49Lføv33 @fkזs5ތF~OF-L/jOJ[>})iNؕND"BWO_zp}b0L &tRݱp@Gt>ի/`wg[]6^g@ێ֬@wV?Ӓt3Fݼ^wKZVw#ơ#"$9p7\G߷`=` ci`@J0C1)Q0󊸞<+ߝ[ВrE 9{NÈaޒWޕ m'2H1D>O1wW9K(D}7 A) iN3X&{m.,5V4 ZE5=!8)Ae_HSGD瘃[xqz~\__z_ΒhlViI]lvcI>Yb9Jl5N-,+̃RaYLPZIXn6iH; \>b';(}-ügyQۼxQ}z ?jXxc^.=.vv)jdҐ0@+w(RV, Ư\2ZBm6^V{Nr1糨{{i'҈ߕ>j@k<ɃȣP]S!> kjX?7vy@E}eaOp}P, (q]ՠƂADET,NPXh{,G$1qu]{Xۏ{@xgygΑڛ%_>`Q2l]f(2C/)멷4y赌A.| b38~Z9P rxë;<+"Q1ír\\p4éUp,2!9V3yLYǻH?RO VF*gS݀cju#`WDak261ZCcIڲ*K%\@]+!=bԝC݉Eݸr6ԯ_ȠAVh6#GdeYPV: S^ jO-Pwm.߃k=?CIl3Yw8ߕF6eل\dikbR5љ&+"CV!V`zmDQ7+|; R@.Wtll]> 7 Lb|II}g'&w!h!y6N(F{;Q׋]# DuOrLhv/C?[7lO 1yI#_ҐWhv<xռmּExD3=桍i<,`!Pqk6@kA? $#dYM6RDJvRK!u/+~xI!쨭PpW;H32$t䐍dur .2i.'WG ƙ5H?2|B>N"u9RkC:k%2SVo>~CG7A8RWm! GzjXjMf|tX@Tjds"@# ~I p'4q7F \hK_hZG9&ۇGx}Lԙ0&He%rM8O_ŠS 8tZ%#R9SThgG8A'5qU˲h%|:bN+qJ'98̃UYê 4jpHՀ&|W2cjAxQeNW^/'7~}6}pV7lGX3`?`8nsWu2:AC=84aT9F@YBz7ˈn.yJ\C;N;tQwðԹGT{$aL敃*|Tx{JHfKi IA3!!Z=k, `;孁Pg} lʎcPR(bdl HVJ TX)Iy'e~LY֐՝FRK03Ov@ol=P4[Gas8OgHy!s!) !!9!5!U!쐣eOKC"#TțY?]8iG,=c~3XP7la(<`G`q8AZc"[eLeʳƕLFEq2ݸS^~EX(\(I< ԝn_>|r8nU =+LXcFie%-7e&2Lt\E)EjZL1S-0FlSϏ8gj1=6 ,Pe s :W|j {Kھ>XX? #e&5E\F3+Pydvf>6#hE ()Tm(O|ǧJx bca@OdFwƒ0XiQGdcNR̎LNNγ]mMV71.!Fh*a`+"}ccbuX2qH &̏(͍͎)K#"q4!SR4VhuGEyafav .D&葨((("0 ̌ (qh]\Q0.cMh4rZ=&Ic\kmm&A;8}}yIirjIjI4j{'JxU?3~F[6a>(ѠԦ*CPnH t$=WV^PVOW5MߡYgMYHc֋*^TZRES.qaQؑlZVudD9TfCi*LiPlJN]Y(_Yeƕjq&˸KΘqZqC&#CT ҏ}mf`69x%RuԘTfbK0ʬcQbBA>dbJxyhI%){rs~0AZy(R+‘R9HLT I\E4L6-U]ު^WY>J"r,JB2`y)PK8]LWA߳H^FB@̯}a瞂hĺ0ǝ"ĸ3ndX宖Ns/nO}M><<P{ ~u@7hYGo ڥŠ$;Fc@G8;#\<өG]  <M hw=n];G;65+P`0^ہN``~ jCp(C!EAeaqC1}C"? 6je6րv1.Ao8]@8B{|a#hB>n~psynu󘈿+27ԝXg&Qs459=@{?0# pZM3lF{p3,?gyٟ!a{(pm>/д.d/`=fC70ԧ'J"H5K\~¿ƍ b^?EnD|B]k4RCIX= (z%-BR&kOm?rw޸p0>&?62j4hGLAIþxq1GxPR*Ǎ+GsMԝPS20l<@?F-5Aո޸5ZxWXwq+0"<⢤MT8UKƱs qW\ %uW7hZpYӉQ\ňv ¸C8? ΍3n&<ĉIdGoN~:G ӊx0n11W&%atrF&0- _NI~GH) ^?`ST!|:lG0V#ӝ84ߛш3۱j웹 Cv`p>ݳ10v%%U'8V? _LHjȹ{<3&̬)8>'$r&cp{T`: 5cgP'vö~ak?|^ .l >/څCք|/@܎FcyG92]ұcq6-.Rlw/# û º]bO~qui;X\/=R}F4XLk6c9 b r&G/Ė$W|ٱVW.jձ*]إ[/vI!-;*ޕb$7SjU=c;3Ҙ?ov$/޸ذ, Xn}+Ra%=W.H Ƅ'NQ?RjjWr^\ Ekp4riӊ 2)I~<'yNGWJVRn0͐/BBl4ԉC6 rUe8T.j* w4eߓ(N*;STu˯lU' j^,^h71nFȘyP"\ֹ-B-΂d,NJ`/( bAAdHyղ֯dۆ4fi,5L}2dZU%3_S11׫=W̽H;Xx:O#c㳪EpFIB81(rБ-6!Q"ګ{dwY>ey&& MCMZMZr4;ej\A+XEq 挄2r˲S/dSYlN)ݹINuVR55I4)I%)RCm|GiJ%i"ߋk$UNjr!ۥɕ,]]EBLHuW ]򲪣r|ը纯UUT U+Wg`/*!mMVXE] k#ݳFz}IEDŽdAyZ8Z1~SIOrYSZU!ϸ\R㻤Ž@H55 IFJd$LEb<[ðu ⽉f`ׂX.omBw{P ޻bh'bh*6FU {'Za'|/^@,%#k& jU8"W-EĪdĢn+ºKuG|qXYĖ,$&niTUk_p "$DԒPJ2UcLUjj:Jϕ:Gr#y<꒕Ȭ g*]FhI#tM#44B3`i M7-a *tfpY Sa*gC~mw@^dQbOE*<7Ps#)7Fay 믐  ̟j_v;\y)`jcmAv3yf.fN5`={e!/b򥈥Rpq/R?- T@iڔʿ4A~kS>jmVҾU^#_WOjYQx?Vv&gR\)"K/ʥk%O<Xp1Pom$5qQ cXFTޕe) SM4PIYhx>]B IϕR)51JjIb۶21 ocR P RCk(b Wovm7) ĚzrjE oTK;$]++>v۽ c~ǏZZ}-ͥbbjW#0Gi%oFɺUh$/5?(G ~ŏc0$~b9EQ:_|F^}I;l 5wKa MchJV0E:\:Ǣt%B{ KuL/gds2y4]!T=AOI.?H+XMXPܥq>gA*KczM#c/v?>>~_zNo:ptp0JSjc &C0&51II1/gה_q0ބ10fXP+` -6ПPOls&\wV6= 0a&~j [Z=W^u_:Rtzme.4+k4xƠF )O ίu/`@hȉ+f7r}!>w7%,gҹYn!Kktv> KP_ ٤4*3ZzCǪljjm3S/`R _Z- N!Mhon6\[b6R\wϑc*=Vc=?jCZyF+n{>@NZ5/bF*#r#7i{YQǍԨ+ƌG(HyNd7xg{=Ê6Wvg"7*l.an ZЭ跔=Js'jvLbR53fg̈YaT2c?5b/ScSbM#I̯\%gˌ\}2|))enE1>=*U)@=Da)fn$[IcuhuX&L;by7q3qFzWhD{o͌ qڽ]iVK4+>B =5#>4`%ۆ)6ZSmD{d[1ѶИ`+UXj,m\Fλݳ 1g$b>ã0{ KHe K"I&L2IfLB&$$C!"ITBR, @!(}cVVc] B_Hg3s9|/>X$E ҐcU8E5IsT@U-wdґ G@2#Xa:Ŏ;BGYn;[ycq9.YK$_mqg.j]L,kc acSUU TE<',ݩӣgFsQ3Lw[,q+'+yN+fNj?g8IK+MuJ,Ty]̈Qif3ȝ;KnEFk\mǽvo[Vr_\GF9ƱlMԀxꉧ,'r`fE8;J9SU3GK= qɔϛ\o@^o1Mfg<`9={4cVy+󱕒c}fCV?8+/n-xBRgT7\c_-or}'w*Q?_n0#b&w[I^+Z\xm&}$=o%PF0 7f|>xhA,BeVVQ2#*RzTVj|&)ԥ`- V(!x lc 4o2cؒbی-͸"ۈ+c/bO~o&j`C5o(]k(FӜUʥWj֪"ͬFnԴnM=ɵ(zۚ\16&gJm<h|Pu<شZՃ4>\3 i7ѴxMmthJcuC2Mjӄ6ii|qkzCz[Qk`mD#hl#Yy&-)tS4s!&E:TKXܗ.S p8.jkaR3нAWe4ހRbc‡/L>e~>g|A`fNmh5@8 q P`%:X>qBx_]}%~1%ޅ&V#7B%B70vޯեh>g^}~$%zEs`@}xËWbCaADA z,EL Fe;{v0-[nrt#Lqjh8Чm>GulꖀiEP0'oeX׈?L0?gpjJU^lbPx;w@x#F7b;&"awQ\r㑗#G~-QXM7gQ;O-SQp2"G#q$*q`i9-2 v/kΘV#cak6X.#/a86`Cj~c>11_Cqy,$Ȱ31;VcJlYi$+6%90HAOPKL=PISA&ze?Z#tI %UoW9R2yWP~XaJy;RU496*pz9֧1ڌv d?}ѓݙCM7!Y'KG=2%|'>KL!rl/碗͙s1  ec [Do=9 V8PxWtS9ڕ{QNUy^ g#?¡3m>K,;&Ygɸl`\*cїyŸ_΂j ([ OaZ p6¥jJ4 ꚰ>ªzB$a-@Sf4(cCO# 1.aV-EWQ|řh/΃D*.m^4aS$E0 u3J$a"?JE>Nśi^t!:Q%,r\pVhЬEv6VZk`n&AaԾ& EQH5咸Oͫz4KI='=駛qfܚ%piQ)CSU6UhԕêӣAgF&}F F@NZOIB[%*%qX'{j}񻋿UZLXj`-P:FC#j -1tBo Ag}Bcr:#w#K V5HA 5Їf$&"p|wHdꓰb | .&7P[M`븪oR#$32R$uHYjA\, iD"*cDAtH8MENLm]'{LwXǿ *pʐ%DqEׁ /BEyjMl`֓&8֪16Mn?H}~~=~_Y⦎%( )Dn(/WS:`ʖ@Φ%r2mKʡ|2LhLcx, W<$Rk3`\r2#s͡jgQ[ ٙek,3ƛvsZ+*Pb[嵅OΗg S3`VjeSˌ[ۑCh(u:.:.Xn0g<̙+[F_sa SyH1g`^.@Us$z 4fp'Eg  m=E'{xK4bX94s퉮j#MCd;srÎ]ر;ر;h(|Ful]pwr߇ {)5՜ ݌>4Ap&B4hΏ{Hc_N`G#I#ůKuX4`;1'-cٮqux-tɞ%CR[1Y~ւ}8694.HbU(Mm™&>v ~fتnc8!;ݪu.4@W 9| -Mywt{>Sӆ#I? {YrU nGL_M%݁{ց 0=&&OVۃAcYp drXw@0C̄9P eP`~aY̍;ټ' K==⭇܁uޔ_8 l4r9 scxƎi )>s]u ~˯| | \K68ش +/cHgi? ؂.c*Zkl7ң49Y}]ZZ9flAMOŢ:#WϚdDeo{g)Q~hAN^Z0UiEUUnE&herU|w+Wrm]w?<5nk0I!vßWÕ_n/*}cJ;U *4X;<1*J,{T\,POfӌov?)E]C)!*mU2a.mTAE5k)7Vy~7L9ɚ?^3kz7P2VkJ6Ҥ3J &=UjE7%gaz<+Ŗ7fn^ jzM9X=G(eJSF,BW(5x&k\A yOcB+%FXZ(.EQ6XU<+Ė|l%69i!]552{+w >4)l&MPjX&и /SJ ج%E҈ CE#\ 06C9,{rhaVᮚɑJ쭉}5 5D㢒46jR'ktQ@#bjxFOCcNjH, Q-נ\ZZ#mPGjRRc<5>_b5&.R)qo%jd%ŧix|4,ޤ5^JأNh`'P-?<*?we1 $n "" 2,0QNHAA(MqZ5q4զM6mzĸ&ƚXa9}"ΡlX?m _fK1SU@Y(/ir'+; ,E&C2 2UZJRSdHPR>%RBNJO %$HrT#,g= 3 boeȜ6RpeE+#=ItsjLJ26(\MG'qA;Nw(4bS:F @QU5IVcwU^56=VS5Y!r>><ekzP )iluOy-P0yڇ>+7{4>]5o_pS$l7SO7=ϡ~z&j"9Ff3A(h ܚ4K}i~i<[dZ8ZL-P kygຈmlyh*^/|3Xs"kĚC 7IÚ%%m,1ϵxXE# C N01ҾCP"p8iFjz͚ 5Jc{Jj}?@?6f p뤰;YT':ppzybFcI7xZZ+ow^BmxBP\wFzw>{pbGs֏ ŜC9VM(gU8@xuq?Nx;AEquO/Nj[9WuqN ?%wŗ̺75f/NLN>V 1,vb{%Ө;[|;xR>prWJU}s_DщTMNΨ@Ə7𣋼:~ŏZu[8}D|E Bm'|.85go-/(t"шZ:s_lخ|l6bsll29=قldsۮ"G'#$:D b]Pr\l.`w,$ ϓTVWUD̮r]9 ];A1B9 (hr4*Ѩf,Ry ZDd+G#r"pvrԾѿ+`ܵ^ Gk4:ıT-TiL\Yn0˰/2,3,31 $vcxKʭk7V괪*RRU~V.Q*Jc;R{;G: rq+YȦcn:JFd)ﱰG}VuWj폴~UeZr6f_T=/F|Tg"S8%S[K8]ͱlsrx[}嘽,Lr fÄce.vLg2=&> 1,wvi9Tk%?k5t2Y$Dq"nG9orj8`!E8\IL&1B(iK{SH9#3jJCq'_vDSyʝi%SK,'r %pj6iLU1݌2ьQfL4-0`tݙ2y_ d2LG_d}>'.zi{XdU˜jɌf*3Y&w/4i'p y-0ws_c=om)]Ɲo6t=&ezX✖.kߜ,ȔjٯZ͛ٗs J*fwa=V|En+x O=ūt?*%o^ΒVGaֺ"tQޓDY3%R=V =xz1{GN]a92k=c`~53tRLrH[(m $`H#Ϸ\_!9 }ue1ӿH4)$(~I$ =5XE_Z#_t ^}Wt,RT$k$S @:;I Th$9")Obp/ yvOL\Mb&&+#rrC|ǥĠp!ҮZjBVCq$Y!6BLaCSl aTdo1'"lgqHLݢէ9(Ji+"J_1uBp:ع DSbsMa}aܰnBywx fkf?T#VJ٭aH=Aa+\89JI_4)ҟMDZYXI׃(ORS_US[Ƕ\[U\=%=@vP5,O8"Y=%]6mzI0H_)K0l>.wR )ZL-vj5!/Cp'V54Xք,(z۩g C|D' z "9&5xZpT% -vz'57` BcㆎS}&Tyi0(:5 : HtRwKc)j<)^xrS긭Mz[95YiGcݲ9S OkI7e.5ӍB 2{2ceey(Kk]XXXv]`9DPEEE-}3Ѫ68ƨǚ&5UcըʹMG϶&iLL9l?qg~e}yG㣍 Y&FaV[O?r&4ݑ Cƹߢԩ~?pҪ 'Ki.g]l穋 LhݷS c)+C7`?vj $ur.{gxhV.37kznP7I7M;*D2f;y6U+6S|}.UXzM|;]jsrE5zH]< t9}" v@ Z3a,tS|=t}M>|\sOzO BVȆB}24FQG@Ǘ9 3ЕbA\Ru!u>}p?^0zݣ׽C.RC('~n>_~fb/%||% x6Otk?Sn)qG>H^WBԟqsϨسu8Mhl6uF*ާVc%>V2e e摍ϯilJfSQM49αͷhf x%{Z1p"ơ4-6o,P 4jИTmnq_x y-5+8{wn}W0zh%KdhVWfvWc!޽LӺR8MI~Tc&X[Us<1=/gjjb(Gˋla5øph?YCif5iJ_&U}M (Q]HѸ8C5 TFU[UWo<=ߏ2pFqZ#-93#gjҔ>(BlQmp֘~+~e_UC,dlְڪ!T~q >O ИUEktI"2¡9*PJ4@);҃i Vgd(͑TG9du(9YgdrF wAF2:)SB}ځγ$:P^ ,g3_Yٲ5(ۢt%ggWk̮*\Jp5fuoQeEຬ(]EgS WgђL1P%PR]e`Yr#+sY<9Sg<);S2Ez7+;y*sIaSDn[X,4&rP ^pV,o4 P!2WdU薡PE#Q4NE -ZE'̃>8dY]p9dj FEvǮ"!fRzD1j56$HӚ1ZsL5Gڴ4uSv~LLJ=}}}J,}Zҗe-=/kMي\!iZP[OhgJ(~ԏ0h.CM& lXoӈ`]~񣇋5顸{ ٽ ]k4N>brK $B])f:[`ki8`ogg~rr9H};¥{Ev$9P,z)YJ\BcU?t-=7L0cQq-)8ť|?ct$`]9sMxB@w~DŽ q` a2B5XXQfezE|^&WT_?xNDH x&@QGՠoLNי1]e ?>Ǐ?Y>c2D|oI9d 88>//w@<)3̤NL ?>ď0՝?{wgROyN9%x%cd5^ \{%e3)/&.lخlln应wEVوvϓ:^<@G!.b(?hDcy2ĶuDڄ]?Sm+_qх*?J&v%} (nC D:\fkmt*t3zs7]/Rk3ɰZ嶥jm\Lʤ"iʒUTZM8K[T`T}wj9ME$QnrvJˤ3i ƗR-gE)v8T:Lũ#5-u&0PiєA^MԬI_ ەO_ kx G҂Ҋ. `+ܔ9"T0k#Qi*7eyG(AuY`w]`e]]6xM0xD⠉hhԦ:M4=$ΤvI۴;^37{y{wiJ>SMM,)O"t]-)n~]6pDo}=׿%؃ M|!.oNP9M1#U3&_,UVSSE嶶i] u.XwzHb=xpgيlAS!|(^UEUY\QYM29m^a,-<ٗоY.e|9)-0pvӍ*-M0 &]*pĪ̑,Wi*-5,TRŮ:&5UW27j{/h*u]9rFc3e.KFB|P e;GYli*.RQyVe(S^&OF{f)ӡQ]FV>L+y>FG*^3T͑[|oF׸[SQ5SӨ|3kWo2|ەۯ4 \UZ FoTQ=Fh.& B }/P06Fk[yoHCY2uLRz` XmJ-ocB2)f(= &rkxȧPPɡf%*!BCC݊S\bo+6znڌ5]0Pp]W>mĤX6&*%p¹J[4,p(.ܨ0/6&|f,4b96Dx5ƌ@=|mA{D'Rb45AC[R@pDT#EMaP<0iBSBca<}P{{$7eh6ugrј?v6ʜMncښ 0mx9c8GXfH⽓1[s)V)m)nql( ".ɣ=åM$wc:<_O&(ӧ &⩒iX tSK(kRˆpp [eg%yt2'9drcN/8&s-[ֳji'7UjCm^0}ƛnr ]"W4y&걙ztG7B=V6,Ԣ\1ovaM]QD:Ro ig3tt:~͍[`+<(f"$#I̯e'{5N1bhof=Cc@~ Wad 0*r޸ΞqM&:$fϼɀ$`8dA>ؠAd,-=qB~#M][}wuO|ʯ~g ryAXzEa N n2.SY4yy]C4b9eh'{̻Ja,#tZ\S Z!}5}L>U3 xG;h^ms{V3]8 Je|INS4hTO[}?#ĞIybZg)W*7eƻjArz}}Fwㄧ ShGV4\ԭ~b&Tb n_}ث ѫmM-v,ϵ'`| />g,ƒ8B-^T*G_L|7{٢mӉ9:w [iɨ Fܤ`< W;k,ExNT2yg?fۈ_FtA7 Z9#9NZ֓I:Y' \9yv2È?#KBh&t0UjgBF5׏p6XfƱZtR'e]o;v.p8qNlp9&MNv-mvJWrT+[v h5[@QZXA\1&  !:'}<_+Qˌ7ъFQ4$M,c]OxaYEVW^eN{{J;Q>!ctM:^FݏNtf6R;Iha:fmMEQڣ^C")RQXs< uM!}*FjT tj"W5=dƲ7k 7,jpV7PE,+s_ܴb%4J{JCvJ.Ym\)Weʘ&+W*ߩd~ Z4ZHAD˜*@#S4hтk"6P:MAZ]ƴwRIJfa X<1ٔ0974dnҀ9~sb}kIieF˜, WrFAeY*]YzJ9ZM `<ĉeȖ" X-V(b ֣.:c 7(hߡ} Skj.7-}G\ܓ<:B %CYXc)O/;Qb-SOYrʫYVI6+^UrD~ǤZ[ث&xFNjr;^Ɋphƒ8$:j0.kQmRD5jq*P mZjj9Ffy|Bu|A5WU| qOPٍQ4` z=^0>Eü^P.Z\jvW]/ۧv5GT_?(g\.&9=A6Á23|43 #7964U_.4&ab1۸zsVW6t-ribAL"c+ǶDObIcN9TYPs46LJs;0c`w^@nwUf 5V1!a5&9f6Ԍn&لnތc+Z$_-xIL|1yyuz8c}:`?GgisyǼO& ٷ=0ۃ>9g4OdNi8)<|.[O+q8O^aX\ūÚRZ#u}g\"ӿ30+FHaW MqM7-:uqSu_qp?a`ә>^h^; s͌I.1_^ }C~w=ue|>r,!݆!ytVLX1K/W[e2c̦Z^ً@'~yy_=ͫ O8v?;NDZ%n;7zImvݺ6[E֪] Bҁ( ʠ*kT.T`@`m2sQS>w{y+8!hn X_8wp@7)82}]c^e?̫ <߅o79|NFb-COoc\#Wp9/|^u¹|<~KhM^#80lO1|e.c_ރw&2؉_3/^P'=C%i/pZO~|1!} "zARBLy,|>Osyx4c$csyy0;G{ W=hϳ<*wnY6e6NY]adZyN8K΋eT/·df }?edNaA{)tg"֣=Sqy9 ܯ3 OTnawj~ m+'`6@;vahO0y$>f{;{n2ŵSϰހa<_֜B~c7EE]TK2/{]B?J5hgI8Zrs̜y)u&x"<参 ǃ-hQt1"Eo2KnB>@6X=GRff}6CKc@ ZbKI~hyYE6VhF~ , )Y}E SQiT]ILkiS;,>Dj+>V%%9ib"6N&!ˀXf2ez˪cU99Ty:;QޣeJZV2V˼jQAE-\RrU!u9Eqs mohn0*]7t ԵTiU)CjꔴXSҤZnicƄYEyj0*h|JTgX>E:'?'n݅=XK۳|ý49u_;-s)(WaQV+TѦhEJgάkpnr*[yZsrW^Ru pSngN5pwoc-u@[>C )VB.1WljtU(r+RW:긂 ܫuonkUsJ5_#9ϫ}*s:Ļv|OA?tbqo&FxL y,j+P[ZޠMyu7)6U>(g9|'e="|Ruޜp-ĺV|e:^$Z"s~|KwF@܁rҪ d%"#O Y_%xQgTxSJ}NBw3h&hڡ{Pa\a.UF|rFBt-:'kt,=2GWY!D.5Wi8{ 5سly Cc~;7zUSr cN1d5OQy|Lj78SEc*hct U 9?ހڣس^V>7CPǵIrag+Z eʖʚpȒp1xiE%ɔL%I$1ILY( IpB'Po+h{$qh~\r߅uc H^"sʢ!Sʩ%) S jV `V4NaRRRl֝Iّ]hϠņd6h3//LH/S/9t5Hu i࿏{vw #A<0sqsc,1|rl7mF1f#+>i<>]s 4y%lH*P_rsN0+8t&ܧH()^b)e`.ɐц?:񣛜M'х.;q+\̎ ')'/aS} 0Pc7!g y?QK9d% .5u!}0klVO)^ތ6)`{`5=0XI}ƏuaK}u\kWr@nzcyGY<D^%-ći 5M7a&X90Os6&j>괟d+V곟Xl!y}K؟6Sϟ!s=U|R</hr뭁H(!0 XBqaC*5?+8plI>| L}_cuM;9`ͅ9x7Z}k -Ǹ(dD\,FN?#'')3q˥|xCulb3׻Z>W]yD&Qp$ U\0!Vs%q@ϓs ,QTg~)!ĻeW9IнFsƺFA}pC&k@&0@>r0u-ys% kTmr YWIe{1܏-S׀CX5ȵG6(пјwUH}r:~\eM! s?ΣijOZ{$U1#1J ]v[>_mpmu })'hЗQ* 8fy >=w$) t9Ïa|$љY;6f_)b 5خǶ&b{gbx O)5dt;mG/Q'*;)p XUf{&wѺИPn.NVjd ~E=Kx:\?דDtO`X >-`U2K@ +\gQQH/5?z ORz^Nl߰Ǩc~g;h$i= lYnl WP:l7`{'!n-n_%sŃtAzDwm_P|ت]>`tdJa7#u:IDQR-4,MGZYmbÛV͵ǐy,G1C,E'9 'F;5:KQL䥅L>f2H6lq~+93=\ssAOǾٚ5E^8BpDJ8jnV_D*P#ĸc7|8V3pw1wG6Q)pd‘GnRx੅M؟Ld4HR1è:g(UW^1DwAýxK#>6s13:mԐ`ˀ)𔰓U W\ᚈxC v~nw]Al}`hi`, Y̹ßI)&;U^U'4$yRTRLPij݊.V8uS_T(u)G9%RQ}_ι_m>@xV˻JP=Eՙa2åL2TYrEm5WEA{kߢ^y䶝UrF8Xʸ HjFJޗO4:Vđ,Y**U" 3X|WF\~96>>`b:ɧ20ہZyVJ)7WJI*vf*RRY N@9U*!k]S˵HNZe^+쮳9ALk=YHI;cQ5WR> BK?/M< *ϗ'';A׃AA?L pew^g;n ,$$\ T D8V^Bq2ZN6#2Ң >q;9oyn'[鐫%g+{ ]Il% e VP!d"Z "8<<]LpUq-@ԉhܛ_! c> ) $Uc֥ &Sa (Hw#)<as29C>q-JFP .~1͵~L{ MHi 4 -JG ll+@5c`*o >40E70cۭ +W/pdK,1!a7fF3bll m B&xjG؄;@ |Ro.<)> ?:cm9&'4^6O/3JκsܺbCg\o3@jiy\g6^g8 9@/}o1DNQCbwD&AzkN# -:Ncnx_`='d62!'#FW?r&eRR;㚅ͬU[uv ~&v6IZFPI`%XEnE㮥>yl>7 ,f=F5\3KTh\5!%>擤!s`1kD- ^[csX|0>CMlFY} s$A n–Z5d||X`5?b ߝ%b&&ϰo_`aM<~H{xy71RX:8{WYIň%@#_&A%WL$u8xWXQ>8B>0uUJ &^pKd|G|FwUV3]6KD_PLpoFp*%U~/N )ڇGNvSO8jQv85mjd+~Ɵ9D!Mǧ);Lr+jOU,U*.V_ZUbRmP*Q!y7^'q~&>@^gUcS;Y))*wzT0TjĞb{*tT(Ѭj-JsHOU/Zl( "Tr O%*HV^SSSI++5W0*7BMJ3:eK1VmlxRS4Na\ɑJb1ǐ' A9J@!%7=A9$e(ϗP&#}cr?8ʫ o6$,fwI6l~vIHBH&@J$ $AkJJJRZjŢXZdZQt:0VvږaV;0/۽=s}o |ӷCyd}Ke+{y3݌slP⼫`M2|ey*(!Uh+ت`>9ò7RN-F 6`|KZi |A|lr :)wr(4KP Q~RpBpNˆ/B׏܆hDѲ!|PNc%|a#hpJF0ߕKżbxLq㤸Sn~ǐ Ѐ (%]%\a8g|JHlHOq4di X65|ՆoexhE0W!Д./n{y೎Y|< scZlŏv0 :rEE0&u٦0k@3nIk%e o!ya|HsvB!'KA#KYd>`]*Y Ճr\tuL-1GlkKx_ o8I/9kA!h.\c 2ꄯMS~w9Xeqrđ&fNjn q/X6,ao=puV?&kyGC&g3dL(9!Qjgky?ۇG>-})wžk) !#6ko,c\ɊA(fC~yCv&ړ{OK߹F*JyW=烀% qe#3pH\΀j<9y{@&/|N:gT "bc|'ku4Jg-_-__߃?[mrrz{ҿrGQ -@t%"}v̨N|StLF8$P3\PEM/3y^b}"3ɹ#LV92l+C 3l3ԑ)eX%x?<>j* -tL4&qXsh^x_xONjqJtR{L(P&˽v+p^Z!3Ne8qY Squ sa(C2M~] {mf{Lm5:'`6?)=|w|_APŎL籟.Li$_y=Bz?"kzDZ}p_!B%}'] J)(<5kn tb#BŅ9!:NwpCȎn$|_)nSV"xfO*xlyxH%k7xxSspd;I쯇o9r8+[@ ԁ8cҕhC|E\ ;{Tn6ٻ4wX܍*ɝyyrgEo/(3?do%3$$`BH@ Ud(Q"EED TPM(Ȗ-Z""Kw;=4s3_sg}ߖ6(M@rAk&Ь%vJ^ ; KgM@ úZ|u9I<9v,}l+팸 O8:C_ mk<b$J.!)A-A&.~OHtOHZsѴѪŭ$NVi%M["VxsRܢx:{u>4 gqYBzt}N}.ѽzDEģgq%+ġ~ŢNy}d8/aKbrg*bNE} A3A "M~K[4[<~M [[%VA[rNj?]༆ey|1G@(h`*]S@K!M>b Gs)4 N_(| SC,u%7$ђ4ų `6уv-dwCaآļb1a11NSaȤϋ8!5F -ESw':{U!<\>y0?*>⎤3&C̙",\&57K?GӚ 4JC96g! -dSCI23!rm3A{Z"%I cfqdZ$-*<|6xcw!^"0Å("qkNƤ5!96"M%3 Cso#:24s4/%RLZJkM[f ESjhrٓ\gRGB %xPEWjI],-VI^T0 GFZќ^IRkA#VN,c.'ZϕW:g/\hL1$iRUkkuRG[bNڱEAΚh˺نTIn}Rɻ@S3$( 4[f\" h /\4DSGwΆ݊+yލCF3gDv6gTT a[>u 4UFhF4B@?hI| baX_MbHДt%0>BS .z$f*|ըj@8:FF0'YPyH`pΪ4M LH9:KFf T{|jHh#OS4puddq'qm*i~RRB7 ೛%ljۛ ZoIq@>CRM}jP~D&%x8(D笚|9*Ŭvh֘Ws/wQqN2,AI5F(SB)RV$M׍luxUyd./(ǘn+ДЬB݆j>׍l[ {T38؂r99<cBvOUdN[`(Y9y 6izEqe-Z^Yqխ暶U_WݱSv7٫w8vC 1r17~¤Snco5{gκos~?.x?.|EO<䩥˖xz3ϮZ k^Z~Ɨ7ymn߱s[{o{>Og𑯎~}Ϝ=ϟ.\JJ]IYWQdg+/RKrR+kAݔ7) nƃe-ʅpa2b"NLUV܉w+3~ܘP~< y G+K<Ô+/b:&e+8fMy[sP>| T}<:I?().^J>\ͻ%~__b2lvǣaO G8#1<\|LҚ7?3' t뮶;f[mq&O6}ƽfϝ7 [xe+.j[ȤƟILiLT*Nhj~o'G~83gϞ;w?]pƶehbm֮-;zW_5a3Жj꩛sӲZdOG. 54PCC 54PCC w +u%^]/9 _ԏ-~kwe ܝVOѢ'~HPG VFծ=Ͽ1}C&|ww>/n{y /Mٵzo.Ѳ{_d'װ6Rk]/޳̾{ttp|gvzffgi;fiNд2/AoF)TLP. E["-)'-߶g/yޘᎀN"_ )Uka"a>W~ՓĢ ?J!&vezzc-̣>$CkSFkCe\ )j3J-)|ʉ鱶d(;nZs>w'C71}fDmX4 >J6 3O;F.^hW}F]υ {E"f(/c`4Ѭ7h^!}w>85KhʙHAΡ 5.-F\ |{Gq{im=/ZtUppdK*8+#KD0 3{717@AoPa.57d0~DK2qH9yBCOmHLU1tՔl2"8dX2, K%e( %6@du= םj^A\ˎ*$,!2.KGv[=ZP $A=]+#zw^ XaF*bZ*SRD &^\4h`C͏@v~'x<\վAGi]8^@(WI<}IXA-edYÍDVa( e Zg:8QCHz,I^PQ%xI-02,탡2Ad jk.s[g-HQ$Xi}yJ&E|Ne2@ZFO AF# zw/؄9Ќވ0RYeJ($9J;C`M􂜇}0 P/69&Il됼:y*LYT~?W@lͥt%SYBfaC*Pn;ӑW_ހ}]M*'(bN)%O2qbzȅ)}^KgX $'mo N_u_q y[r=P"fUdVp=!:qܴ.K``ZJ s^9z5-&i *ઑ9u(I#ObDQHnƖP VKE2jVwn '\G&ǼԲ֠m0NJ\ɰuUH Z %4Y@" 5Pog1ip`䉳ߦq/g(MEɱZ,T"V $KM2TjA})Ï9;g/(Ė>Ȝf+Z5b m @92v~ jl̆q'G%7B#~̇ސt& n磛#XB. xю?S]1a^‹w>LpP8:H"Ol@H4@D E> Eߧh x 3{ =p~@bIb)y`o%65~) }OztGr( yĆ_ x {L|@mT+5s7*Nȁ3GR]xڅ)|9x^d\ \dyb.pPdmkkm_"8'q*)c{&B?P|5 b} \hXL35j1|%/h`?b!4У( ^@9 Sa6r%'Pb 5A(=)|FIS|F!'AcIn#V4jBkn    {C.bE aԞ=ag*"tVP*GhHLf)sUQ͚H%PY~5[y6V!zgkhpwK Ly}\DM3 3]WdkijJ$#d=U$yA 7B-P%P_6`ׅ3$}N+5AIL62U`#%yWFSE E[V\Ks2[nh`ԱCbx. 蕽|Đ Cű-NV>ߊ=jVy& ޠe=ή0ۯk@G *h\̰O^LA m(U42fwO'pxa0|YPa47(t%1 Ο;\0^vwvgԟg oB l;e^cdUd ~Pb07(PfG?^;87rzĸ~_|)8Wх5SSrITdC!b@ As/=s߼tD[gnyQAA$LN'3 c8FBm}.)u#=g4b4~noUc[Q8ܾMYBy͇fBHOI8t8:K |H{ȠLdT}ūoݸ\7gMӫ[e`Gp=ϡnO"@EdYs@\4yjlflV/o.=ٴBj:*n%}lNmg[SeJKn/T^P@QQQ@@PA/],YinmyRؽ e[ C>yE@)H;a#ssEfKϖ?,?_V3|~lEfAx8䌃XH?Br_({Jh3[^^0_S 3`p^AkOot7$磐dmÐА P+6/ f^ Gp1~)$T1|RB.玦TMI千.YoA777SCkCɦC ?#4wPO?Nfo0qZbNYLn~(VbOKmkZeu8MB ̵Օ??#Ȏ,kNDs:#:'>V\9Oe t̚R2'L掞8Nhmנ镡1!?mb#~GPqEfV 7UO$K.R+ \f9\cLu%uMXyߪoNhkGWF 5Ak(9ԁZ$)93Ε4RfiNb]6*MZInAӉW2v -&Ġڷ6[ɐiuL Ye>3YK@e6rU/"4 SjbMCb"5b@ ЇIUBEI*w:SW.+Է[i>9Eߔ+UKr7Se@p^*6A3x!Y!,!*y-vANEM&ACӫ cuԆnvC$e^X_/.bm[rĠyb g \)ƴ&} IQRVmz;hgyn46,bhغ ;WB;b>tv/KWt:A`jNmg\}CEŴ6NΠ7Ҥ}4E111t"/,1AaO\4FٴC AJd2ȫ(8Um3R HaD ذ$[n+A? cSΙ# ͺvUD֜Zא )F/ (F;Lj! 14! rfס^w Y]1|6QHUU5gvŹ=utsԚSͳe׈2xRKFEMP81H|ZOgk15zq4`.dzXFPV(3Kd&Z/asbP+KVPBCǎOf{~4]=|RPIZ-` I-|M)z圾ЂxME os?߻IocA?c)ґ]쉗RtIZbAe򺣕EHE)B)2*AW8/1/o\#=s#ǒF#l{t%/NՓ % ʸtM~aB4|}MG 5 qtl^44ra8((>' ) 1tIDIz*5+ @};XpgӻG\^km'#!_ٴ_DTXrR,-s4A8K`qqY9UX[~M6®QUA۠]tw \ԮUGg<6`**9{".#u 7 '8́j');m{k&h ho''DX_A!NW1K)LY[FfZy on: L㆚ P 5ۗ@+@t =  򆶤YIVS~AƷST*e\W;^^'cF:/n΢wt@s[\d FPEt$H3>eOsJ0)/(kh@>Ӭn fvhN1{vgo'h9_ >u6EgZcin=aqWu7h4(N~ ="l'h0SFI721MGMl/ 4d`B mȠ84'<@sgV;5Q9Ts ny*rQ(FRiھ,&#{ZsJgK|ݶ ۷6@|ftgB&'=TeH[H}U{˚6˪Zs}I/S9K 'h߷ T7P1!O I=;scPcƪQm%WY.(IM7ـ Ad|LgGX"nJVx+9J%rS}Zd5LV%THdHm/6%^AfdP] ={}-*[[|SJј*9(#6a"[R)|Υt9Xe*\of{{8 o@eЅ փos{Ȑ選 WtEi2ȕMe*icAfa<&ZOki*QCP:gZd`"/zn߽ʯ'mytSqф̚t^s4{g%wQ5g,lmEڬJgd୛ m?gz݋NP*|3I;! RʼnC䖸 5mkey_goMi#֊NǺ_ъbZԊ"( D K! ـ!!@BB "ua(nXQHU^h?ܿʪ@-g{~o٦w7iaݯ'^ EQG TŶȟEa|1Hx]&]-E"͚`^?eܡaWtLmqu~)~?;I _)OԄi_hY=A.3+ݑq+rnW-n/^2禰gl}'=$qϛ2 &[ftC2.L?+N z*)ShSes s )[+,vU%8Zyps T z;v6ُ.3 -#0l&. . x D ꞏ|ces`"5^Y{JOD'"E5 2p!8 ;Bq(7n\v{>F+,Uyv.5ก .I- vA@Dl 8p}!:.uXb,15(`ռbYȅK2Uw ׇ _ yC7^R@qX;o;w]8|6s\FV[a4,/Aqp[k=;\ȯ f+7@!H26:C6 pm mlO +8{q\ׁD!P@rԣag BdIR&ԉqMYϢhc.ƓޜG{a87Nso5dX݋`J#o;A ccx⇿LNHVvL7(I sU g F3LcL.SITS󞞹's1{.bXܛ|mz^y3-9D^鮒d L4T ~m8d{嘳@_h[;V'(PJIki)%F'\WTonuwWIeU'z+fjol/c}I6K m+ΨU\f\VnFeoÅwE*I> fh:֥ݰ˧֚.n&(袔[1Z(>D$h $k+{*%KGuS[o{d<5mq|셽qj??gpzB9(RF/oeV[׃ZE-M]5rI@.i' 7crk]:_Szp؜q봋sd 2hD Ӌ>n_ҧʫW\[1(\Ax*P& e~Qaўw5rr,` )||dh2e"1!>LpW1CBzmM><\( WyPzѿdf--hxomP1^R#g¦iIIVD6)/D~R:.rЬ,N/TV ֭],[y )u߃'/RBHoƒHgyQ0 L=ED] DI(>݂]+Q[W_M[f1-cC\ÿDa)5:6`5\,+E$Eq$rV7z߂jZ'W ۄpN%4X`E3@D߅P Y &( Nv /Wm FI,ˣF9"/*J~ ?*\8 'C| X d}51RL܁i k|s'Z8B$1"۳ uod8:;r8 8DC+D8CN@;)/S~l ZCDݑA5"*{&#Ud8p@>3Nl ]80 {`ma CVsX@s`5Qd3c&?.n)TC*בֿ$\)/]N`,w[V6/SW1F@g JUTC4$"1 Bg $*AHP ' `jAj9H7Z $d;A, Q^jC>Ak6*8$l(|g<59jCo_j@nEDioK 0W, `{kX3_*yBJZJEZ n $/F.D>y;5?5HoCIH>,1Sd{jC<, 5ujS h5<:y)!j@Ky4@ݿ4$ig>3MM$" q:y;*CaӇ,.1ҽ?'qL.\|Q&$NzEseP ONM%O_P@<Ґֻ<eh@!Z jYu&o5C\D.S^GU$ͅ`̐n1p=pS4\:9x Va dYˤ~Hg/$'gK'd= iN%  t=n?e5&S74!i HCJ9@ї^\Z;=z4C1O#  FI%>aOЀ~9x,&i<4А͛lG68`H7K ANmtaLs)JM .QY2%Y")u"bb] q@$8@50Eڿp0̿bv9YCu7DrV,8dI6Rr<ĵH i(ߴ׵G>trÛV/,أO[C0L]5SI =V E fKt XBkUSjOL~Wi_  鶅 ^9k>=퓝#ۃ͑QqMzZA(VIXb>Yʙ,uIr- RzV]@j 齒B  dW'`#g! ƽßo=UǹC;|{Z#"[o]MIjRE6') oTWV(VX5֝U[++h(\Aj|l>m/^7K>fs,ؐ'NYJdXʮK2_f dzh F<ߪ!zA=P4;A%r@Esw]kЙM? _p8#,-:Ym+jQYņ<YK G*hez}I$jp^ixo\GJ9t[ivO=W{y{7QUmqYd ݄/4s b)R$Ī8V}pKsةUu_8t#Tov4t_6=sꋈw]`X ҊsdU4a|S$$E#LMaT! LdN)σM~kcK_o}vvo8~,x8<⻘4j̒byƉ_Qy"Z4`k0mz{i4hހ&ǁqܵy 9O"n|@F 'gR> ݈6fYM\d2m&Vp73pp,gnWA8vx2 5c/OOp>D962{"1>m"S^gEYQϸĐ҂z6 v|yl@jGr j`bCo+ o=]ޜ3a93WgC3"㧉1ԸkxI!/)uJTm sE7Cj?EXzf?l^s_);xًٳa'fKf`cfKʂCgy!$a~W}g{e(]P;# Q7la 8 ` xd( yBr&gp>;~`}juBR*G!lu))6<קix A;/CԞPH i =H1= bPz\Qoh<-^(eCUM-tZ':-"%,X8.λی-~^m灴\qJw֮ udO~q|2PG( ac>lpNj2[Ke8vGEłH "BH)$${$!H*(( X.l"(3{9W?p.Y{ofF0  dI_}Rb/Wx"xW]^ <|s8ųq0}<Nb8!cVx} sw[1,b]YHLelQuҬ`ZdY-IVQ¾guDY@< ␋ _x:[9pˣ!5Q-e'& 㤞-Pq$FDk (ܚ|9ǻenkxn1P` #|"Ȝ̍j]w{MEP[[L('1F:רgKjJPER+.4ŧ3M7XN-Kt_>kDP"ga^c'qqK>˞^=SgsוGŜ*OJ)*JS9ZSXW tr]:ǐ,ȣ+*,4EC>UuӜХKe"[q`/j, IgMk@76޺|tŦڳ1ѥ|~y M_La˭LQM-àͥXL$}9UBȹn&;t$=)Y-0epD`anj{9vZkgoaGQudC g Kv1[F?!RS zdH4%Y0aN8u)H d9s8g[lIJŴ\u]I㚚G1hhjsP+]ռ\}xn~sDr^G{TAPI =uz:ڬ5>tk7ͤ﾿Mw/uk zDs7u#)y)6YAO9e;푷T֦P{@!AsSwZCRs?U O>Rj&;ߨ}M[Z W}^w76MUK,Ց=8RAbyڰsԁ ֫ uTqZV"D '(`A^Iyݿ20duQ琯UPi5w["I^OjfƵ<ɕawY9*y;zZ]k^wiT4لݔxwg 10dBVI۰ՙ!NG|=xa~iw\p7?W^)m,m*m+w4XƋk/ TA!GRpn .q.qst [q3c>VFn=RRL{ e"Ibw:C/8hΎCBh$3b\PpJx֮CyK2c~q_vdrT]ptInpF"Sp},t66!l"FMl I3Ff9X!AN{H+RƍQgSwy*wlHڨTG= cpsdX"[,G\Z $7@t6KH  /im>MKH{ D6XkBA2]d (["O@~bN{@i 9Z F?x9 ϙaciǩF9ݬۜ{1HH@?!i&Ri#g.Qi@sTnBz!<y1v> eJ ?Vެ#Cbhw/e=(}z,~L:%|HŞcdA@6}GnRŨj=˱j*n_J2}rcf32gҎ$MIٔqQ~7לG᜻ vfOJsE]Y*HPkPNaZnZweCI~T~%c"7*kHNT$Kc͢ܧEw/ sGxvt'g@B6$7ϰ&5oT#G:i)E edY$oH I؄ld)C@+R>}/Ç}07H^0iƟRO~O$,i,K0)QN|BȢ`z@`/A\$%%!5v_k]7t 7S.lt9nF f=ް|܁Uǵ6[B!ڐgiznT[$߮sڀxoʐ8dgWos0f3iApZ@bڢ2Mq? n.a~DX+"UP"  "d&R0 w~T]sJ/)h k0x QbF-&*E jQQDkbaĠ8?R9Q_3kỵ@` ܦO_,Z_t86]aɿe?'#a dëcV[L:@?}b#o$`W{tC 5@; A_m@%kPkj~CfeK0Jjn@A((g4:I?|kXyI*x $%Rtfffjj3Q*jS$bZ\uab'q(\} Tp0zSs( 2A hBmT‰c4탱!]~^qD:M"!#M)Xag 'd&n,D#fa$ȋO0K!G>(B'j m6s+.\I9MD*9N` (7Fx!$fツ^kx]2_K,GT-t@B{,Z_]$$)\Na8XE= Ìzs\2Nl숄^ RMVBd2ePڠfV*`u}P\\cB瀿<JmQۂG0ց~Ӯ^ 7Pz<^O$B°7yi}>Ǎhc'|>B':8<WC𼍑2M0,؀oNXׂ䣮wvkʯHH|;čWH^: 4.x#=h1, -GrR:" `q'yq~=@$= &j ڐw c!o& 0 *r4bY0CFsȒ,!M[t=NU")3`^D`0~폰I𱤡-YI|89H  #D:#eDN3afȎ\E%+!_q U7xw܎ pN}!kH) 'c-uh&W؁/1("B`p7Yke9⬐˶ETxATGLroc?KO~K RSS?{i_c#:u6ᐼJUOjoSp 'r"Rqΐ1QcM#)'XkF/%mG{~B?d%KD.vX5u3Qi`slBE|q볢0H+z/}+K~?Hcd`v1n O ?dh=L-6kq=NƙLR =d,GJfb *`[%ƶh>U^ذl`=>ԧٝG0odg>$nޤ__I\2s)pFn[lu4v?5c5vwֿ) eG+ ˙%5oDH:2p~LξɹΧ}⏰O2t.KC 7:y, TzdVG[ʾ=VF9Pis.)/w"`8P#~}bC:1J"n!ȼ=sSbMsF])c~.SPnrn(W%3ʓNcžQ[=T ,BBxyɮht9e5hp[Ԋ˓vja̭J9jsT}vi.|oC#$ $Z-2dAC.q {'i:&C D,{ږ^;2(+r9gJ' *GUYs[eu-FvAdOse}N6V i(&A;}_;c䰛p­s}Vt*YIVe˯W6嵨~[TsdJiujejekq@H[2YD,%!iAGF>s:jh[i~W#J:Q#gW *J-eٍŻuMj*UgirYB?uz@Q5B];sk:~#-4)A)ԡZ I - *HDP]@?8*~Yѳ}ssv: {:,{~'ŠBzjZƲԨ3Y i%9ՙp0W(D/D)췉y@4!M?a{g6-—KR.~4qj4h^\:Y]_^+(.*N/gd)ŒԌ 񟱒@:mCySn~c+ǯx`q_8ΩZAd ёTaiEfFajŜ¾#E%/KiG $I;8-88 w>\/~e*=3rpAO^?۶[cK8!)LjFU^Y\Q/?//[>_LRZbٛ$8I rԫ⾶oý؁{q{nvh䘽a^k]gOhV0qјĴdL^M0TWõO5Ki1oxU+q@6\ET)I}QFˣ{*޴!ݖ17ݶa LjiO$3#>$Mr,ȅ#q)MU2Cu6d7m\N ;~8I jTDfl\o,jo: {FeDzS{“zbb#; WקjHjNgv̦_ -8$t%diF4;$ݑFSh䑎T^Ŗ86_p& ׄ!q쁊D$߁!c`V761=/{5JqP)^^ >;JBf6gdtmB᱃F՜ACƾ,ǴPOhޝ6wBš(whñԉ9mb%~cPI _}8-ۤН /οQKrk{5.T@%uR=w1щXE_R^K>KC  />/iE%FoZgaAլ HkU-ɫV"WCW9FHՔ}B[Z~Z/9})gOrveNfB82GuRbE| |#5lYwT [`wi} ӣ}x={ɏPcMeC0cy^a[I2ކP_B-7:=P&\hΆ80dWPh' bpN't/}hc{6m@]Ĭ Pet7||ϔA$י T%OX黀 >]4.#`\5ƨ LϬ_9,P-R ,?S@5"Ib-adVp'EBP>0O]QM^[TzYuQ Ɛ9! I@ @ A@(rUZPE *Ȱw;9]笇ظm@X  o#D/a$vla,|Fk~`We0;xۜ{!p .B i+n hkrx[6?nǹQ'q-[FÖ8āh=н0 D Aq1O#pR=%~h@m 3@ ҵ@ez$|e[IZ؀ ws*CfV=zG%v?&W0e 'waO"w6x   Æ9~/ϸnl$;C8 T7[ځ|فa䮛 N!F#{4i!U!_ٔ>oA%W;9-<þ$`ODfhl<%n|TQG wN::>r~u.;Zm`.W&<AȍԄȾD WA3JJb;D|IoKIyO%^H>J3*dS 4p1:?,y7s_pyP]yW~1GyFԦЎ'XGE6&Z,L( %;Hi{I 2+F,,jB&)&:Wn*J.eW{;i4IsȒVIT|(0g-$Z.UíN2 +TU% iC nE>rSiT՟՟y z ߾C7u27ۉZ5/[|ٲ[WjʙN[QM*jmU-M-4cR<7U>42_%di> 35LA,ty ]lrxOgwۂ_;CO=aCAֶ2fS<֨ThX%B}0/D=$קUR:U)?RHӎ1thkuNf Gkf,ںkyWS:s-=hUR*S Y#0deIU+*"0$N%ǘq5@:g6t1f_Km^t?p#`:Ἇ7R4ԲwVW e2raS(hr+F$!ˬeHP<3Sd[X15@ cbfq݉Ř]K0W4t QrFVXY_aS֗pRK qb\&-O+=JA]4_8̗-,qi O 1P= f<^g̍Kv;φڻp;iSe #ݓ &ZJMr`:/2O_^*yNi7.*a^\W<ƴH=;af~.al̽s0W0}Wu8/l_t.ҳWl:j~IH (" ;BBB@aG(Vԩ#.uSw ,0EtVEq=c= bʎϼO;~|}&GPnj'Stbo~~́ՍҴ껥? eUe>6 S9Gg?2ɃVEnvK7rk. ^H /usYq[[ 7sbMFuaӶ9Y k U E┆u9&NMit tIn3 .3^9w^SǰVՑ|פЭ37\X%XQ"L{~:ܮԶʬymdmC9TeZl7$chI-if+ qA3$MScCV{n Э _}#/zq|εIJŕJ*-A#HOr{kJxBrA7좑ܭt~NZn2I##rߒwYQ۞7<{7ú{cDfknNS2KR2LH.$ &zrX艨Y? ^3C \?bY>.Ԉd#hݐky˰qooLlqd)jMlp-:2{-O)zIH8!J"HX>--t?x9g#0 ee:@i5 !e96̰p\C8hՇ" `Bʂ,R)!*Bk ;[s@\#/x7){4<ǃ.fqq!cBE1"ST,B%W"=U^jo3v+w)n࿡) >HmW] f{!և‡ T\cMPCj1de6C!>Q DHhu«)5QʤL @JM 0&jTًH CָCR6 Qrq Zلq鄏 gLQغ|AACil2} fl)2HϠY_8!e+<8!vCKľāIp1\h"G$wH .HpAFڕLw8(XahS-^dltf',rw6&`FQ4%oL::!Az;׈Qɛo%Cҹ7I{-GK+ D4ȝP*yLa5%B )mP1oL6Ɍ=~iޫԆ&7rGQo1IyCWW/dclLg)BCBt!ő,:飔c}!"LPƷ:̚ bϱMr6s_`kcN8MEqkKXܪ {H @ b B-@"D@D A^VPֶ^u9ߞ3)1 ŌyD>$ < {>p}n0 1[ n32+$lw} b:XۯQ)GrU`0kq&LxO1 Q f#@O[ a#O}kTm=0}ډ}Bs"oףX}i$6hWѰV0+ s~1e9XET2K^Q9A~E6fLH@S@V@((C^ d!o5n3aNKǪ]/wt9Q~uqXN-Q1J8yj^NB03S?*?g$z$ {s羚P?llew]O~{GI=VkȉŔe&tir:NfQJ8Y9$Q)JRR^y:m<$HX|\^ԯsv-K.O}ݪ7rV>VANfgf1ӋjMOu^>/NPJԷ$?IIeH\@\k X :G.5yionm>KWg(Kɔ4m#%']ƍϬfeiƴ$:7<-3.#%. lb$ zob0[=\&:7;/j;E W_v_U*є(ɧB-K^P•Djω^H;)ʋ*|˔|J d!"5.7 Eg0ri={vUM-ݥ :gv_cĄr5-4uFxb$[ܒ\A?LQGl2d=iv'poٻǩѕ7w6qiD>YP|]>&Q*4qw mWB-PA;?k#t{h5h0phUw-uHy^/;,1 0idҌ,M6ɍOhoht#$1a-0 pF;0r]m3`fouw)^lw+{/J#E] J ˒B'Q:*(v#-3>xJ÷!a m̝`,߷A ,hrO-i~%s0ɇv9-t9(ax@!p`9 l ,n0aߌ@v;(ݎ[G%];1MοÞOʾ\O%(wƁfdlfGmrޟ~n^BL Ѿ"4 I\dLCpfbc!Ń5RlOh0P¡Ej9Nh8b#MN dBBgCbrDd9CVI;hdFo۸O@p꣞Sc>k ᳐ENCP@^ᆌE gސlB@|<:S!RԨ/Do/G [1|l hf;U:A=*$(j='os背f2N/d~~C]'^OaM)^Rq|m$ y$ rȋACrr]3CS2.TkyP~@ȏA~6dJ |:a9z[ gBƄ>c8i80 :W=79>Эvc4ۂnAPAu,lȗQ!ѿ)^E*T'* d#d@G4LX( aaV4D{%1K튢|O"Ə y%~Gnwv?DsdڐT ߳`F5}E=z&L`dcn= '\y0.+\2lZb憘gMOsN=ɪHӞK{*+y&O\0TAtLi/vNuĂ 7ucżsJ>?.\0s}Իym9,?-wnog\?]}oD|$u0R.`ḁS.͇=/4[/[$ɿ(*n)1wƎKNw=Rv<[7E)F$z".5,uL,Xo?T48˽oҐ17*fhiHRRF酒EMs-3ԧL4'L]c;ڣϳۋd)!J~r}EoY{|_y"űo2ksk._YB|Ʋ.͊c/5K9P|>wϹ%VKedZ n)J{4/#/x b}_`߻FܽR|~vLU k,WTy|zߜ_);qc2i@Vs%dM}Q ỐOsڷYVp3? c> tF}i1\Ci`mrkU{*7iw<狹_(o3~n9h2m:oHXնf>L0?I8XUA)ғ`B(@( =jjA@P((2눸zQ 3{f{vV|>_NnMF*1&8xxot~ |NΌъXQuTY٭9.}|gWF>UVJoO&51/'&Tſ NZ 4D#/C +2TVkrRtLgve뢰%1Gz ;ryr)R~1)ܿ>YƪLa&KEļus->TC"{٘p#W7 ưnA:hO6zIw VzE':J 9U*%IeQ'Nt=h/L@ TP![ ד`]tk 5]Rwҗ]&ok7BۣKq-IM79'LWBȎr0yL, M1e?0Y~rD#CdUV&z 0_@]=hxVr⸁pD0`ƿޟ:esZdjJh*dAC1b)VO(P T{kn~x{oeFgC5='ݼios~)wC,D쏹k5t$9ǐ27zO17ml36E|blՋ6<ȕ~WNP0- 7HP5 #(^C}lgIqLO΅sd?8{ &`V`ǘ9f32g̠촋#:JR%n+Wq gC5(~/r!Z Ɯ% Ygf~,"/|&x6dtmGUnߣCnO6p`sY9P@ -HUY.B )RyLR7*71[hP),SOeNwen6sew,~^p\O;Cde.|-{2!aYb3V]5+ꊟJJMWӌV}(>o;6kb6ە/a+~*p<@k:> }Kې_|4kC:(r:k!T 5C^pZ>}w <H[_Hh \~:L:IvMQ" ְD{P9Jڍrw2Iu|u &9+m8)@ g)kHE vȜ` dYTg;Av5&@ $$$6!)67,E*n8RA[EQ}k=ťӊ֭Uq3_ۙx;}srpig0 bɴA$ ZH2E1ʴ JYec'6PT9I~(“Fp [83ؘǰ' hiCzu%icj&v&ON߃Ѓ`O B Jπ_.xzǂ6p0~b8A\4uxg3O>C|x\-,@0Yï {M;H3)W;=%wÔ/x0ȃ&|<BDd,H:τ(} Xict `)$- ?&^[?i >Th\H>D,Ku YB !2m@½V"i EknٓWB_ a5W\R'H#ݘZXc!F](#,2S֛CMʆd͔dpG#vg&W߉ڏux!px.S lH`8G!ք`gr{Qv4bgمD)t01&*4 _c3fE;v7{^u~%;4 sI\I>{7s~c RV$4ePͦ24/-!E: >&ϵ|3So"j9O=w60G=/xߑI;vM +3 " D[1`@*&D3>+ߤL_$~YT|?V.z}nFs#b{=bwUywTyߥ7 Q> v&c a$7d;3,!7#ўL {g c NrPչ_Khȹ&v߅s1D <}Ip"Xˀ|ăs8Ép'4!ιtl2K %dsobɬ&?$3K/w)|*Ι=G :Pui㟈&LUw( dx CIb̀B R2 {ƛ*WI5GneЌeJѢDNgN˽^w05@rp_Rhhɠj_Ȁ꘴?lww}Kop[b RH~6[EFVQlƯuNV+.Y*Ns:v(@Vo?,r=K%};;RC ˷W$VCؓ/M7&wУ(#Qo̩G06NX'3ZȖgaks&%C>_GT䷫I+&gRVRZfQ6Qmv>-"{9צU[^RZ*^Q$ސA.o9wGxS#VD5\j}\?!m,DPSO;!oQzR[3~:7SohUڻR]\Qo+/]%n.Y'k*ڤXUMYW0Y?U)aDm{gՕAP_&(TLf ֦CnAlMU``|wBmMIs2<;?n-_[])XSY/^],+oWԖ~*鏬(9]VrUQ.rՕT iiQohjl5M]_M:4:-p|澮PѶ[ZT.kzlXпBаliTW}" aQ(B @ؑm( ""PYdY(.Pjg: eLm 8ȢTEgǙ3=a>~s>9 f?pfތ=!)B3&w7- :íT~!3߷1 ײ~\btqjZVWdx,ҬdX]~at,^}w:}.();x{Br%FeTA:']Hx uE:L8˄M|j2$Z%&EŹ;itK+L)(I:Z㟘75Qp|o~ ^BD&}8jh]π4\nAG byэWYoP|&lmM95qU;U.puVnTUy?? Ȫ=us5:r%j8Of.-lHa^ttz/Z}=b]Zfx;:ƞ͒G7(=:}B|BF:V7^:{Nx ۵W:?yO^T]ׇ^+F5);ǃѽAOﺴ4BU\ۘ{>ȔF|rT^^v=#}#mJ6'jEVH]r.;hHO2pl`)0?cWh-KjэcǚD&Zn*Q<ZG+2[2Q)'9O7^F;uߑ.> g_E̟d+?Āp{߆L3Npp~; ơwRL2,X kmb>E !T*ք!>8^LI dlT,q*+N׶>~LW4Ӡg3s'|:Dx ꩻDa5`ɿ | 9_!(_SW"y֑vuc8aڽ԰ye=c\\tm2YYpO'-Ba -|P&(Pq%HђBW=iS `0F3 1 Ә+{XY2kY|uS}.?@O߁2``Aa1 5ZJTP+Л^4#h=up,08XKt0Ļ75LU$;x #0%uj}4d/K P@領F)AWJ) (t" EƖF;R!"Jh`8 AhyǵHsq'*.Zoω7r,ɖXD8(g?E,A660G \ QJ\ Y ?ψrȝ/j:YB(>\E t1QB0MƲ!Y 2Pͺ(EQK  gijoĨ;Kx,(RfBҜ0SD% ݂5%;_t߸Jkx(i ZG>b9 z }z3u< qz:O|I~`V=.h` t "7N qQTM ֆAH$2Ī3l5c ~[>`-c5Sfe~ #Ɯ}Ƃٽ0L ƋBF cJjH}1@LIJQz#r߇zVM#ٳn'AF}xiۻnzЂL0X^W6!``U8ߐ4|3-5.!q1GQkG,7[޸VNa{rq&ՐΗB;_ y4F=֧#TX`̿6M{W"H7Bd]沼5_g.}ʎ{fk"f|*k1vWZ~޴b.#" t?>1>Kg O.Qx,ŀ^ `38xػ,|+>Iq峜DKm%8opks=}2f43J>}pIʡ^~3G 4@x{;W`2@_VBkcڝ"_!y٦9zw,;XýȒp>IdY>--\!BEݔjoBWhN(Ԏ}ɂWD+,z*2m;xBa"4hR~/C);ªțfc?]Y뫊]H[@Y1BVaߩSGB:j&Z4y/#g$H;$l61ױTW*H}$B%M\(/,  nOY xb - ;jp:DUʎ0\2ckY,ͦ&k\wUEbʊ:NFQ _r*(VP~[|(B0l5g>BU t]*щvutc%߱0Nkc,l 3R5n^Ԑb]P+uHd|&3e#30x=KvHU=ki;m_0ptn.>'n_Zm}W >H[4@oƤ`GLspf=1Ze_LRs`6`a(nQ5 S≧3JӾU_zk;qolcoLc9a91 5Rk)C:{PWX\(nvW(hdDzs۵ DQ:8[3.O08ĵ}ݶYٶG1ֻ5]ƶD\"ΡKԼ */= 0"&\Bֿl!:!#ԑufq:': ;#;?:kXݵ&$F$W1h|~z=}?o ? n3b{˜XFӛ̊VsBs>)Kk ~ׅBy yV?Kv@x D? ŸBG0qLd0%c Mc{ xgu7v+{u+}u+5=Jp_A_F9\w`l7@0JttTa4F1ned8 Y8ebIeI 52@cs'?25P@` EԔP\ 1l1 l01LF>ba c/jwJRC,Hn!? ۞ Fz0EYf&\TOal>/r* QD('UDE 尢O\\DEM‘0Qn ƹ28_BX=&P3] ^"°O,ߨ[VeJڤRUUG/Tgs⧪+⇪n}Sq[{jVwF@/eP`}\zi=u\Ԏc|p<˘VtS~U*~QV@do}v5uv^ͥQw5y2FkHWɕ(az{tGh.R0#3{g$inuD;nݽov%n=N7coK;bOIǶˮޖ]}$7,5ƣSk<:OQ0-mH8&dհd'dXdYIgs3e]~õ5NW7HL4\rA׭][ަm}^9U3~fݐ{S"6&d2:HF'6Q7t̓МЏyTbq~t[]͙i{iBέ\ΥM8t2&}w }q_GRJEϺ4tKGtfmL,+zwNq›NxLdnG*/ZN~I[rMuG5}qIK@H &8L 5! !!!!B-D~AumγMzvqwHEӒԫ|90;Fzx5OռQQBgC$kP|sKMgZ;> .=w$e@q<;eb6tU!ŕFQ=.Q#U"tGr VMN|D#2fo+) ;i Dokvpa2v\wz`Ys:P{qG2ˬ6d:jH343!ZHXi\:!$;D0ut [8?^|WA ,9ai;d8У;^rji&F7Q*Vnbh CJdCJ,K!).R.>H_RT DQ!5({AW ie$J/wwT_ZIqae-Q(w=|kXhރk}twKfWvzoUk%ƜyTe7J| EueTam5-hftd֌W RUXz͏eDL5;hϴ`!@[+{} =L۪_9w^ܧHr+pڸVwU9)ECi6P3&4l6m&lbB&fBdk*=[\?ޅ;`@Iv0ʾd Qџ\ЛvPԓ}-bnV>h0-<m[8u{\r#?Z_#3M/eȐoewbp8S-]YrNaUy,"_M|Tn'UԐZ\&MaSހׯT%=Oz{U z9gIO1!E41C׹z. 銌hԯ-iw {=k aC,CRDNئC GgsYg./1n_nߘ7wϰ_d8"i46[4X\3 嵄 37%_A_Kn^ ,Pisc ?\tN B`hDSEoOu̐&ʡ'Q <8H1&FTȅ?G|&^(=7ت.Dv6ltvS!{lOVԆ!aP~`*ZpӄqtL:R͠LCsR|I_EuqӱKO,^&?u-Ñ#w6N/►*♺2jw*vEME4ʈhn ҵПƃL##Z3p'S2'2h,ď,Q ;mu\ݾU{w+igaˣlnsۧ.eqhWD>F` }lAmstl6+Bx4sPzd\yʔŊBb5e Λ]7w+w_cmBKI"KPUvv4 t6L睦y 4,B8,pc7p5aFrD{̔=jG|Ŗ6\!uSiz)kN>*ve]]q+aMLtX*b72):F[\B:qP?Y@PU/bT5?F37Y-gUYv|cVtbYk25X2}ۗiӾ-K;4NҌA^6 ru КHW?w|98/#j8g> ̛fM -KeKr?R|Z9E5.fo/u$F!@n ulJA@5@XYE#.`ǕxZjUlF2Z;sng.8g>>&u)1$~*2~DV]Y$ILLl'bopk9@[D;W"!+H^૫QMmG3ӭ>ȵNSWV:u.NLVH:.K$Mr"91{b7P.8EC`{Jm]inTśXVʳmʲ Y咢LSAFK^z:kQ;kiZ2E]\PUnZV=CU`QJV$YNM.)g')v'(ds8]ٚ&3&I*`Fga4g˨}=@W:Eh[+WV(DVerی"ԒJiRqì5Mh'*o{DZŜb'z|K}jpvAH{WALl:O^UniCan4:vfGɖiY6I55تzv++ETuQOL9DU0DR/i?WS (l BԶ۠rW~>oJn 㬖u1D mRUjNaug}Pw5n|5s U3b7%zCt}v=7[*J5PjfqoEz S:BL6ψiO3ڐk6V*Y%]ֺ)s`7΁-Zòf&^l'~L !߽PvK'^e.=ӑ#Af'OЏl=R-4+Y֕mYdbkufM_Osak%[F~mf6zP(hU((H"y5E/_fm7A|oi=3zj,}{=e{g7>=f>yz LwoTy#@D rH!O.tȇe|5r B<x GhfL{'0yZLA8 c< 0~2$o򏁜a?O@ ([@z0F=7 30z ׋z9cQ- 7ö́1j5򄌑+)?W $ïK(ۍ(0` 2=1 |f Lmo08qLJ8 ƍcGg 0H YG6.Yc \#'+q/?dyTSWK¾!/@ Z*,ʾHHXHԸТH݊8mک^ENw~NrOqw¢)^/  (sHlCbh&M+_<8 xKKO>Nctf' HbGZdAC6=|Gwѽ8}|K ߑgcr?F>c!SMA\=iOcOg#SbH5|'.5ԘhZz%BSE]3QDtNSEWG-M1fO u?Ax}aM>nۓO_)S 'zRC*}I d+d[}̛~?$'7$XW<.z60s;pv*f} τp-#k ,IK`btV`Y.u˻w52U&߽6]n|ѳMF<My~ozIfC޿Ʀ76# uAmaG-Ƽ\%9Zy%FjM0=favo}OOՀ)c>׬>~?l\Ȃ aha߿~}'l_o0'([wb+`50@hlFcYqeF9 3Йۨ(֑p< u}ֽK{BVq nn +ogY^G-=w[k [?0^c_t-ě:aqFbe=-V؝՜vkNo o ;(61'ǖg;͑ض9 |/=7SЅt>LCO!l/5ѓc;)մ31bGں=[n[cm\L_&X'\=* 1X쁭! Bwa0$Ѱѡ 1&T,ҨCh-Mfٚޔ$7'V94%6ҫVovZC,nKCQQ}܈.K]¸c]"0Iiq' AR :Jm(sEM^ğPи(Ƭ Ų\+gjm܂RZW#P BUQVW-Su=#*x!Tc' jLޤQ8' •\CT" RFM.P1ha, 1(6-+Id,[MQPSV ;ej׻ȵe=nRq4ew8],X\iP%28Z2 XNvQSK髂X& Z:\Q-Qg9(J+FuiWIcn(YS üIwypB{a4ܷ 7XFU7(oE42 ÍbrkS,klEV^UM*U.$W4 *\ݢXq04k 3!A4(ADqpU֩Z X+ 8"8KlUk+.D:Zu}_Z?y}r?hL1+'Ǫ$;LZ_3~Pec^:A?iÖ8g~&h;+Wƒ&^I>7AR9{u{d*`}¬4=f15x/j\jѫ;|v G X{EwϔLmn5l%$ ݓWoy?8lJeҁ529ega:__qڋQq=C89NwnXۚ]2xuj8QgCls4و<+al܃?/ b, q=0DGcr504/"~}Ts{re.r,EvܜGD7H}zQI;q-ri9Ѩ }>mmV ⭱5^tWtSYNq̟Xbߢm_6*m管;k莿+gs' v}8 .B- 8Dz 6PF mmmmdۤ}hͮnyc!xP:շn+9 d ;H΢l@@ѺEA0[TV%=вdKƠE4++JDuIU>%Kſ+ T Oﳿ&3{_3[_ wE .R.uCKɗ"ۡrAWY E ] ombj/e?fSXhf? rh^U?mwfpػ>pbP٭P؋!vI/3xG@S` j'hjXU5@¨#񥤆5kxk ^]zB/Hf,d~Љٖ@ˀO&|P:t^;5o @] a\:$dwXNR]% RJ:RpUu~ߜ%Hx]/dϦ{̽j  ~O9^D.Ue纍.O<Otc BTPwk`w%襸MtlVGKf#d<3#Kwa5,Ն!]jr}va2v7Ἰ}[S-.R\ @!nӀ\!Cu~a/ZlEY`<7"{n\$n q͸Ah?J ŀ2EyuŹf)4S6b*B:Ul| 2ۚ0#Zŭ i4UT$wT9Si̴MuڴWUb*PԅJc~ 2W :b\Qq}nE%󖱢2YQjPYl:e^Ɯ>iNs8ar8.hvO820|aj|tmGF8BF"xY;ը&(n1PO|3Bq"zQt8/ǃKGhE2 jĪ}Eb'{c\jl!B!$K@$6Ibر@ 8X$vl'Y&vL=i&I:Mm433{y9^+b?uUL$L(8/~?b.JϤTJ> FI l |,Ki #ޖ_LAYB e"dDG_ŞvQe sIZOKB/yȝK3kFJ0}n3уL̽{T rr\9fW 9eAEEr5 z!֜l=+;ŝ\2S cr0GY)kXP!JEBlkdJ'+RRD.0ԓy 5LG aŸ!5Gh@h@DЯ$a!0\̜/񨻍(#AḦ́˚Ͱy 4iӥr)uQL6WlzUDQs=\,+ {xw/\: >ulG<>G~=<𞍄r98 z1iVIEזƌ3SZPJ\ܞx"Y|RԡZoS'&>Ij){|K !hQ< 0*A-3^d hE0cJ!MaCqG_NU{ʭ.m#۩mv4BfFԤYJh,]KNi~ɦ[ڴ߮%'7؇1wޭF0w]żcX[kN&U&VfG TF4nQZjFn5r]FЮk/'Yt6~5F_EO,g50_.|\}DW1y+Zu/iВFEtUG9*=QYhc5T4sm&Z@bbR&# ӏJ!@xU&K>zpu6͘79o=Flc 61]ASF4[˩ ʪnX;恸Jqʟp|&]ՇȗIz"CG/_p3u8mx 8لǚyRHG"^mQlFY]gTֵL}qq:46ZGHX#*qe_k%xa>}g6ּ::1wvw ҠMζm֖Ljn=LnhG; -Zeijg[nAYè>_b9Qe5^Rs|^b;Gxa}x&ּ+?1s [ܮhhw~{I6W*֕IvFVvǘ:˩ zy{-ns[ [gDdZ$E,,siJg|XHCBr<(ds r뀯hf'07!_R:WƊ2B_}(VM* 6U M Me0?;ϋgnse@@Ӏs%`-TMP^q7W;AT(ĉff>XxkU@c^_ c?\p/0Qz:Ue@+ n:ԤnZpC͐7݀3!/o)ca؉?DZڏCKswُM>0U﵀&Ѓ)yocܤQ}E.>o9G윸x~Q`:ϞWXx}ͼ{~⦆5i`M󞬉"CFQl`.~ <_ @]Q }Fi ͦIٴ66*TL';1E;w<;A&W E8>UQ1=H?y,NxdJ<2uQ-R.iOeEBvWjz/+/ x=K{+~rK NX2Z*L-!Kel%]ϒ%#/X |* })v\UlSl}Mbc#?4esZ 4tU\q/Q]}IEcdOΔﰦ)[+ZW(7[sUͪ #s5oPtU]*60>kt&T Q?wQ=F*Nm %4N)h"/_WfWdkr6hvج o"nYo̠6ABmАc̿B$Q~<)p0EaWHiCxڰܰъ_({NV ^ ]dLk$d>=H(aAha^S}ZO#=vn4ݛjfWpj/s'Ϡ?FJ׀7GbCdr#H91Pf蛤^'Ygi3lz2 h8;8R}J_#6{܎~f췏l:lvژȉ醕1aRVtYFtbaʅ&-jiّ" )+G7Niq4%CrcG ;ғ=FYcP'pFnXoEF|O v"-6Q͠hfLΈIM=ߐe41zWCR[c@a [5{砚}>)8 |`BV `)-,5!Z>ʔULM7]?1nݗbWq\>r{c ;ғm|/#Y.h=?goÌX<5/e GAkТ!#@ Az@TBt]OZa]-3umn~L _|?~i扫t$))2k89ǹ0ՒJT2k7gk[=LڃYSL^&3iH$%QS{ Krٻ>5`:d1UKkR$iAzc~97⚣[XVu'4i^ԛ4#uNpK J?sYIjeC?14LӱظP\!?kԜsr2\ VAZwmꔌ5I^Z Iz-Y/(bkی8(bq1;¬Ay¤c> xc&;b|G:1SYQ1#:As9|ҩw X=|}鄓2v q~ x́GO4=ˠ5½ PBEE(z<(O=޷z]ɸ-w "N! t;< Ji7N}7PHI2$9CԿp;7qBƝIS0"@!tIeKo4pe" WX0/#tpL.#?o05w1cbzx;~~ 3 'MJpT,=/^`Q|9Y0y\t$o>r|O~|F!Dϵg/PdcE]cAnArKĂܑlX Y,?`/G|b‡hEE>{F)[6SDϣ̘.c x6o>&w -C}1<%ă=&YEyCp m49q42,&$ Ud=LZțNr qO?/ z%qx:)$D-"d% d+APg?u1q xk%w~AE?4tN"|G҉Xy8&>y;uvQ ?uR8ۃo>?pnA+r7Fx@qnT\9C41$[1jlf4h:Ӆ/u<;HT}Pem:X5$p 1$$"B"QmCToB ~ZC j]FҊ6\lU~\_qQBYOU"1J F* !zR}/&4w|kuWa\QƗ#.hVs|يs=1|Nw'#k"uqb  $?-2zp۸%Wb7;>ŹU8ӽz4Þ8ٳ'z^m8k:CO`kO]"_ǘ٧1-O$.E&꟏Q8ÑEOg`f_BfOr2lav lpxixm71Fd7w_AB> ' ]8\Q|L|4h9'6{6`ٮf:S-ڙLv.Yݤ]nnbkwrܺ!g5CV_>T-ÈG<&w銿6ZY=[|0,Ga_pҍ6 [tyجs0t%zmu:vMl*[/m[bJ,ѝ.ݒ6x,m!J? O?$[FM|@380J]b^q!ވ,fM\2]WʶUqKiB}YHҤ_%o5OW̸񢔐O%RkL!jy{Io$('ClH&$%IfQmNpM$2BZ P )Ҟs=n#ڌ2tŪh1hNMaf3sRNaC1,36 K5e0j*` G11E٫`Sg~+Ofz^b)K29sG1sӐc 7_k*ԘҐi:A/OL_LoWUPQ*L,Ch>rp:>iBzeE6l r1M4侍>'d[PJYҪ2 ܤW(6uy8ƓuE^W(6ҜN`g!XK- 5?OY=1#?ov` UyvΟ-R%(ZBe“LUQݭqZ>8,;9,?y™'ʝQxɷTd8GڳX@~*P`ڢQ3a6=$fb+ rٲWZPėX}5 + .ka][׫m]NVM_jUTXE gܤ:![G-^]4:u&rDiי; ^Q%k}j_ooUwj,\ub3^wY Gr`C3}Qye1LȸfnowKlE~F/zGn)\)\*ܮ6,x2Js KtNRS*4~$'j+텒x|Q䋃7q2 t7畖Kr!Yw]Q{;TiޣTďQV"_ <3:S P4vNO~%npUFQ9FXҘlRir* J$?IRF*ErVe*IXPT!*E9!{:;)`Tҝui />aB0H1șldBLf(5\ZO N$I2Cp0]<^PU T$ QSo&7h"i4L#UOs: {\?a0G!=p:c 066)a ~nL>\yTƟ3, ʦ0 '-Dk$F5O465"eE 8Hpj%&*.TӨ(1> &y{E 9^٬IθI&9]hBm^]u KY+ǢVwdX'!-'Y00g#YT:Gaf)r /lV&TƜҘXe\*T%R=PC_7f1&yeVr dia=H>}BR8Ο,$}oɽX{c?&ؾc~RĬvywR@Դ`5GQk׋WI%0PCi4K+MA/@t Cc4b嘆HG;rX/usRغv)XHk}/q ;z8x@Mi3_pz"©G3*ViDhe B*"r8*Ǣk$T͆U[U}VRS0\$1θلyY&7Vlc<.=c6$z =08WO] Թԩy$&ߓBwp_F;~v[.vB-ӎxJd"%"SB ԩN 5j{q|˿C?N?D_/b"Od fRg>u p6Q)\s;SU[whWp}+\D ZBӅ9 H^!M?Ө3m&SǎXC56sjnݸX|8%:Uj- @oX ^zXHo2L77Z3X Ȧ 󸮥F5*phf,Nc'Y@*o1zuAS;hvcGbl ^;CQ T6`sQl n?Jp!! "',Y<8}hHBmcj"G:rĦ lZDB4zT픊51n(T{GUHOic{WT^o}kd4hg7Pih2X8 PbxņiuBT#'Ib9/a2a"axFq-ENcEv:Y=k=ן@|U߶^pĦXcBIXcզQ74QZek!0}$-3-rPe*S,1mU,65*N*$Pf)盅"JCơqs5>}{`%v,iȵ2j/e[&IK-Ŗ兖 y%[a)-%yjťeyޙ{D K] qDpFf`fD 5.Kq-5zXTkĜ4mz5m<96ij4Iۓd1w= |zemA6G#ulI1kLslJFɄU&3-X,VUZMI[a(wcm<+1Vl y+6"SH"?7wg:xuH?6#<MXmE%4X2EZ S,7{2 ۼZ[b~^*6o]BeKa?LK^Ze}%s4kahEI٦*t۲mPj+KlbͫqֵRul:lsm/ԬkCzu]˸9Dq-빮l-#QW eʔ$#JLHY"8Xr]+~)W$/U~Q)ʅpEy'<[!܃Yż1t7|ۊQBRu&T@j:\L5IRԀXݭRYVxO^YՐLܢߗuJ@o/K} J#Pdc:9pHG#KPX&.q5َ,Gjo2;uq.,q3l>P/^0GO4l^\NGV G3 w><\$丌X]9bCJLWcqҦ6H&gltҥ^եOuo4gH꣰+y|'{X[rzTB^i$1qO➉ŞdyRaX,|!S$.TFO&ͽNkpoRrFIII>KB^ޠgS@-H zdW BVHX+' ; <)XTeʆUVU(ebNL,n{OKqޫ)ڸʐ6'.S8\>84ʕ] \n ~OFo }HYSs >Ź͚پSX[hbBڟ8tf`5 |?` 4HnX< S1?$0o.f0fi8Ycc 1Qu@fύC PD3I&s[1efƌhLoiqڪ3fL ((@Lс<؈ =x*)`|W ~KwQ{s+=o^[6 Q1LLjۢ0m,&MSX<`*30`1FkZن;aX"FԎG=a֐Qe۩BFT'%`^ v>ۣ0} ڣ1}t'i;w,ǠF ؂ h?[?CAzdݛX'$b_f1G Dqrº+RW,] Lz?]  |d8paD8vs 0CK77[7E. ̹3_oI}^3vi=EWGA a:-Dr:0 3G_l]BG>Z{#=`7ԧ__ DQԾI@!j{r aCя =aOpaȞߓ{G{]E Ybj٬5{#|Dc1=GO>g`|C x/y=dO4 rjbE 20*;o!"\>'ug_KH2kDT} ** EZnnhYDQA@B"2bM01rRV&NRV8ff\*5qܢo~T{=缤O~ld!Hu'3enDٍ^ӉYDdd"d3AvtS"oq?xW?" ~ 1 1tKlF3`'5ڨqssg#>mj O9z<&ȿ?eg7N&qdOT@EꬤF5j8s#5P{8g;V!}i_2:2G;C5ķQĝL%_AԌ3sӨCBjF%5jH-_'QB//} Moq~$7 /DÁc 9}r]*|=c\| urQDUԨF-5>V9wd4o鋫˴wi0Z"6;ٙ0eG'\;kBq5JN&gͣp y]U Dh9YВSG|kwqlCyeÆo$O^17x Ұ,\p9bu,ǙU85|z6S 9G#qGF^Qߠ1] sh!ȓx吻|!+ȍpy~.)DpM1lt-C[ :jtmD6toO$xm}qoc<6WL7OfRߛ70L.Ot%wW􎝆|=^ }`M.Ůk:-ScJ O9Sylv M=D+4xB y4O3 : ]&s6L*gsf2ϴaR4{bW*UY[Q?kP7S+}]s_\uS^})ZO.;v{{bs%}4h1' >VlDoj|P[*BoηUX3P>G\=X6rޏb|Y,yP<\{-]~tS\ `*aRJ=ʔXLAҎ"eBY$,W ˔br+-]--YtI#e?!,CG߈.10vƲ1-Zָ. Uc6C}PUT:(PLy!E_H^X 1cx@k[Hb[fB+:q#1&.헥{Rh2q<3I+s#kvxa>Y=DlvBP&-~,"d%ĞXVjI 5bԴc1ZiCvZ3\o1\r{y{lb>Kz 4&Vq.]#4"!RhX0&>'dӀ~M}̽5G%]3G%>4G%VhdeT>` 38E<gTJ&;iHbR48%LSh@jT6Q}Ҧ+:mҲ+3m),)tUShShdArCc#˰ Jsz2gکOzguStV_ٱ ώS ˙МSPE9kS+c͹,2L/RXݲ|އB}0 f8*]A , V@a Zƨe|,3mIU7"ue<-\GacFgWA+%r:!-;klql}Q3dcMW2UP #[yL@^RE7_W?7Hq؃R)`+5okTg/S |!adg,@PՑXuw\ xº2s/)kS ܍>iޖloaHa1~R=Ci}_CP o,^Ç<OXI-A GhFoz<^ÒsdwT2GvNI8Eag0?:Ǚg hrM@-H| -/:'֣?<ŕldllj֟%hMFg&9GEq\#dG(+t|+e`؛=vEHrsh@:st4CjQNFi-9c֋]DNg:ЙCGaoA:N:K(gJm5b>i-mP՝ U|ǴUl';cWC(NzM=~WO2|u{7W ?w1ԄZY?T}40VEq*  zM f*7h+;8WYEYy!GsC+-)%)a_ڸŵ7+x(0fl#Yik͊P- %,@=# ^+eOiJWZxR#2Q>_ h- ZE%Hy!@$ $BТmN!Zҭ͵{3nu;֞vNZ!~>Ͻ`͊O= S&',V iw$uLs0^5K>[R)G{Z 6g-=Xaڌ pŸQ ?|mX o^:"YDX\f!U<ຒX`d?|lΞH)EkӰ:;9:rLh)GCN9u]Q-\ʰQjIY̡TP/*IT80Tf?گ>8b팣E5yhV-O j Q`e<y [v&*w _4#2]Y&H4cO79rZM;렂Ʊ _39j&c6.N:tpQæ_/'EYQZ' ̆wd%["G+ ?Xu ;i& }60(Ӱ9lT4 a+,ƕ(5`1h(.z^ɊLC2iTVh#HEc[LyB~'Z$[s8ܦIpf bLa5eXX0QRBq*[`4(0zOd:yc/"ɴfIJG=L+s3Y&Pa0JR si:K0PTf̊ʽЗ?]yX}"z\loTBe(me-rA/{"z`-]c,Mb{,KQhO|+UA[YJ*WC][:l1pYUD+~g9 ۀ}M.G}\fN*KqC0TGB_]"hj!&y5*P9P:+ZlW3 tu WH=*gDjUO!wIBFs/QwZǀ'Ɇ5y0(Ȑ_{8CAGL V;V߈Vx2oR/#{Z$y HDGqKU(=C$ s[*e^ Oo*2}QHGZ"țRڔM*,o6`YUHj"ѿK['?m$4CB$!s;ڹ'Zg[#cR3 Hi@R$bi,i]G[Xܪ ;u Fl 11man% ¼"EB̺1q}~ux@s `3]9 ;v#%L-[Jpmcr60%&^JI$"|HL8x˥^ȩI @@ \*""^b2T@W=j>gmt]36v[NvݦsT|?D~;K NH#H3i#ϑm%1|I1G,Cy|G3y~g_2)ѐ,O"ƯgFCldbOajWL#>[_0o69aOƒ #5 &$dP/:jTι_72~w1N.~vp:kߤ0ڍ>$%qαRgrragaoj^ԓ24jZ}\ q>)tvpgp//^_ğYopjG708=]O͙xԓ3I<87+]Jjbf@FRcn)C\vV{k4Wy? C~9wyD)B8%3/ DQU^jM]c:ut='ye&I-`SGch"x^Qy1H}^Y:9?"56qj66LubTZGKB<kW)hVub]X1eG;Kf ?6I:E1g ~s7ڧmFeV 5f4`Up>V.X6!QҌ%!X50<_EugxG|Lw d*g> Iǚl)X>#"BTGP\,SEsajTϭCFTmCyTG@Y̋ Qo O}؂ձ!|u iKd煕Q~X=u1cQl2jPkDe qN̏,Q⟠Hn (D •>.SL >{Hh%kS'F$ $Ơ\*C4 z$d(OB܉(L\|2dp:F87`O9Ia0x'29gIigk譞>'B>e`H![BIFlp&9H*F^r%K))w"KyUȢ(S`n:ظv``볎>VG-}+Ǣ$t(#R#O J٪\Rݰ#+F¤QsDyUd _Ads6x:ْ>(}T"O :X5)hĄLm6KaLAn6tۑ? HcNAF?V'.w/Zd=F.V}0,9ԋa+`ԧ!Ð }Bk\q=LH5|Q4@A4 " F'Aj?xK1#MQ2gLdL3a Yt ZL ԙyH!RU2d"9k^>d{|~y0Bc{?wp$(^ J5ři h!Pۢf"Ֆ UlRHqCSyRHoԾsGBl$va3#{/u+9Tq/𹼜<\z1:EPyCYH΋D# rGd $:m:!qAEk-b]g|A#% 9i?wQ{">9*VK!G%=B$A ;y @TQ `NQ#"7#xŠO!m9B!H@+9Κ~/;9_ 4s]QQXWeueߑE=-fQ(̸ `T 0q8QU bզAlVMM`L6{bCRc4how{ xmcb-fJM`PW`ŘՔhSE(4\ldZR[_yE`oجloCkiYΧ6B}3UXO|)uF(6VvЫ dά<Ȇ3D$ͭlJabWS2mzAWڄf_0'xni]' )vba'luPC!d|R[Yp156v)40wIwvjQ:jXG .@Z.Z}-Kbna14,ttN_tb\KK34@ o/uahj!j6pENc$\bq'-%r?= kgY,zA&Z@q.IX4iÁ=9]lix3o'3#MF{- ~FK.wuNĐv>Q@$M1p2 u1(}\4׸7qț|m‘3}ldIƿ>_{[4Ү)yWP(]%| [6]?>FC#c61qF./l~ `0)`(bJzآ~d|isY;}/\pedZ AwH0Ŵ}k1˰_}- :55u]|gu N|OCx̹7T} c ضa{.0.S0I v͏C8 Zנ"ZIJa/`߈"ih~1/Ƕ \M?Ч<~b*-a8k7刦NƠABc")}gcfcߪ^N*ȎSD2P-T+nKK_ϡ1L4ʓIg#?EhXrc;YvO^Ö}51%;JUhi#:cFg1v՜\; keҧ.]:6k 8qW:Dy{+ePvw9] ƧimZqGiV9hsV8s\ eJ]*TNuA2_T=z6k\FXᷔaw͆SUnZ=̣U9R%3EiI *4,\JhX|~C9>5fSvVfspN_FъpuQ7N :sh@ h;3bʹvK| ]9ʎ UVd21fF ֌=Vi)=MSf)kRb5)\c7+9Zh|qݚy};`sآ#;EXojz\kj|MV*%~&unS5Qr5.at_7W=hTbF&6jdѳm/uT@T@S2 0 ]`H䲨1 `y ^K$Zf*hY)=Zֶɶv:k%ִܓ?>y}}˚ƎL}%q4bb\9\0 -_EUG$+7ª\eGڔYQ5ʌ5EJTjl,5?NܛEra #NJ + q-z )?zrX͎1*#&U,*-ήԸjYR)JNإ2%Șx~)S'FNm[q88GE9^2LTaJ3D)Ր KB JI,Pr\%ͪiV'4˸Q2ː.;?^b911AaaV٦0QG%#dɔ$cRf%*1D ɏȐRfřE[*| w)<@75؇~gא2jSHdd8̓d4*yS~NC@SKoޖt/*zXlȤ,bI&XP,cR4QE *(M+NTV) M-Ճ%4CJɧ䔼K>yC6&35‹JzYQ΅Zz-X҉oya+>J+)5I0=hD{&3SV$_VqOjlyʳ<˳:8e ,\~Zʹ4\SHl2y1!P&JOոJ? HyU%ʳ*UcQe{"n[FVKիUF.wZVmhȠF΅ǩzr@LI1Z(7T:B(GFe遺 : ;лX_mQg?ߎI~%g#=Rb|J cʥUÛйM\\k1>$mIgiໝSQ;vMG'$]0P`C@uQN w+ }|7[ًO FwJ]#y‘PRa#> eԥ8 t4v71qzjiW|?-/҃ ܏WO1xNA^SIAN$'gR,Yhmy׵u/`ͅ35b%Ұ>Z ҅\Opn!p8>c"5ec,ýKKf+ų`ߐoO!|z-Kp\uCѫ 7RnWosܦHv;; PeP hfh(MEyEևb7:󺮢gKp>5HCax$q`\,?Yu !yaMZ`{!`{9)E h̏Qh;:.iofp^'Ѻ7/}J3G~1`9U~ YKm@k6Ӣ?ڵzGOѺѩlS$8AQn<r_ w_pYX;|r"𓈏4-"el ֱc X:V;؎t^*ׅ5h 9$ V,a߆};plՐZ| -]ɳ|kyF;lݘ؀m@an_L b -M&kk^5SWUv6ҤjTiViӤݴnUNC}>}}.Wy%z"Y/_{Ob> ۻ3>wiJ>EOOUE79𓣛}!\+q~F6e;K 0"WҽMyޑ`HRsxx/Yڱ8]c~9Xze TtOҢQB|c29wxz8-RLSγhqyi'Ooi=lff1s c`4!F?јop4Vc:Wy,=|`oŔ>1 D`1*u`6ƎjLza"ΏnhF0pC LÒ{_CI"%M{MlbdK II%LTc,QcI%:0,APڀ!i H;0 EldcdsI^EwUtmDG{+3wLYfV 37C;1"##) /ՆCГք6tw`z?:GϘ2іyYwz ^ω?9B x6`uKlfiq'L) (R‚@v9NgѦUGޜ!4LE4?-xo s@Ïy uQD\, Nݿ{xmtMc[:oCxhdj2q@FV Z' ܨ-ZKg1TΡRav+(7~@N<_&-7p%~X Rud h,LGz}jTpp2Ԣ؄ c;E즣(3@y6uX-/>K%"Y=r`wps:T:&9&*Mp a7Qn.CŅRKlm$iXga]GQ"}opKcm*q-$ RG7u2VP֊&E&.wm  li&IX9㡭BS5uv۠T!ӆ^(Fp Ho"!R䳈=%.p$[;xuwIE덂99r(ݬ«CׂL:|Hu!7 yI$lBr ҖHlI-_Y̷۴?77s, ijڥZ Qn Y8H!ůܟd2pAф;! !3 OqF_|g|AfY㼓#VA}FK=J} io{eD$ B D !L`0!J{e7#bɽ6ɼ0Xa,L|qzJ] PSSm$;8D'!b8 -,FI> d0 1y7ȹf{5"Iq[\9 N98|_%~ / .) ._\Z!,8 ]u'0B(5wN FO3朜>dPg\Ҥ}jCtrt\\ȯkK8D??8{=<<wrx\O &5y vh}q- t=! P Fj0ؔf/TdV [=v]Ku_}K7펝ץc+ XASZQvg+tB-l7?ckncgX>Ntho+|+{n* ^k踂?t\B{lum29wtt"w71pyG\Vx塿ۏa ]x: k %^i optDoq>!;p(cv;i w|-88,~>^rlWaد@Z=ZAXf8Z_m&:-D`kwp~ >szK?"'f)X~vcN^F[4Eт&tl2!'*,42"^q6Q{rר_\1a#bP Gcᨆc2pӜ.E(>;Fvf|¤n 3a#<H#8 -F"t)rkKwմZ)eZTmjKU}*{lVEσF]W=x2undy>уnOun5W&h{j3T힫qCU1Bc=U9^= y.RJxh~Km**qtS>TgYB*ݨ|V {Sy+0w^s6|;:rT ?Oj_J#5ߤb*ꛪa}sTw+?\Co50hv++2*3䞲B#u jv}L$7TA* 2 (F588CB)7P9!_) t21RJq%ڕP xwۜC^_IqD7g C"De(#<[JԈ DNRRl٣Zw}L֘Kp(щCp`<9k6d>FBr<̨~J2(-*F)QJ+):C ׀r%j"ǭٴ]&gzWq2}61dZʧyo":*1CБTCd3F*'k\T%b.TLje΁kJJ%QC|`jK0~a||}XzfXd/,`0oJfJj_5 TE WQ%+@3T.¤Vބ;@_Kڕ|VKH F7D`aLr_hvȣ<ȣ<iFF6wh es-**12eXI3b3Ism2Q"@zcn^NVN$)I&O/\T ypײ ~ h x Nw 8 ^o7h:9ϚQL3xm\|pZ+>V4X9np 9 %pb]79E|Fk.=tqߣp_ ~ @z! 8d %8b&qO, 7G;[s}F7}#8>oDX׏xobE.!}F'W\G8?#} y 7{//x8xB/?xxd!]ʥ?8 Jqq`2ϓ9cʚv鷈uXi<^^G~_['228}@-1/i z]@"b#v91::f)d̲%8 )=`A}`7x#vL*%x[fEA>Nlb=Ӊe2į~xVav];aA-63ڧamFnf:iyZG1cW6!~>gbE,C %F3QVXn8ױwl=>t 3mIB6wh=X)p1b8{V e5YЕ(އq#%Y/>`ݍ.F($ p< G 68jȣZӴ<G UJ\ #J7á{6h^b{?v[!{8v !J$D @2-Dʂ xPW`k,@9GY?[ԟ0G^m8rК.5~a_\0A O:YT W*N.gd m$VM{Mn+rޓ+}GXo|/DA]U9fy;kfTW5-hr,lSNCݚ;d\%X mh#aǕ~Iww[~8:ZڲE7*HFyb=41\ T3f(8NYɲGNWfd2"+Y&YMj:.,/>R+цhkknтҖQ|k9T(ƛm,S/My2̣d3[n\F)%fĬШW#^wh 8ӂ%mhY y>̠NSikTF.+_l# 0 3ΰl (0.D4Dwq;hc9&٬i&VLlkXSi&=iZcܲUt=}kPqQE! 0ԩ,+7lFSNx1WUJ3nUK)rF7r+%.^nrn-d߂Y?=N#_<&0ҧzs+&OQA1#RVg&),3]Y *հI2dPp<(0C9?(8/<39AM֪lTi&Sy?;pMgq$*rkPHnȐP`~˿̖qHA>+#C *B ܼg9G0s%\*(EYX'btTP%b_qq-OI,WWҍ1 %gحNՠ:iV4x i|U<}/!㤀A+ Р2|ˌ)h`yr\rYX 0嘵rCƠSW.jB豉4/Ɩd%ӛ BM 0wE=\.BD."c'1!Mdb61;-s8KpG`O+yɇK*a@ȡ3$x \ \5\t5\@5д!`u+-M_M;"88Lum6{&P\ U jbibh[6ҋP@/DG=lyC2D-\X:` XX G} 35ã9p5XᲈXĢ.$ml||<[\ nm 5ʡ]ֱ@!H]/Y@ & VxҏVx£%RZq.|j&UL+q4+ZOX9HfF$|6K[w+(݋ < d۹xvzю(8r965]@:r;zgAK2>Ab{婋t} A===uh $߽V3u"o%9KɓFbvI9V#= u̐ǜc@E?eb(Ea.^zCU>_Z>QA\%!Կ_p55AGy1~ [/ g?>q&8Ǣ%Yzq]9@"g 57<Ǽ=f/΀w9Q|P5Xr*.S 8yP  q-M\׸p@E~_).: x~B>G"QUmpA0ҷx̯5c=U K+<.$;?1?R>@k?eέx ^?ni 53|5ezqA#_L ^.{8 3w𗿂8#=C=:n$2y?t,Y?8VrEr?أ8G:rXD^]M2m~A馲.= ݠ&救GZq+YȑLLV8DDRKX%_"6cvv'iP6Դl_+u:~G-rE.9ϢB1į DWc Ğ2 YNy: ߰Z_j%yWx=19v-{E'{Cf$Ilq1 BjrԑdkL76`0`n&&`CbH'@B(HB[Fi.K@%Ye (mfi6AZN]5mӺ}m6MӦM۪}ؤjڥ4G.S =z?y99『w f 8$7el{W('ߡܿ$xqÖ8 1Ua#f<ߦg3q;cX5#Df= MSw)h5졅p$v1iL.x 8K)gYBDim` $]v>NK<n'2LY%u )tY='e*\v/q~J M5+ɢmIښQ{rڒ˵9%M)aES՜USj61m"Z~D XR(j ?R/1~ b:m:r"8+GS IږVQQU6`(VBZ7֫޸Qu6Mݪ5Ri3)yNU VUX>T3SKH'bCطEȓ&K"L3TgU\Z_5ZjUm(hک_Qgͪ,mUb{Sg;>S#{Lo&Yg{(C$;I!Qk,ekͭ*[*m媰W^2GJ[SI39OQsWޜw6 %33IcuKZ~vlF9{IW3SNʜ.*8'"WH>涩 Gyv?ʬQ5` Q)-[J&RVj0vƟ^Dw;X҃][K> 'dMSfI,kr@ ʨVz(PRB=J )1N0uR;HfbM ~f/w_ዾKax e"'q!a$|:xĞqbMG#a{i{sp mx AY2`͐ѐb: }0q8k]A(nbL4n"LvLavL"&i0bK4A<&?åC){1ǎJw ցJ9>c;cܘɋ9.?7FҳB_Hx| :;_ U:G;0\|Hv,bb,R(2 $y{8G^~;?oسEi㗩WH*_%p p Ǎ' 67%X,e 2X&8ҫ>_{Ŵna"r܄*_a |n]M>gVcB~PW Iʊt9c/ggTW6\ۏ_ݛ¸oo=^I/G!R6\{tƟ6%inmzK4IIKKEZ.E\1AAȠ ás)`e2q2&sӝYiOs~/<Yz,GG>ۇ;h {mf5*c?,ks51#ꋚ b԰>_8?@}^Gnx7u6v̀/b@2(CAw6ڦq-gҿu7g8?R<7{{BGeER?.jK?wvT=:uч踂89,C%tz gz@{཮kz _>/߈M_p귪һܷtɜGG8qyqa6WqR6K'Hz0v]_p|ܟ>ݛ,::)tGsc88#8Zܬ}d/ _R@m!B#_y \b3e'"֯MzGek=:Bt5JR=pt±nѽ(\Sݰt*O.r?b̘C"f'Q~mmIG<4vPAo ɠy#ynsmEo  8,OUB$P]*,Od_ 2\G{?vX-s^tSsd+\x )c:h_P ~/k$?fOyF>OqmrѺ!.sSc>;\䱧"p᪇pMdptvZf^w@dG\ȝ -a4uAL&cjHָA9ʂ͞*P}LHuª4Z59_'`K0\RE-U$Fp+mw_ղqlI&&cqjHNQ8:CjU`b+4$JUI $5ȗ4VH%oUqOxBwU`BSDEOƮGm%#P1i(bPɨ!Ft94y4T*Rjܤbs *HW5r[)\ʱ\zD $#F#ϯw泥8!7#kȍߚ YJ-*RBK UX):Jn[rm3/T}RcxGi3-»[1nŌsJnFS'R*U`cO۞<{r%r9|I );AY㕙>MNgҝ+*{^2^5MlkH=Sl-~@ Fy24+iSө̌\P 93*=+4L={l]< K7#L_O̔zvx75RxeXՅ|vꤖz P#6(e3Ǣ49\#L*Yek.{LddHO*sLIs#>|o #c`;3 mcHrSCn|Ĥ* Y|vY ke,K)EmJ.+x U\Qy|;rȻ chiCG3#t27^RL%VJe,u) % VRYH 2*ۡXxK^n"/˴2K-pg]9]m jF_-CF2֓b$&@>*-JLx_b}^ SH~gCcc ~cUEp>4q*=NsaXFh11+)`bA MhPi`0MA C?Vj)x6{LzӐأVBV7q7 $K%l\xa0t\x ǸcBHuhcC걓zCON0yy@0"dF\1RkRivHMdM4pġӄ&45GoLLk.Khhh k\ni)![ 9<h#;?;: 6+Xy#tp 30hs1 ; 9tG7&4nrхU]Gy,AUEpܳ:^J<a<2h6ƺ gGI'M/uE賏FG.Y'ṿ; 1pa0p{Lߐ {%W@Ca!WқO c *r1@_RqpfLtLRl`ut^o$6hVӐq -8.sfp>rFqخR+_W.0Y āt0Rοgjs;pH}A#GGs"^@ aG>|Tp!X4T |pƲ~kg88K8G<N]zS'u/ >z:=E;N*ңn<7U#` :._ORܠԍp/h=k!G!^7YJgz\hDt*bn 6^ 489x,؋h2GM>:p6Nv4#ԥY EfUR0we mXu8# teDt2!Ue/Z"\B.j(fmV]O{ jȭ7\~t \χc9)2xYŮC-Z@泳R\ ,F}9(48ĵ5xW:EiU5YJϨ.&j$ n1 BxS(fYjC(i>'{ogG;k}+l$n9C5rxxK;\p%'/\p k4\5hr#{#PN. idgqedY1@3zMaL$?r2C&X5>ȡ1A.%jTPFgiD a!w+'tCV:7)5C)O( 1|!OwDt.Xm)1PANO!ǁ紆*dT^Ur .eGxGRZySbdSd{< =ZQ1]!2YQ,jLN\r,rNi 9~LSeLȄ*W*,qB=9  NUHO]pwL,Xߕ|VLl)f9#'CNPEyLxl2{2yeLJUD0(-U3Ui0v|:ɮL1v ͥB+tr)D]᥊y ݸ~0)\*ָɽû{Xfmհ2V|ߵ=růĔTMT۩jEZWj^vqq*B˄ΆKZ[µo5c[_U`8,G bK^2ٓ:hh5i|1/jZVXA>ך_,N7Ѧ _\[=_iu`xD@yy_2%ʹx>r؏{Թr`jf>+Te$9 `cU: I ~%ٱ/袁/h _s)qqlK3[j ML_>7\;ֲc4QkTT((kx[w ሕKk4U@{.J1P╢4 ŗqE`ƎUn\ɼEi]l'${.yǵ1Ja} !Ϛ:mfG3m4I3]4E35q^'$;i츎[u r@ 1T<ȸѹm a-߉MKvǀz(j-|BL9~3p.Q3 xԭGn߶dN;|ܛ}6'Ѷ$3'qR<%&4S|qJ~DzR>ދx/9f |ʸ'yj= kâٱ ]0!,ڣp~ӳq0rN<Qٗc;ޥ`|<\^\e>PF<?WOcq|xiorM_a{ u| =&RK忚6W$dv}*1?X߶i{#_\Y3Nmc} 6>|d)];__/9Գ 3%OlOI' 3d,mB=E;bW8{; ,g_^U*IltBtl x( $/g :{'iv6l`gv;8hûCQO)͠s'I=. \x)9)#+yJ9ۉxs'5ۆ Tx>)3tSI/ WB)t~-vk~ƻFvNZMsEp]z>Dk;ddI8,ybi|ENbWVf{crVրco5(Xe1/sSG j+GYvꎣ7b%8pTȊ*J3LJY–ٲ_h9 ukTz.?.7i<%oD,!`R8\)`. .jȥHB@H1%폎@TXb/&f:.cK4#1wsb=8|LfҖxxCCxt $2N(mt 5&j0T?CpmG2aEh9K(U/0q&{@AkX = =Y&zfͺ uЭ>HV^iPfPwމЋlxH9,4ٲ5f` ,x808!qM٠)]I l"10BTI##P$Ccba܍2Sc5#&F&G;Τ-gҖH#D >[3F5b( Ab${izз9&l^}p"F;b2!{asE D&x#8j$,byb!p,dLY]ّ!1CHlp\q .U%NLH-Rdch ^@D3Hvgxq|Dp*жhcHu}67jʌ ?R#3I3< PS,> ؞Eq\=-R'6;9IAzɆٜI6|XdA,@W־+Y?[ړC iBF-(ӊ -A[(oq@j ȡ^s8j$,AE$h~?Xhڊ>ǁ-•a0|!St+R)5D@*zmahCFnlV7qm͐pnyQњ+{O#Ok R>5y]Nbs0 ;P^84~EJcil)%dtUY#Wq€rFtGz](9dj_8`]భKJ7HKwsؗ1TT..(rۮѵ}4f>z{ϟࣵLAϻsƌzfzkfL(քC ~h?j}CJ3E%/c_TVJ*pT_xEy\_^Hڨ;Wi YA"ҭ[l!Iv^يR9$Vd2nqy>=/<y;s+Nw $ ӟmWy0\*c<0gלuN@B! +G[Yu?R|^rrH/坑,~$K]Kn`l=Z5[7q|gUnr"~F8ߛ-cY đ\ೖ-K1Es)`[>zyH]PF(볫ܤ;dqFV Lk-zPߔJK{wWy~P'C8d,ߴ. :J@7 dzqF@` V" 6X ##  ZeWŔԃN~a~qfu#E".lйy.?Xϊ ;m HK=`(tu4G!gn_:^!B@zhCLZ8l$@ + @ e!OAx C8~ⷎNs]=/I֣3ѡM*{q6ljK~!}9Ym!!_7Hlް(Qppj`0GXs,D`+/xGF@ҚSШ s=t##URuMT?|zq+[:sMnִ䂹33o\P7.B *OEtO1o,N4GO\ٞ~pc݌)GR0XQAl(f4 M)h@<׹L"]NJYsr,'%hݹv  ݆/U)|JnPW x kFEQ`0|=t[ 1x}fpc3A&ŽpJ ~ 7%1,۰PRND,^HU0uf>7웻ñ]zQZVq6 S d`0XA#GVJ[(9 RWvHo^0x3 bx p`+gQ(^1ױ>9ږ騬*^x#qb ,Y2aHwcVMOb/f=-ȁ/} - `=瀾}k) 4`" C!)p3:mu@XoQv ngn3w:s+*qBV- M$NreO{}v R` 83JyMO4)XZGyQj{DM {_πY ̸Ӻ|)weUefᨈ.A]]dciI~\w<8/t Pg+e >*7E`S# 3\GHpχHn aKS[K 5uk;mɶcVރ iEHD_+߾U\'9GVXJ¬9M<~̨փI+qijL9%A0pcF"((`77Q#'q h[:-H,n#*Z_YXO =Vy!pLYzY*K;x2}{"w7er"Iw:GSy\V[<6'Rչn%:溬'5mDtbZL\&$ ܾ~vן{}߻<%E&gINDHJ"NƄdD] Q!c@ d *>7 8PW% \ h`3^l:93cM|;egA :܂8XJ[7XI|0|N7w[{EkvcJȬi%J-Q#u|FBѵ<~ԠVTw|_JvV{J,͓ɯ)l/` R|Vxfm 96pL1c3Y0ߜ,/NP[@Qt+eKTe9ۏ-p Ȯ|BpW$ %IHO޿y:~0?_(gD,rE}KcШ+)J_*=I,?!4l=Å[Pծ=Ğ [ }g OZO$o!xL=5dbBC) Oմ>RIr\r"#;@V2[kclzi5a#*Xm?;62.#:ĉ֙Li_8L+ endstream endobj 9 0 obj <> endobj 18 0 obj <> endobj 19 0 obj <>stream %!PS-Adobe-3.0 %%Creator: Adobe Illustrator(R) 15.0 %%AI8_CreatorVersion: 15.1.0 %%For: (Ben) () %%Title: (Untitled-1) %%CreationDate: 8/1/2011 8:34 PM %%Canvassize: 16383 %%BoundingBox: 82 -553 493 -229 %%HiResBoundingBox: 82.7622 -552.2969 492.2744 -229.4507 %%DocumentProcessColors: Cyan Magenta Yellow Black %AI5_FileFormat 11.0 %AI12_BuildNumber: 39 %AI3_ColorUsage: Color %AI7_ImageSettings: 0 %%CMYKProcessColor: 1 1 1 1 ([Registration]) %AI3_Cropmarks: 0 -841.8896 595.2803 0 %AI3_TemplateBox: 298.5 -421.5 298.5 -421.5 %AI3_TileBox: 0.040039 -841.9355 595.0596 -0.075195 %AI3_DocumentPreview: None %AI5_ArtSize: 14400 14400 %AI5_RulerUnits: 1 %AI9_ColorModel: 2 %AI5_ArtFlags: 0 0 0 1 0 0 1 0 0 %AI5_TargetResolution: 800 %AI5_NumLayers: 1 %AI9_OpenToView: -687 184 0.5 1252 619 18 0 0 271 129 0 0 0 1 1 0 1 1 0 1 %AI5_OpenViewLayers: 7 %%PageOrigin:-8 -817 %AI7_GridSettings: 72 8 72 8 1 0 0.8 0.8 0.8 0.9 0.9 0.9 %AI9_Flatten: 1 %AI12_CMSettings: 00.MS %%EndComments endstream endobj 20 0 obj <>stream %%BoundingBox: 82 -553 493 -229 %%HiResBoundingBox: 82.7622 -552.2969 492.2744 -229.4507 %AI7_Thumbnail: 128 104 8 %%BeginData: 15054 Hex Bytes %0000330000660000990000CC0033000033330033660033990033CC0033FF %0066000066330066660066990066CC0066FF009900009933009966009999 %0099CC0099FF00CC0000CC3300CC6600CC9900CCCC00CCFF00FF3300FF66 %00FF9900FFCC3300003300333300663300993300CC3300FF333300333333 %3333663333993333CC3333FF3366003366333366663366993366CC3366FF %3399003399333399663399993399CC3399FF33CC0033CC3333CC6633CC99 %33CCCC33CCFF33FF0033FF3333FF6633FF9933FFCC33FFFF660000660033 %6600666600996600CC6600FF6633006633336633666633996633CC6633FF %6666006666336666666666996666CC6666FF669900669933669966669999 %6699CC6699FF66CC0066CC3366CC6666CC9966CCCC66CCFF66FF0066FF33 %66FF6666FF9966FFCC66FFFF9900009900339900669900999900CC9900FF %9933009933339933669933999933CC9933FF996600996633996666996699 %9966CC9966FF9999009999339999669999999999CC9999FF99CC0099CC33 %99CC6699CC9999CCCC99CCFF99FF0099FF3399FF6699FF9999FFCC99FFFF %CC0000CC0033CC0066CC0099CC00CCCC00FFCC3300CC3333CC3366CC3399 %CC33CCCC33FFCC6600CC6633CC6666CC6699CC66CCCC66FFCC9900CC9933 %CC9966CC9999CC99CCCC99FFCCCC00CCCC33CCCC66CCCC99CCCCCCCCCCFF %CCFF00CCFF33CCFF66CCFF99CCFFCCCCFFFFFF0033FF0066FF0099FF00CC %FF3300FF3333FF3366FF3399FF33CCFF33FFFF6600FF6633FF6666FF6699 %FF66CCFF66FFFF9900FF9933FF9966FF9999FF99CCFF99FFFFCC00FFCC33 %FFCC66FFCC99FFCCCCFFCCFFFFFF33FFFF66FFFF99FFFFCC110000001100 %000011111111220000002200000022222222440000004400000044444444 %550000005500000055555555770000007700000077777777880000008800 %000088888888AA000000AA000000AAAAAAAABB000000BB000000BBBBBBBB %DD000000DD000000DDDDDDDDEE000000EE000000EEEEEEEE0000000000FF %00FF0000FFFFFF0000FF00FFFFFF00FFFFFF %524C45FD0FFF7E5A3584FD7BFF59352F3559FD7AFF353535592F84FD79FF %35352F592F357DFD78FF5935355A355A35FD78FF59352F592F592F5AFD77 %FF8435355A3559353584FD76FFA8592F352F592F352FFD77FF84355A355A %355A3584FD76FFA82F592F592F592F357DFD76FF5935355A3559355A3584 %FD75FF7D352F352F592F352F593584FD73FFA95A355A355A355A355A355A %5AFD73FF840D592F592F592F592F592E605AFD72FF5959355A3559355A35 %592F282F6084FD70FF7D352F352F592F352F592F3505065960A8FD6FFF84 %355A355A355A355A355A2F2E052F60A9FD52FFA8FD1BFFA92F592F592F59 %2F592F5935350506055A5AAFFD4DFFA9595A2F3535A9FD19FF8435355A35 %59355A3559355A352E05282F6084FD4CFF8435352F5A353559FD19FF842F %352F592F352F592F352F590606002E5A60A8FD49FFA85A0D352F352F592F %35A8FD18FF5A35355A355A355A355A355A352E052806605AAFFD48FFA95A %2F5A355A355A355A35FD19FF5A2F592F592F592F592F352F59060500062F %6084FD47FFA8592F592F592F592F592F59A8FD18FF595A3559355A355935 %5A5960595A2F592E5A60AFFD46FFA8592F5A3559355A3559355A59FD18FF %A9592F592F352F5A596059605A605A605A605960A8FD45FFA8592F592F59 %2F352F592F350D84FD19FF355A3559356060845A8460605A8460605A8460 %6084FD44FF7E355A355A355A355A355A355AA8FD19FF592F5959605A605A %605A605A605A605A605A605A605AFD42FF7E2F592F592F592F592F592F35 %35FD1AFF5959598460605A845A605A845A605A845A605A845A6084FD40FF %843559355A3559355A3559355A3584FD19FFA859596059605A6059605A60 %59605A6059605A6059605A5A84FD3EFFA82F592F352F592F352F592F352F %59A8FD1AFF5A605A8460605A8460605A8460605A8460605A8460605A60AF %FD3DFF355A355A355A355A355A355A35365AFD1AFF84605A605A605A605A %605A605A605A605A605A605A605A605A85FD3CFF59352F592F592F592F59 %2F592F592FA9FD19FFAF605A845A605A846060608460605A845A605A845A %605A845A2F06A8FD3AFF7E353559355A3559355A3559355A355AFD1AFF84 %356059605A605A60595935605A6059605A6059605A605960060528FD39FF %A8352F592F352F592F352F592F352F3559FD1AFF60605A84FD04602E0605 %280659608460605A8460605A8460605984FD39FF5A355A355A355A355A35 %5A355A355A35A8FD19FF84605A605A605A590528537E532E052F5A605A60 %5A605A605A605A605AFD38FF842F592F592F592F592F592F592F592F59A8 %FD19FF845A845A605A600652FFFFA8A8FF53055960845A605A845A605A84 %5A60A8FD36FFAF2F5A3559355A3559355A3559355A355959FD1AFF5A6059 %605A602E28FFFFFF2E0552282E066059605A6059605A60596059A9FD36FF %59352F592F352F592F352F592F352F592F7EFD1AFF605A846084602E53FF %FFFF0628052E53065A8460605A8460605A84606084FD35FF8435355A355A %355A355A355A355A355A35357EFD1AFF5A605A605A60067DFFFFFF530505 %28A8055A5A605A605A605A6059605A84FD34FFA8592F592F592F592F592F %592F592F592F592FA8FD1AFF845A605A84602E53FD04FF7E59FF7D2E5A60 %5A845A605A5A5984596084FD34FF842F5A3559355A3559355A3559355A35 %59355A5A85FD19FF59605A6059602E52FD07FF5306605A605960352E057D %A72E2F84FD33FFAF2F352F592F352F592F352F592F352F592F352F603584 %FD18FF8460605A846084067DFD05FFA8066060605A84602E052806282E84 %84FD33FF5935355A355A355A355A355A355A355A355A355A5A605AFD18FF %84605A605A605A5A0653A8A9A87D05355A605A605A602F28050606605A84 %FD32FF84352F592F592F592F592F592F592F592F592F5935605A6084FD17 %FFAF5A845A605A8460602E2F2E2E0C5A60605A845A605A84605906606060 %84FD32FF7E2F5A3559355A3559355A3559355A3559355A355959845A60A8 %FD16FFA86059605A6059605A6059605A605A605A6059605A6059605A2F35 %605984FD31FFA82F352F592F352F592F352F592F352F592F352F592E2E5A %605984FD17FF846060605A8460605A8460605A8460605A8460605A846060 %2860606084FD31FF5935355A355A355A355A355A355A355A355A355A352F %055A60605AAFFD16FFA935605A605A605A605A605A605A605A605A605A60 %5A60352859605AAFFD30FFA8352F592F592F592F592F592F592F592F592F %592F5A2E0506605A605AFD17FF845A845A605A845A605A845A605A845A60 %5A845A60602F2F845A84FD31FF7E2F5A3559355A3559355A3559355A3559 %355A3559352F05062E855A6084FD16FF846059605A6059605A6059605A60 %59605A6059605A2F06605A607EFD30FFAF2F352F592F352F592F352F592F %352F592F352F592F590606050635605A60A8FD16FF5A6060605A8460605A %8460605A8460605A8460602E6060605AFD31FF7E35355A355A355A355A35 %5A355A355A355A355A355A352F0506052F60845A85FD16FFA935605A605A %605A605A605A605A605A605A605A5A5A605A84FD30FFA95A2F592F592F59 %2F592F592F592F592F592F592F592F59060605060559606035A9FD16FF84 %5A845A605A845A605A845A605A845A605A8460605A60A9FD30FFA92F5A35 %59355A3559355A3559355A3559355A3559355A352F05280606068460605A %FD16FFA86059605A6059605A6059605A6059605A6059605A605AFD31FF59 %352F592F352F592F352F592F352F592F352F592F352F592E06050605062E %605A607EFD16FF846060605A8460605A8460605A8460605A8460605AFD32 %FF5A355A355A355A355A355A355A355A355A355A355A355A592F05280606 %052E60845A60AFFD16FF5A605A605A605A605A605A605A605A605A605A84 %FD32FF2F352F592F592F592F592F592F592F592F592F592F592F5A2E0605 %060506055960603584FD17FF5A605A605A845A605A845A605A845A605A84 %FD32FF84593559355A3559355A3559355A3559355A3559355A3559353505 %06052806062E8460605AFD17FF8435605A6059605A6059605A6059605A60 %84FD32FF840D592F352F592F352F592F352F592F352F592F352F592F592E %0605060506050659605A6084FD16FFAF8460605A8460605A8460605A8460 %6084FD33FF5A36355A355A355A355A355A355A355A355A355A355A355A35 %590606052E0606055A60605A85FD17FF5A605A605A605A605A605A605A60 %5AAFFD33FF5A2F592F592F592F592F592F592F592F592F592F592F592F59 %2F060506050605062E845A605AFD17FFA95A845A605A845A605A845A605A %84FD34FF5959355A3559355A3559355A3559355A3559355A3559355A3559 %062806060528052F5A845A60AFFD16FF846059605A6059605A6059605A60 %7EFD33FFA8592F352F592F352F592F352F592F352F592F352F592F352F59 %2F06050605060506066059605AFD17FFAF5A8460605A8460605A8460605A %60A9FD33FF3559355A355A355A355A355A355A355A355A355A3559355A35 %5A062805280528052E5A846084AFFD16FF84605A605A605A605A605A605A %603584FD32FFA8592F592F592F592F592F592F592F592F592F352F593559 %355A59352E2F282E050606605A605AFD17FFAF5A605A845A605A845A605A %8460602FFD32FFA92F5A3559355A3559355A3559355A3559355A5A605A84 %60605A84608460845A602F595A605A84FD17FF5A605A6059605A6059605A %6059605A3559FD31FF84352F592F352F592F352F592F352F5A596059605A %6059605A6059605A6059605A605A605A607EFD16FFAF8460605A8460605A %8460605A8460845935A8FD30FFA8355A355A355A355A355A355A59846084 %5A8460605A8460605A8460605A8460605A8460605A84A8FD15FFA959605A %605A605A605A605A605A605A5A2F5AFD30FF84352F592F592F592F352F5A %5A605A605A605A605A605A605A605A605A605A605A605A605A60596060AF %FD13FF84605A845A605A845A605A845A605A84605A2F84FD2FFFA8355935 %5A35592F5A59605A845A605A845A605A845A605A845A605A845A605A845A %605A845A605A605AAFFD11FFA8845A6059605A6059605A6059605A605960 %35352FAFFD2EFF7D352F352F592F5935605A6059605A6059605A6059605A %6059605A6059605A6059605A6059605A6059603584FD11FF60605A846060 %5A8460605A8460605A846060353659FD2EFFA8355A355A355A5A8460605A %8460605A8460605A8460605A8460605A8460605A8460605A8460605A8460 %605A85FD0FFF84605A605A605A605A605A605A605A605A605A592F3584FD %2DFF7E352F352F5A5A605A605A605A605A605A605A605A605A605A605A60 %5A605A605A605A605A605A605A605A603584FD0EFF845A845A605A845A60 %5A845A605A845A605A8459592F5AA9FD2CFF842F5A35605A845A605A845A %605A845A605A845A605A845A605A845A605A845A605A845A605A845A605A %845A605AAFFD0DFF5A6059605A6059605A6059605A6059605A6059602F35 %2F5AFD09FFA984845A845AA9FD1CFF7E352F5A5A6059605A6059605A6059 %605A6059605A6059605A6059605A6059605A6059605A6059605A6059605A %6035AFFD0BFFA9605A8460605A8460605A8460605A8460605A84605A355A %3584FD06FFAF845A605A605AAFFD1DFF842F6060605A8460605A8460605A %8460605A8460605A8460605A8460605A8460605A8460605A8460605A8460 %605A6060FD0BFF855A605A605A605A605A605A605A605A605A605A603535 %2F592FA8FD04FFA8605A605A605A84FD1EFF7E355A605A605A605A605A60 %5A605A605A605A605A605A605A605A605A605A605A605A605A605A605A60 %5A605A605A6084FD0AFF60605A605A845A605A845A605A845A605A845A60 %5A603559355A35A9FFFFAF605A845A605A6060FD1EFFA95A605A845A605A %845A605A845A605A845A605A845A605A845A605A845A605A845A605A845A %605A845A605A845A605A60AFFD08FFA96059605A6059605A6059605A6059 %605A6059605A6035592F352F352FA9FF84356059605A60596084FD1DFF5A %605A6059605A6059605A6059605A6059605A6059605A6059605A6059605A %6059605A6059605A6059605A6059605A603584FD08FFAF5A8460605A8460 %605A8460605A8460605A8460605A60355A355A353559FF84605A8460605A %845A84FD1CFF846060605A8460605A8460605A8460605A8460605A846060 %5A8460605A8460605A8460605A8460605A8460605A846084608560FD08FF %A8605A605A605A605A605A605A605A605A605A605A6059592F592F592F35 %2F605A605A605A605A605AA9FD1AFFA8605A605A605A605A605A605A605A %605A605A605A605A605A605A605A605A605A605A605A605A605A605A605A %605A6059352E3559FD07FFAF5A605A845A605A845A605A845A605A845A60 %5A846060355A3559355A3559356060605A845A605A6084FD1AFF845A605A %845A605A845A605A845A605A845A605A845A605A845A605A845A605A845A %605A845A605A845A605A845A60602F050605287DFD06FF84605A6059605A %6059605A6059605A6059605A60596059352F592F352F592F352F605A6059 %605A605960A8FD18FFA935605A6059605A6059605A6059605A6059605A60 %5A605A6059605A6059605A6059605A6059605A6059605A6059605A602E06 %05060052FD06FFAF5A605A8460605A8460605A8460605A8460605A846060 %355A355A355A355A355A59605A8460605A8460FD19FFFD04605A8460605A %8460605A846084608459592F593560608560605A8460605A8460605A8460 %605A8460605A8460605A602828052828FD06FF84605A605A605A605A605A %605A605A605A605A605A6059352F592F592F592F592F5935605A605A605A %60A9FD17FFA8605A605A605A605A605A605A605A845A2F06060506050605 %2E2F605A605A605A605A605A605A605A605A605A605A605A605A602F2F2E %5AFD06FFAF5A845A605A845A605A845A605A845A605A845A605A5A355935 %5A3559355A3559355A5A605A845A6084FD18FF855A605A845A605A845A60 %5A8460842F2E05060528052805280506066060605A845A605A845A605A84 %5A605A845A605A845A605A8460605AFD06FFA86059605A6059605A605960 %5A6059605A6059605A602F592F352F592F352F592F352F595A6059605AFD %19FF59605A6059605A6059605A6059602F06000605282852282E05060505 %055A5A6059605A6059605A6059605A6059605A6059605A6059605A6084FD %06FF5A8460605A6084845A8460605A8460605A8460845A5A355A355A355A %355A355A355A35605A6084FD19FFA86060605A8460605A8460605A853528 %05282EA8FD05FFA8532805280660608460605A8460605A8460605A846060 %5A8460605A8460605AAFFD06FF8459605A6059A95A605A605A605A605A60 %5A605A5A2F592F592F592F592F592F592F593584A8FD1AFF8435605A605A %605A605A605A603506050653FD07FFCFFFA828050606605A605A605A605A %605A605A605A605A605A605A605A605A605AFD06FF84605A845A6084855A %605A845A605A845A605A845959355A3559355A3559355A35593559A8FD1B %FF84605A845A605A845A605A84602F05287DFD05FFA82E7DFFCFA8532E05 %282F845A845A605A845A605A845A605A845A605A845A605A845A84FD06FF %AF5960596059A97E605A6059605A6059605A6059592F352F592F352F592F %352F592F350D84FD1AFFA8605A6059605A6059605A605A5A05052EFD06FF %2E0052CFFF28285306002E5A6059605A6059605A6059605A6059605A6059 %605A6059605AFD06FFAF605A846060A8AF5A605A8460605A84FD04602F5A %355A355A355A355A355A355A355A59FD1BFF60605A8460605A8460605A85 %2F2806FD06FFA80528052E2828057D5228065A608460605A8460605A8460 %605A8460605A8460605A846060A9FD06FF60605A605AAF84605A605A605A %605A605A602F2E2F592F592F592F592F592F592F592F5AFD1AFFA8605A60 %5A605A605A605A605A2F0052FD06FF5306050605060506527E05062F605A %605A605A605A605A605A605A605A605A605A605A605AA9FD06FFAF5A605A %60A9AF5A845A605A845A605A84602F062F2F59355A3559355A3559355A35 %3559FD1AFFAF5A845A605A845A605A84606006287DFD06FF7E0506052806 %06057DFF28053560605A845A605A845A605A845A605A845A605A845A605A %6084FD06FFA8605A6035A9A96059605A6059605A605A5A062E062E2E352F %592F352F592F352F592F7EFD1AFF846059605A6059605A6059605A060084 %FD06FFA8280506050605067DFF05052E605A6059605A6059605A6059605A %6059605A6059605A603584FD07FF84605A60A8FF5A8460605A8460605A85 %2F2F2E2F2F592F5A355A355A355A355A35357EFD1AFFAF5A8460605A8460 %605A84606006287EFD07FF7E060528052853FFFF2E055960605A8460605A %8460605A8460605A8460845A8460605A6084FD07FFAF5A6035A9FF845960 %5A605A605A60592F062F2F5935592F592F592F592F592F592FA8FD1AFF84 %605A605A605A605A605A605A2E007EFD08FFA85328537DFFFFFF05062E84 %5A605A605A605A605A605A605A605A60355A35605A605984FD08FF845A60 %84FF84605A845A605A846059062F2F5A355A3559355A3559355A35592F5A %FD1BFFAF5A605A845A605A845A605A852F2853FD0FFFA828055A5A845A60 %5A845A605A845A6060602F2F2E7E7D7D2E5960605AFD08FF84605984FFAF %596059605A605A5A0C2E0C592F352F592F352F592F352F592F357EFD1BFF %84605A6059605A6059605A605A5A052EFD0FFF53002E5A6059605A605960 %5A605960592E052728FFCFFFCF2805605A60FD09FF84605AFFAF605A8460 %605A852F2F2E35355A355A355A355A355A355A353559FD1CFFAF5A605A84 %60605A8460605A84602F05A8FD0EFF06282F845A8460605A8460605A8559 %2E0528062E527E5352052F60845AFD09FFAF5A60A8FF5A605A605A602F2E %062E2E5935592F592F592F592F592F3559FD1DFFA8605A605A605A605A60 %5A605A60350605FD0DFF520506605A605A605A605A605A60592E05060506 %05060506000659605A60FD0AFFAF5AAFFFA95A605A8559060528062E2E5A %3559355A3559355A353559FD1FFF5A605A605A845A605A845A605A842F28 %28FD0BFF5328065A60845A605A845A605A84605A0528060605280606052E %59845A845AFD08FFA87E535A60FFA8605A602F0605060506050606593559 %2F592F350D3559FD20FF8435605A6059605A6059605A6059602E0505A8FD %08FF2E0505595A6059605A6059605A605960592E05060506050605063560 %5A605960FD07FF7D2E0528062F7DFF59592E2E0506052E06060528062F2F %352F595384A8FD21FF846060605A8460605A8460605A8460842F2E055259 %A8A8A87D530628066060605A8460605A8460605A84608460602F2E052806 %06358560605A8460FD04FFA87E2E06050605280005052800050506050600 %28050605282853537EA8FD24FFA935605A6059605A6059605A6059605A60 %352F050600060506052E2F605A605A6059605A6059605A6059605A605A60 %5A5906062F6059605A605960FD04FF7E282E282E282E28532E53537D2E2E %062E2E53537E7DA8A8FD2AFF845A8460845A8460845A8460845A84608460 %8459592E592F5A5A8560845A8460845A8460845A8460845A8460845A8460 %84068460845A84608460FD04FFA8FD43FFA8FFFFFFA8FFFFFFA8FFFFFFA8 %FFFFFFAFFD07FFA8FFFFFFA8FFFFFFA8FFFFFFA8FFFFFFA8FFFFFFA8FFFF %FFA8FFFFFFA8FFFFFF %%EndData endstream endobj 21 0 obj <>stream ׵`ךYnrrFG&FC蛺v:^愈. $/.Ytn"O>γ$FZ ϏVłq7_<}Buk7iP :@kZy[+rVqƞLlZHh ʷxE7wd4LmfNfMkPϨ"ٴF;βj[O|._H;oGt`^3x7k:߈lx-KYͿm<-mkg$jaƺdS,,y?^r֡r.Jʕ5صYba"=47p>(EZ>d#>Эc0̵CI4i e*\ Vs*PfLVsԮܼ9'M:,E}UbY%Jm- ^# 'oK^!tfͤfayoوV'v3q`uUsW/c6.gا(ʣgw8aut)IO$(R'*^EZQEzVr1]7galg}ÓWNiǖ3ҍGϝ9kyϟGb:NN C.Gִ7/M(56WbE1B;B{2{.6m?8_)nj~u(h?ש_|Ox>ϻzA9m:~ Vhg:0x樧!QE}:֊ E~,ѲLBWtqFhl~Gʰ$ \[V_%)e0KY_ ?V[8NO1Wk^g},om썍ɷxa:Z"Ifu1ֲ8!ި|#zQ!ֳfVRTv\悋Y("F3>٨on0߸wY[i[讓 ßQiVOIyq*3R݌ĵ 0{w78*Q>ꡇ}y ㎃0ƫPbB(SE }cf4]6:FP߯ƧnuϿLޡV[m}"5Qf5-\BR=iy=z;v,Æ$!Eпd&[oWΟXEX/zHߙ*غYM<Ύ{NR.D'GGd=7µ|av FOz 25:ZFf:%_<++FHgg,kx֜jL(FF%UƱ`%1w !7YeK&+U*Q*rdC(IG駴rb_Hu~sO|m:Ϋoڳ]ϚcPi%Irp|Ƚs dWh~l=f%n!*D)ۯlJhkO k 73}1b(KH`,%qԤFMsI#=>t{"qs&p>v;oD4Ź{+d3_̪Q3F+u7j}JX>zlEԋ} :,~~Gk+1`pk<jcֽ,sz ~\;@#JYr~._ҼTr 8,Qv .M󓓉7kHigPRX-4p4"yn'rBø r,5}0H!MI.o?6 fU4.6L5I1ЭF1`q lodFV!/Kg ACQK/7SFXRn雚YjG_|KђKC$Bj'7 4IC}iX@4dQ"{ӵ^hU*)\jv76wGo.Poq ?0j_b5M㤵 Ifjb@)U(J(wQ".Y=R2kzQ4G)bI˻92ٴZ&F}ou._QNPm;~ᐤ/i]F` Āj101?y>f/<;1ctJ 9刋[XdZTji{y2'mGt5_aQ =ДJf t(t&1N$[ V$ $A>W$f]BLh;\<= \F)X+XߋƟPbE ~0'|8s0 ƹήR%NrL +%ԛ凷}xx/|EoLBvNwnG%Pgwj"=Oo69i ?nH&C+sCc!OC4zZ0VS8"ν\%J(C_~7wK0A`Û 8yQ\Z9scep9{y$<%A֣ϯNl*oǩ\܊ t5?t[iC<4'~ҽO[#yDU%@~|iaףD^%žc^di=N1bKl\ӽAY{VWrBjUp%E8O\1?E5n=A '޵'vyesݍ&V?:@#$LNhM4^ jK*|fqPπM/<@s *}Ke<˕f[e<<[/rp*p{/25oȚ5W$Z]=W>6_+<&+!g=fs4s7LBN׺y0yQ0݌C|X>ǟ@ߧCn»W7@zئ//y蝗U4 [9й^9oD4gA@Nېtk?pMn[}PD+zG۵_dLjk1mzCQ@bQjm&&jXvG@Wcq܋n~2޿ .'G2]nx~6[v^Vy&Gtw.my\`7V=9=c\HV3&Rӕzy$x=ƹݺ1 ш+5 0es "x"ώ9t;lcR20,|.ЉЋNy TV}sZ ,vke8#\Ej"ezpM# TSxexܻj?vYx"qr_l\Cp)wlL5ʪH#zظ^]zkҀԲ J0`+&JHEz ))#=ԅ2籔;qu\d!jX}9?(W-'s|iy"Ske,F^fI:U|޿ʭv+IZao:CropJ"Aa 0 /lꄌ`K0/B|Œg=~V?OPjHW~CrzЗ@^dTC_]S%>/Kߏvtv9Y۠^NjkHi]x&2KVyTO^t\Y¸ nf!T|Nu֯5Y/=}m}Jˌ=p~|d$ b,aIU]-R&h_Qm!{+"VF%(U=n. ߼`u( bZMMa -l^%nbNźټDmU;w'}`$q'"usYݕy?e%me9Sk=LU''75ci8<tJ\;ILWo"ΰ.ls-k#!,kmszOێq!]}L82N0%{SJOA3&{lݨl!fCuhGjVVޏAuxj~ΆFO &v:XSY%Y2z\ckGBAn^&FT8R+mzL@ۺ:poZG5"<&v":gLʿ } 6N Eײl<,__XsrJ`ɑ]_ORO0Wm"P (u/bU*qUը{Vjuu.7$,=A]7ziET92.0@H0ѤXV;M[1zܟ>زAiӵTR2\dOmq BC_>c,K4'\ޯ_f;mKObs  ~}u\1NW&'Qa=dóNj_`N'24nYE4/hP9HM :<Ї/K L^>L9~2}̯+u^oCaa_%Tg:Bh|bTeTnS 2|qv-X$4O!3,y1e7-t"]R/o+ߩ16a"4'1ܦGk6 ڊ>7Zd<Z2ڂ̏k"IjYMs)!4j[)ȂLR6l?U$ sx'I)zQjn?X@GN}%Ż'Vł!Dq?Ң))bSƹGqPt:NL_(RwU̦$=?(4Χ񎾋[.?OE߼HFqpEHܔW{2R\$U#H)aJ8 Q|j)|Mj~v/"( POti^%TPnD󅎾FA,H9l/WpGϧK2#SNlcJjF:~`b]2LЗ W'1p)tCxx7O={,J%vTٌ ݥυyQT="1jnjK&܅W),@v] Gk zz'<E#Y^f8,WZF$p`QpL>ij1(wt<{rӊWkz63R_Ѧpgέ>A&>kU8 ӡxd_0z'KFy1$HC㙊k ]~Kě0roc oހBa7}ȫ :5Ίq>_}TࡧډzcZБvZ/b˧qZ?*tf)|)lWP7a@oU͚>k=} @y:2qIz9j2y6fE}{w.;g87TkoH4o1tqKJn:b(Z NL+2QoGyb'|VLF{u9dyr;!?;a[˵ʹ *95Ǝ)xKߖ3K=ss59{8A٧y|NӃ>,_Cs Mi֯:q>'m'd5n5kkn- yl7}:/Oqb(zɨ8}F1N6?q//qnpO}~8<g9 ݱZ>maZUv鴓}foc󩯠/{WʚMCg5V0Ҵ3>-³:0مfX,E6N1Rjĺ'ꚙ_Yt0}qS詖wZAR{)E k oIKjUvS8#֖yoAP E!Q^el2ܿD|{6{j~rYi3T2ώ=04m2^|b͘qzooɤ#";k'F[0!7_g_3)7ce)z09E8er'p:l4Wʼno Z6\D7ύٌ?&=FW8]kÏhxxFVK5J#W甽w`2/3=c:t,-]75 E(I%>ĶNHAV0eNu~0ۛ<,-CiEwb=}j/|]G2 eQ䫥r2ljVYhM~|``?/n#j1V%,qu8Zc"/n \2 Jtkip$Wl|vUϐ*` 4uʣլ2y9YޭPIEțC֬Cf—jӦZuӹnJTYgYNRu;xjr{deL~70M9>=[*Dl"xlN<+ˆ+lld /΋mϫQ8_,[mzAw_Rit,0ğ;{ %{cb2pmo""?$HUve݁ƭFb۽}.ݡkJ[#N&E]' E+m^i)"a{jeK b8NU=x`頷("4ikUnyp`B+Ow?\T[F},A2"DE$(挂v{υU5)&7ÏEbPk _ljn&OfȞE3pjl<'[DÐKpImyLdM^G% OO: K4WUn`&W5[]֦SyRMV7%v>2kT˩ݽ&A?_-Jg>j|g%)B9kЛڽ!D;"+A!t_aZp)]^8hQ6lֻ5 wLxgiZbrq] ש/<8,ekBDSwb2 ?K |j^x$VX\߁DVxI=} gxy7sSwopyKJ`uù}s+Dz[Ia2Zd%5E"boo2 d/`&78y(hhbVLvTj%Hz_q{{vf.vֆs-!7T[Ճh׺)K̾1h6JB) $]*Z+Y)6Q^)yaИF+T{rny3-0'e0%bKſOS'1@ .z[K7zT#K%mu.CT8ǥB`7F{Y5 G`vWʧ`pxLIlfuVrmO8lɊԱ0bK厬I5q%7ZͿo{N(P>}Z Z Jzy   V1dަ{@g 0WA{ {0ҍvݡfS9K88e#/@7__k'[A=*B6C0[7;Fo_ o?Ï?0n-ıJSNHaE'8jЊ]ij^N:-e]S85ߌ;g(>r*ыЯޯ҇rEc-ݥ:HbBa1N.N4'/Ɖ^5SUzƉz )V)ЈK1q҅9/UD5vy6}0KqP&$YN~Zoo7rZGDjdiRi7.&%5{8'"8ȿ8*}ҋȖ|ѣ Wct0Gˇ>.NkKn=U>2Pd7!(D.Z=A|9/xQ˯ʨyύc2An=_[nf6t;{ş{wawǿM(#>%A:7ң.+f:siqɻ9/(8oR^\h] 9t{ftlV[m܊n ] (\f]HrbֶRK|\~M1_(.}N/0k\\;WAB3{}VvVb;nnM\Oa.zn \sbzί#靁uFb'zv޿HrFˡ+J'8"՘8䬝o|)|}_zL[x7u񁄙JPlBl<^'d5TWxu7~tb/o .%b}H:ɫ 7ɿ[HGOmOT^_!8Ʌ_;. ڼ1W,Ջm{%ע#2~G&.yˢ\O9?n)îY}xՙN'6l>eb͍`,Ջf(fuNS:qmD IV3u")4yݬk25RT _:dԵF;oк]F{]U0Q=j *ʕDT۳㸣rpt<[J?znLfa97Hl#*%yS5ơ Η .x}i4\n5: _YdR^OF}Xɡ2Ȓ3}z2E’GsxuR?%Tª:(A;,ChX"MB۱%mCA]:=?htsh[}Oֻn f^P,ZATE8JBNى۟%ʟ1*BE.;$.aEKc_ʈ/Џ=⺸4\}ݷ6h̓h ܔX `TbbT^b8,)2W;()?}#8 {FQhFs# iag/IȅMŴ^zO|! ۤ dGIm:ho+V>8{,/SXwAϳM[s3z!7`Q@ 6ef+9[m r@D"aer\~9NT=cfqPM.]jSq/{@m]OA-M dPPcTP;X]~`0i/y6epf)nyNduH7҅e8ݝGuA/'umk]*Ϸ."z}P6 Lgq?]DnDy7~jBZAץ|8uHt`Z.{I.:J zrp} -?9Ezʨ ` D/ʖs@Aϊ.d$f}ȋ괊?kh4ܞ0+yMGqLc0e/fn ~cSϔ'n1Ejo*T].)_+oi[.ӢS8FosN[)W )SbXߧ,)WZ` H+12>ƾ|^5ؼJpUku?P^_Hu#sF_;)sщ횖jg_Ձ?u7M +RMll MoII鲹jj%=3_ {!wS[kg~7|!NP'e)Nk;Nz=,c{c3b{uTlvO؜hw%kfUeS+*eg 0SLm΅p>\RW#N=j h9W8W^AfV"Qrh0SN}ud,W )/Ky(9jl P{(@+[Pc}2lُP;>=0}NZxs3ھ|8ڢr}'g7_r vf:6Yᰜdá3Dq^VE-vzaVPu[S7,N}6}u322S@=5;lT}~ g`Жvo ]'d^1Zijl҃B*`M"vf˃K>/oͼ7>5 na4o΋t D̫HrH$4$weӛ=OvzkXCuj5u yTVT:=s^=ޢ.s%ea^8El1Ct[.?2~yyX }w  6y>Z7N:#تR-\َ;A>mWel9HNN"$;(Wn-Ei6cA#^vs=h gp֘*t^ X8_J6596=VeJtA!BNXohZ 9eޠ ՓQT^ -  ;yoY-nKU?3Ha:w~ Σy}ɤbm{N':*/cڼ!V)i`eUs5+N!)D.!<A'˷',-9+dxbX(&>4ˍo-qIPJ&adP?Ѥ)T?IބwG=Ko^w  S1Lܷ2Ks@0Z:Cs嵰ݡG^/nE-&*0q[ҳQ'MHy8%+_uEHr;;"yջm3ZZ;F@A A3T\h%+g6rh[.~ș9Ǒ_=[ W5|,7CN\#bkC܌8 ؑ&>.K‰!zF7t௳Ur SۍO'lw l(NR.ۡ&Ѣ%ğ/V{g^ k=C=l!hvUPe"Ї='S;A.aګ2C^~c &DLln>k G RUmÍGܼwM"0Z?k\ytWw]ْu{йws}>x(g9AC>8ũEϩ;so}pG2~~xE7⤌k~.U#Ծ-{ O} -u: T YDJ g;ɚKߞo`?x;S|u/[_ν4wPw u t iw ʇYom d37=j룊]ŝ,ٙxRRb@AɺCea@8 :}Mz%u# kN .! #}ϢJ0n)þ#oݾC6 ۆʾ3Ës,6UR >+ Ce #g O ^ @s6 Ra@MU4нC QNjK+&E+uP@qoFm(3"fG]Cu29"Wߦ?_\ |Pܤ?wJ90V9?p1ͅ>>>|M|ަ>o95ejƌgŔ$n!l{+O8U$K˞һOq/l8XPH |Wowk]0z.@d4Jy./_ ooY?4z81I^NYqL)#N1e_/RSb%8 NlWc׿s]ꤽEEBBIߣ8]6eUVܔ%ŧf׀~PKZuz}3yzm}18I'Z>w{yJlأӿ?;Ո?&ƟGJ:QNF]$n/-@v7d/4^E8,-O)=Y}(f~G;,n$FVz5pߜ'ĉNrVYımI.p7%{]B<V=>%/DKkClv5G+-8Oaw9zӸ}67>r])BwXX~PBLD{5XT{6 _kW^s\˨X5'ۙ}5)srmU٣n9[Ϭ@h,}Ǯ̏,GlPR$(r{dὼؽ:R@R> ~ D UNaN{$͕sW C?ȺUºhEZH*d}A;l̪+lͤܤjՌʏ" 8S\,fgY0{/.\gtV[˛2ӻ ;MZkJTQś$E:ĶD}LعLQr!~֤"ϓS?7JřLJl%rb{dTkXjm:&z@o](`[JQvÓw`pMX빳9:-(ti\yoBЇVن AՅ> K ]p';Qgܹ2E\Ssm]Py0Ϫ$2#=sMN(hV޽gQ}BPHqw,`&w5 _*/=XϠj[h)1=K6ѩ:SոtۋGn/zs{s 9`ٌQ6zs%W]PI ~c99wk ~2F] ?;wt܁e|ѲmT~ɭwV,rhCd Y:f)HNbZliopc ]aۤ`zOiFuA3Jlt_&*GW=Zx"&[ UNCk}=ZE4W6mV/! MQV}4z-%5UڵN!:X_>UW/+[xzw.Ȭ[ qgi/G-@Z)fg+T!-dŖN. Q e$,rȕZby# p bʏ@;A>o990sj|Ng-ߜ~-Yo$+% N5&tC u.d~vaVn}.Bkݙ"qyEɹnƘրj)`-eilI` / L'ԳįW$r!mB%~P8(m)9r @'~@5EJ9?F׊͞ ˳mUz)1W_]7(bMq%>u@E,]<} s6v^2l/w.+ (g ';zʖJ遒!j5s0 kLq涔b9_f4ӧ,YYpgjϧ)͔#N''Ʊޠ☬) !IGc,oqLWr)z;_5Jhuݼ*w[([!IZYuҧZg_bk)yZ[Ë uUvU3^ֱ*MTT2Ǒ⮻ "*|d_Ay,Nf -q,Jӈ?G{vnwFzc>;}T81r@a\p}۟#;$w1䷃u|cj e;rKMӾ+e"hN5.(][w'OM;cbiV}51|[믍6Ą*W}$uvn {Kt7ht;W0pyߙiGy?̘*2.KI)uȼBm{0!PZ.-^o>^,3//nL6PX:yB9>yga1CPݎy?eMq*Y~tr|wq]V*:Ws4m>imɞ{1C8*8DхF"NhgTzCIKߣ>o-*<<\ &b%CVZK ESDZ2OV=\-<›|OGv-*=UyTtaN۞ΰ1zÜt^[J:r96Z1<Bȏ>o]{f ]=,`[~F鎰Ms(Tf_~|ù` OyLI7ԾuX+yJ̀Զ=4G_6+H:֦;۰}9zH`Pۚw: 9;t(i|X}s%L3?4Ȫ Bi;Qv0=tʹa6Y9<~hVN:_5 Zd:bT\rk&jboJo)^ z3jq pcϿ)Wx9ƥy%td;ϲe pauST@ku,ej-[hloKO_G86_Zw4C)695k~^ 5{LmIάzi~[o)o3}t`^aPN{g2Px1x43^;gx!v%h]1l (D'^3G=O'';}rŒpI*Nbߨԅ}LٝZwr r.̥m>H9j9阚(u -JZ5eB^!\ޗr=$r7'};gH~Ymj^Y&a4 pa9@~;Fbg =U>Vzv)`gnp>ݱRW CEAhv7zU8g11;VC).s5nfϘvOۮ+Xarya B-i@Ubߪ_f,ivjXZ#']Exbzeez$A7~@nwANAiSK*d(֚nxپ.7D}ɠDgc[2J;&̓K^&Otupbefwഎj 6|_U7TwziL kr.nVC'iUιg! W*/d{C4X#8*N쐢Rx~"zl#6QR5 &f(PG C1o+-_/=usv+V/I)b 8 d?8tUh./ky81F!yR%QԌ*82@PC4p-9libI w 8<-Ln{_ }[J)N<xRHDl$):zoݍF[mnuꃪ_=9?_t]7zŕ 54*u{v ^Ltz`TZG@*M>ݩ6~?ױi?.lszݡ@TW^o~بYC5 {!iͥu8 F`cKYhOruŮny Q o\>0;B"i!yQshRjBSis%``GSS}k  ;/}P^x,WU^pV) 9<EL[ɀ "l+FDX'_I/P:<t~g*ݵbf T\q̣';H)#^;Q^EMᦍOLD*s.9?[oMX՗#gWX(J\ڏcл؁u%-gVכr9\ pU&% >5:KwgrΏ Lo~HޱH.~SO[iҍR&z/dϠ\>q=[ğ כ\_\GIͿ?H$V=6wx|o_H{|vNZ!lcKʖQH>ɧ5&UNȇ;OuL7ػ:9t|a7u Nr>v޳ˡ=:Jf9iiw-{^?2ҫK  63 Zn1CliTf?;M]&pi#,=5 Q|_N7S*lξIp#\6'u~Vjr1 v[_Z9ԫfzʜ,>|.3r1AKz'zjV ?$I>@4933~l,7\kMژ9)Ǒ?s^90tZvql`c >8§Ěx'[Ӏ8ne?^[``0vhٍ;#Ꜽ|QL7# Uv!ͅLj#3%oB{l(-/\|͠Bf{ȃTi7&ܫ_Fҿmej\,GgC̄W06ӈhc_.pܡ!<1K "@GlTa[qg ʽR7.Y˹ƨ7 ;dL~9)1z͟pjx&2 z gZ\`? \1a6OvT@1Fa0әEӗO9W.{ZȠVLYe:p%pvwρV4m ?q$3Vpcm`7 ~Ob=d#}t)r6c;y%rGP{mI9rJT0K j*SMn6{4wyAq2;o_}q{zzxrn<1 vvݽmĭ弓tכz|kj9}@Եf׍cDjJF>Ʒ߃?HvQsm=C~_zmC/m <}ըGJGn[KV}}dzB͘fW~`t@h{u^(eJ=[*%1~%@U'`Ra_T1zיvLbkړЙƁd?\[L{Q0V3h]04)+1ڪCvRV|U{jN,7.5 Pj(D5/ab9wOr?e:*nVc UkGg/+3T _&6yn 71t/ 4#~? ٿṆU=m0buWxt AU0vT4 3뗫Nτόn T<~6mih]QpZ*aᩤ`apEXȑ9:sw;<,X:yΩS&U:ҒxsܟCV? L77 L)>ۦr$,=Ѿ"( }%\&ldjL 7(y޼G{&)ɿ-sO"A ubKpz=pI%®|h;릻yW~ٟ|ziMx7hk%8iͿZ_xOӏ?{n _3{u?x.`9owğNnVYF9%hAӀL[ ))? L||Zxk5 G8XWѹ_y4$׼Eb}Zc%2J m ~x; ),MF(اb~\zqXZ$=*۸Pȫ9h44{92Y˗u+?sYlɌMMw(S9O+*4B<)H>y{-Drsyyd>jf[_U_OTgqj ~.XAT'f.gd:ݘ66=q_'8=RcKJ'^uP={.Mo4jVܾC"krʱpX3he`͎='a,&HRƠNn^wWooqd*묿<Å|=ۀ ->o5 t>bh50wiz/[C̫NKOW$f. xsD ӽqzΫq:|g[q}K}VQ ־k#+禐 U\UJF~Tp215!T:& bLOѓ=:ŕt\ &آˁjfKEѾҎ^~Q[A1vMj8'.)XhxoK 4%a&_Ii6:  P"աxv{es`?f/$d'Vvuh<ԛ9w(70Us);:eR ġG\>rEn&l6C6ە+lfjlg^e%O-U1?bXf<%]ѻbOok٧j/FkaX_J G)e*!7'Fūⲍ#:qlk6=R!H A:q2qi)7+P2@!`NV&H7 =RvD(=eiȽTu|M[4zp>|<i:PV^'74▧gA6#IlE nes`H؀@[zeP9-QT9!DT'cyvݫ|PO}j}Fq}43 >Q6Oz5O >d{m̓r9=qx1lpOGӎOmdρS;hP-o6vףZ,6X&\AK|QjXHaKq]OĽ-Cnq&]Sd3x/]▀SFOۥD.\n{|Zc[{hUL05Ah-I>pLO6}[*rqn@H[s(~1wV4WB^Ѩ/'1+W{@\Nvɗf5l+(: n+| ~Wu侩d-;,c>_8bP8 M{䫜f.W' (7@bg(/S,* ?PR?($GB` m:Kny95Ƿ>Zl97L …mDUCǧPoA[^62gJ J):) vS9ŧ `{MqA~He? j|`Cky'F(Jv6G+m; ?2Z;V Z53변w3"@*B5EN1%&5`&&@<fHc-j@[  %+F?OWJ")5n?1n5r! D& ח:@|?<la4@Zm nE{Tv+c{)"y\'ã7@!@HTue)1 Dd J]tmlbY&Ԉ) PCE9!Bhh)Szo AhK#U!*t qGyl O#FKT#؂piĐ]I/l#*tGv Т _Wv.7nwwg}{bϽ&׃"U R.)U^RИ ub9?'<_;U w G|9DD& VcY{]#nPakwd*HЩ)+2lw3Di>">,T]%XOB.w EQg;I,^SN@/iϒ! qe`Xw[Y^ܒjtarΛ#,9\rҟ

j֠ݭ]DwԱFo]6lj"\b9Z(lT Z7B_,~&wdJD˖L:T/tܳv@PgwӾm܉[7{kKhC [f&c9u_g|I6%ml⯁R{wxٯv=|ۅx'ʕU@2g_ũVo1`/K9r0E8/Yݍa{b06?CsatOP[{{=/Pis4Ǘƫ*X'"ߪB܁š`n&“RP%M`ʖlFMF^7B"gXfaFѦ6b ܼg%AyfyͲoU7+7rux=&|>x˽Ed#m՘y?hRZh3U>z#Dk)V-HӰBN ==n}db}f}'~X89|wObvE6czM*_^@m+-yQ4ujb64L R{b/ʐ٭#@LФm3xE8Iub/K lO0#[dö:LdrU'οuZ[$0 ]k+d:Pn$3TzX MSӘdikBqR0qmeQD[amDUAgES?l([Fa1[iR|繊ÂO'5ZxO׸ _[@X%Jz!ARHTUth7U8m[ݏP^!~Pb=6K\&et~a4*LbO/yL} QgMLO';WHO)Ʒ,7$BͥDd5)DjzV|;BEL~_\s܉^~uFVeanKO|7GzKumvfL>;uG[Ul <}ۉ"ȹ5`>-ŒV{&3n\Z4c cn]V3 gaLnӜ輨w#D7W7ayk;0 ]ҷi-cHB;o/wJJ Zq^z2D%ƹ4[ =tMو&$id^zQ(`~n YJzm R|RTJql]^|)!rkgɼC3t 3?n^ bF! 0=!gzl`@$\3Y>GoDs;SlDwr5,uh^l<>/z4~vDZ4 DȯB.( ~yPjzY5Ny1l1x^֡fqrewRy kî0Iu 1^1fo9S9gKz$sX W`(49ޡ-zXOGRo-QsdT+{ T#T" jY1b;h╿$C0Ʌ cǭj4n+nfyƴ\dfvDNxgpHj,aA.+xMv*DWp561fӁSAGӆ;lc׀2 ! *y $̆ham_ xfH}F!Up{Q>#c'$=Ơ8f1N,`?ٗ9xv;Ah(!SY- 5a.oRnlq%4(9{w#ӛV*U7w5q;x"/a8&'?/5cF_1^i:Gfczxv)oecԯMi~Wb&Jˑiʢ[~S3"-#ce1C@J0 *  Daot3 vK5Dց< #'ED{Kz&?O3/r>nd_` 9ELO.D~Nx?/SW?U  lHF dhdN,N EݱC#D ?%g{=M(=SڏmcX7k; Zgw*Ha:Rt"ɾ?vQ io?9%=J2u/Iw q5g Ԟ՗ @P Vł2fWg"|C c(L%ul nȽ7wį|W}%@q c>^z@s88r`h| ~Co5$dJ$՟$6q"Mbgػ]c|z[un;vg7z98J_o,|/Z$ $1IDj}7pgǧT&Ciܭ]R4f}կkq־:ד)х ^?rN_9);h{(A6M4Կn&}?^?!nV=vr6-7O(={Ў<݊x5܉ǀ)O;Ǩg5IDٮ $ f}oH#G]yt'ᛂ07_HRNK5t|ڛS !ן;:jHk~!F+[M,,&#Ρ~OY.Qͩ״dW f& *GM1w/jY.G}9xu욟ųP83 ߓbЛV s*40v5nSa5H:נ/Ms8oyx@/O>|]{8w޽çI/[1[k{j+h}fꦕGfXf&[1^9H߭ :K4[;o8<^.WPq҈N(rllυ("ou^6H$#]+μ u;0:=Ϥޣh"(S7naZrx56MTc p.Pw)8]_%x/s "垛N1qz 6I x}I80xDO6~oaƊJ .-) kb.Rh>f>yLVۆi~<3_;l-]}zz[ܦuc;fojۺ_Ǎ!*OJM n+kXl 'x)70=yYT{UJؗhzE#E}džzfoes~*kZMQiUU]=_|[vxaO~AkW_h 07;8o2] ;kP#F:$Re(qj.+wf9U+͛~V8%3+wGU\^ 3,^?vG|8Ĭ+X߅_pUPN?D bo4B0ݯrV+>AW[KΨu@*rSZ++eWEXjG"L=yi}Q&>b9IogkoȠV@93l/YaJs9Fe r7A՚=srǻf洐U&=~IDO@8fȷh>CVJQH(Rt:IZ&'`$\wƯ}\L/:#ۣT|bz]윌IMԝ JˑN/ei,>,Gҳ=uR~as`qU<,?i"ׅy񅢞_ g2qe>֯C[2k{ǹ`|wwפaOʤ!x,U@.rn9u"|BE~Z n: v?Q̋CGC%dع/ީ_w]nCszn^8|e7wdmͲ;MbdWgPSK0zַ?t7r13i2WW}j^5K3)ӻjNv!g_2@/0#s}%3=C69 jDTc~fjeNɔq̈/wCKeAw)!җQ_1%ȡ$!XY 8nW;LP< zT7+26 lʊ_Fw q$ÈeS;H#LK#a]}H d>#yĒ[I@i[T o&o-]8,5G3L4(wEA Ol.=\]3ׁ=cI4$#GQ4NJªSE|~Vq{d<2i|e ʄ埐yt)wh?Gx,sR(qzDZ"_9ft޽ݥO#oB~+c(: PSD50:0o^2kQO/12]WP汴3`FG".a&+\Ҿ禳IّJumavnn 96`.S+{D{+Lq 6FT+ 5 H]h=CU M5MYēIU5ƦpVeKy&{«{^~Ya?U>k}@h#7ɥbt)@`-F{Pmlc~T&{ Lɻ,,~r ZlH`8ڹ|M\TlG5;G {) *5l!!gC@9#b1N(/#+vzWzOml@ hDҕs-A͈FDd~20Zy.@fNO6#4/!zJgR5]uXc,.rkA*gb1?\W!ʺꤋj9^lNդDb;`2O핖tzxd gnΟI3혂?%&|Bu+@Tl \^n=FHMd_@82V(# ǔ\*%Ώg&wBBQNa{ϿDM .P[&bfr/6;Av F WYejuer ddtD:eKɗKM^,6\-8U }ﰣhKy\IquӅD}w?roM3_kr ~R?jPxnP+PԌ*Zˢ@ő|! jܳ}nݻXHCqt}8zeM|#:&4ߟ$h\ ~#t<zqzs@Ї$twϿ$rBޤtXMB%8g6~|`T/w|HkGa=":Ow5$H\»id*O*W1šjj"K$ڛT9Kg]ޏq~@~o`S sSu-+#N+&Ѩt#~pqIو1`@i7ombM${ )DMNN~| *C;RüǗ]GG ۞#:n{<)>|38~8.y|2MΔmj":\I{5v:wz"&1f/Сvu}֪:'Z+vWQ_x;;jlvF>loVåO9[;fptNĘ*6{H x4%NWOh0wrcyEhܼpzB9eΣɮD&̊vmnI'y04xj@8yD6:ZftoZCԺ_WG}qnҤB[3]pX&Fv;3kpf`)8GBJJ+#m0wl}O!#ZdY=D9jH =Z 46Ȓ<]8+\/ [GYAkN:M{jBBFl[-fH6h`ٮ^teh ~φr \odiF/y%VX_Lz޺vmUcUHjUr;ghp KAY5ƍ.ԫX۹{ޡj[I'e' Ju+jf{*N۔*aR7/W}~2)wY,Jifkg.4=h`W'+ZyZuOO5+qګYgMTM[5 LګշZ~_/sJDv<훙:SΦzs1ʽNWӑ(sO Oɞ4ÆOL4sr MYbr"FV}~ +q)4{t\ya'fNf>ʦن5a9iŞ_FJ׭*AT .UU;Vw:XΕå]`w+(Lƪ=pҢW8yzCUf[A ons:zO&?7ԥөѭZ閯ɃIiwXX<rv A݇- K6oqs]ӡ.>͞L~ 0ҥsze"F3ҧLU垶 3;1 ZEIE%WW%/CM6l9jSzݮl:_]+pҒM,奡3mn ݽȀ6^)9QlQTדR%ew8F`| `YًZodb:"pLiX{lk`oZC7m[:4u;9@?:͟}===M}xÙ&Ht f;C)jUZ.PMҚNa= O%WϬ{-uӴ\:;})&),e13e/mVAVXt\Ҋu^|g8<1שtŔZ })/ύh7@HPv"]`F;I޿ D^lT[OGKպjmosِe'2"3ߖ}GH"ӷja*`EHo%fm}un;n5oH}Vi#ld4PͻrMF8Ju2Y w+ݾ6}ZV~D~S `PHG?".wK7R&8 iXyv ',;]Z~ ff wh {Iw67qV{}GǍF)́,8Tdky{\gnpu93ΑݎqtˌX]pLF kt4x i잨6P~oS~CA",mRC>h[LSnj *9Me6Ϊ! p8vY-qm Ott{>iϦlPwtR~$9+45|\RX&$Hc1z@9m'PJXK@˜rIQWee}Z苸i]lHM{Q]RL@N}AI%&c(pzuVk;rq43}~^-yÚ:^vKeʚ滇d׺)Jĩ9qCBwݮMiJL:9 +d ͈ɖ^g/KG+œFԏmt: NPz43- E ]?3 \q.Geͭ'\v-ϑcud.|oq>n5`yQt-N:%UlVsF|^Q.3Äɴ#~R LW_G"B,7!RŐN .QgBȇf=Ի]{ߦU GHԔU16Dm\~~U:_h\!V%s`ڧ{|2ZN;Ƽc c< *^dTL9@t}au]3ޏ[HA{?sx@W B]Ģ |Q:gQ}\@6%C bT&1##F?(ԋ4]-:12({T>j V #F'3'RQi$fmLo=ڧg amcrKp/cħ1`/0 P ◌ `ӏ81*[+`ԩMk%$f}Zׂ \nl+0 UYyU!p_',6ѷ?G W3F9 sZyUmp*~]BNpX?~q3޲WdSˠ¯`B1^R_^u&W2Τ[ xֺغ={ Y r.C 6 j; biocBj`=s=(ou2@M /7y$X E-G~Hb@ @\t >7E BHH% @rF$-A6jn/bdVF[1k.[Jt"i+<#b"&ȭ@_7@AF(lAFՀbCO(w(f ϗ{i-|vɩ7\#3 peQ/'i+7k#]?$ߟh1 6@;=Q:x) f ?!ILoxC}S:O(BRdiجcjaݟ\kpwۛ}~^ngW`Թ4n5$ oLR+Q)=2ILob@NӧjۇEwk=nQ\ׂ]d0z]:q8GQ,ͦGy \r<[5'QIÏ-97^i|/ v\alۅ~ YggŔMD%T_WQ_=f/uƱz'ųѨ-S5UÅCl⭧tpc¬_qؤtֵ&C'A` `IWR- SCu;-o|Е܌ ̺^!6RRS22FF!maFQG#[׆ʅnW]]zg~.28Uޖ.sn =~_%HwD>2-xYEW@Mꭅ +Mv(6G%> *9Gxc ݫոLAkwl8*J'^s\_Vѥ6`vHނ֞ kR,V_"20Cw' X|uK˰+mJk7J׽+ʸ YҲ5.HV>mmߛȺe*Q:OȚ걿UOxMlzXE9[zo7s3f|WwW}<0L7FfMhŊD\LԬ^+cV۵V^-x*YUnWd'Y;Ov)lRQR%1/(-#M)ڟ #GKm ל*n|nRܮz:\k 𮶥DsWDW\ė([g,?%ڒR:E إR$\h?NJ]v Eb-ea.oߜrݣm%'֔aZkA7rP0Vw6kR1[}37UĹ~ZgEr-|LySl]h<݋M9/50߲_)1#~;wOvnӧt3PnNNޙTzѳ S\%4jCzfn͟s^d67rM9J)io\3R ݗ͑\+-vW qrU*18phr4+?Q?v+=wŭ%p ͥbpW*/תCt-n5s{iQ煑j^OG|hlhC7T"JzV+ -)xĠa]ْva_nɎ^*]F&wa4#W)g (J4Hi/^AT [ llwgዟ1-UhSiI;biJ:[R F9SJ'Գ3n~[3 .wߩB:܇F::?4Nl~viC͉`4, hRp̾g[v9W1{+!(*U;#,s>8-CюZ};y`>h ;Q}JwXŞO/mD:J{4c'[kjfWg;QQ3+8B,Zbit2elf4_~jiTOcBAT$=oM>n''( [n:)3`ԹU)DmD[2RhB2VT1r]Z!-%uG3f%zX$>'FޞJLѷ85YP"%&F/=E{] &Cogf[ Z-aӫ^K7HXw_cQzђ=5v)z,ȧv{%F&ɄC*1+mxLa841ϰraδ=U])݊eקՂ|8)"uW*sgI5oYĸ9rOBψg:L[Jz +ߜ)(|3{Gz_tѢEѸ]PFi_ IXmE3q#A;lelF$[g3B4ҏ`ߝș{1V!">}U t/sJV8 xFփk+PAs;8M %u*}OZR.o*ߥ"cSzz6 0 })}xJbb =xL`|BAfA H9凔5lHm'i00; V170?o}57@%bTiִo2J̯2+4VM2X+/5zYgIe],Hp.0ppB,ŸJ#SU iY`}ĞwkF:>_;֤8wR_xJX=I8ww77HPxeif4]Jw(Bye|.X'%bX- ce@d& #~9~}]+c2-.Mj*( jsa{զ 7I?;a?1zQD䪰N`i?4rGv'(pR1&@Jcb2z.I/RDBQg[;kJ20]9ZoQԷ>"Y&CO>jfRp^Դ^1muc\]ZCbl@broʤʂ!lP:h/eQ{&{jϖ%y^oȠ,`1F`ۯyAs b̦1s@&Qn1#1q*&bƀ宀,wE?s;ƣ^Zȟy~;z7"Iyo(Ra'pFp&x;]c_cxS )Qv YVks@lpvG: 5`*G|gqIJD2,CFxwbNQb̶W) M|~.:16#L[ L|8|Q?VȽ5YF{cR >ӤA?J"29 Z=y}z|g?/~'#o ݷ17i &]0yjE꠼`ϘR o3ذΞ$OhΉ7[8 vHd z~l񧘜)C NȕMY{|J\uLw}:%`~~skt̽Ш Evz߲f?.o@2h4%rA ^fw6__|o%RQ}"~44FRN~f]o#0fbul-쬳v j(?Iߺ\gW [%v' gLǧݬ>՚\ov. 3y{~%mRҧ|mIPgȘ4|>!$ obM2e䍛P2;xiK-~GYIT3nܼtY(ws3dеBuޭNəۜ4P3aV`&7(jܿz[ V vIdcɔlW?}k~Jԝzo(Ćw}3ۻlGQMo-5T"!Y ƚJC(lL[Wƍ=]ymQ?{w׶FRRfG[v\^ZVm, g&V̆j*'|z3Տ]Aq-̞^{m`<,;$ܛ/\@ gϴεToGln W%UhɛK㵈Z-}L5?sQUWQsF@EEQ99V>ɔR|y];LCX46P59ƭf,ԇpMzƥf ]ߡ~u囓{ʶ*uw,ʷ)G<c^a?}F{'ej\EŭC_HZRGFsMU wn*^asnʻ/RYڞӳg1Jc\Ȧ=oq邧w=1&#bi`ܡ/J_L`tjIrsǢܕRWltKhd;zNrl+͗N޻4eF윁Ø/܂vV菪ƼnNi`aZ_#HTO<{6Zj{ yUOսǺTxf %ce;av.3NIUX6a`;)3*Ϸ{Z|X=IsF[ϴzj%%=wG:'U/ Ҿ/w->nV|,6rFQ!]sB:׭~^lwd>(m2 ScBiaMUtk,4PNw9] IU;`WM\W4E$\>X)ɻ8Xg[@(@ A*O n[{9?9? w9:rZ_v"n \wlUR3iEw:$ (D3 "AmDtt- RTh ġ3q jxf >3j11-8$n;&^{_ qV4"P^ڏ7j-}È%)2h;9Vp*"/lFzѵgPT=  +uWER}o%ZF_z-#w!&[wAC{pj6שTghs\erwWy8@yv96J\jbi 9Q}_{t紡OIQ!P)b'G+"玘CaK2?;rw=z9{ )zƘ0\ rdHjOk!IS-\nɴH;Fh25*տ(*edT{3eO%#qb8umWpWes%qƷ2 ׫\vU,,MidTRQ:q %YPt j Z<*9. Mnm9UbPBmx]}4&[01.7 l~x= CE|zqvm}w)V٨*P!chC3I;{ݣ-oFD YITþBbdX0_]ݵoteXƶg>2׫.уsQ0sԨ#/$ #$f7ȹ_޶R{óVa%ֳf)hzYƞIpǨ{!1"qƱpGau1eagѠPI֐=np2 jU0HzC@}  H 4v6|`|acFKm?`i떙*ؼ N"im}d*#IpGnJ!-aƸ+aL>4pNJNמCYpy iQLfpJT<@Ѣ[1s0 b|Dc_}:ee-0Ai]Ç؝=' 8'cu"6s$.>l]c/A)\H!|>v1B';_XwTR7u o~Ugy5]fn~h*ϓ_h7']Q9@(kD;3, ,-9ˍ4= CTl𫷒!xfɀD@FXZyu~2l@Gu@ 2O}6Բ @r' y\8%^pX؎UnE`!΃<3n3#fƚdA*Ȑ2ZEfpjb)P:Tbt_P ([|JiGd~a/< 4hdO$1/rV{KAzNP`84 cUzׂ|2V17@(4ѡO#g y+: t-W-3sLb]즖\D>݇Q[-oCa?ހFZ7b^(tX>p> `S߬~ X%*s lb7[nճWWUJGD Ϛ|A>Em pݷܥx5A0Jt?xwc453?F4Q@o;z5GCr٩@[z;mi4 ӾYpwim\T zK_mS?O`.G@Kc-AGF1{e|6L1cqgLfؒ4Ћѝ5Љ?ӼLNoWSnYxj BsKӼͦAt)Z[>DVJTOwu! ?kxz֟AxH 4E0Li>zBdaV0iNQݷ֟+^({YoU=MGZ`sRԤz̐2&-͑09Lu U+4=~-SŰJ}}eDq8~N١j My(bsa oCD-,ƎLV(@rxJ՚I[X0N M[cΒU$-l}X}¦:Ȗ*W,VX\XſoYf6B&KrN]hB~{lU޴9ӟP?$fbI¾xuy|Qw8FzaJ@wF iLv *T{ؖZh1z2++E5k;nISOGK?j+D}&>NkT|8ŎpJplͰXeP06Ȣ{scx-v?LQ&1ǐ&fJ5k{zC!"A+@Q͆WoZW%4HӾ8" |p'X4R)?K}dN}e<uW nPK,6%؞P3nukOH>"{1 ɷ(*z/w,H J JDpLX;^POPfSC{KYw"t㏘Ǹ|z1z!W͸^8jYpK j]YK%7\e0#MN35@h<>QRV[/{> b[ 浫dg+)V)Ƴ8n?ܰ]}{r&^-1k},waS5})f5K縔A؍COF"e T !)U8ƘΥyЈc<ࢨ%:NVZyp)^.PaT1$؎ulm38S"g]WcU+9cous/q}4WQS;mjfKgS"WK$>~ 1@|  A54W6b+t5V7h9΍ֲDڍ2}i|V06 ܫS`*,PIRt ce$(ԅd@:e@qC qz~O?ߺ{?QdԷ`A2Tˤios3'|r9'D)'%=[ >_ԉ!Vm1}@gUJщCUkf>K@#n  41':NlljMA*-iMQZ|d9N T+sm6jS#ƻ-ۋQ&v}. 3r6`z& $ү tez=ZdIvq{uZN.Oz~S\v5M4Qih։~ ^p%x`x( 2؏fΪ(@6qమ طPwg**d#ŁZ6[)*vjb՚#ٯxd.W$Y|!C@(x <cRi@(x2Ⱦ ڣX\I^{!P --m_ #6~)_oMDL̞?߿`Cts5 *e ~HQSuk+ * $[9泳4|yExBp3OD4INK+[81&F([*4 + jU[IC sT0knH;d kL(@ClJ?_k꛺l/7 vH J@@o0GkuMr[~<{f&?mΥ߷ҡ_WRƝMVsSOgiBxok㨭ocP»ojO7I6(7Cɇ}B[i痮tө/:)):F(?HlT>W۹r9lVǚ/>=as9-nUJ[hbiL۳3zN'YUa'(&vj\6獨Oո,r zU[2u}Ѽ954,w3M~'L&Ӟ#?}6ږ[#uR=cxr~3 C1'%l1Zbgl|&f?RGga@v?s}o!CS{b/s_i{bv&A'jt^=6[܉&@omPd-rm&IMC0فm}zk#By߱A9H~^GT֭W޵]Bګ*TuA/0C/աE1n;ĭ۠)zb7djIYDC9^!)Vd(mZktCTjժKTikX]ִJuŗówh?5aQ!*;υ2vzK%d-~l$ML. %˜%ksTѹnjV޾Cpc xe[/1\@-S[6(Ye*zuay-Ni="ۑ 3ta^OہJyd`ylSյR]h}yUxA UUFޡq6#vzęRs"{ Z ?EClGRUsB=O#ϽA r|5w8͗ȥs1fVLSlLSB@sgff.S1>L=a4wxLVQf]+}ZqʁHXX5N~z==|iI#S꒽,Nh)grKh3Q4l5Lw2C'>/I[fcqz{f+ tPA~3q/;1-!_fI\.Ϲy0)doձ3{娖lffXt2a7&jbBn;x|.gvbi?Iav˫~c+i&PT~TTTȷS4MC% u~Mϫ  *{)^w 4Y O5`>S!3TDcR+zgz鎚jNl)+i?äR{W΋TQFmED5d*jQVhheM7w|1%ŕ[7,sj8wrm)tX!ն}ScT%f!E%EU] y酴],u<OqcH٭`Z~!(޹4LlWA'KYD8ǜ|ҝ=Zkld;F6鵶[;]+-(}Fc%\֟|dƣn t"Z=^sE(s]n<.O:^{K^Yc̉` F:_[}e:06z-[U?;j9s[fԡPkE˛,?9nMyi)؏_"?oBq6R6 ʂd=ElmjPu,\Ft;>Qƫ9h4"SṈq9ƲYjKK7]G[YD9jmȊv#DKG'NJTLZ"t[,t3SO_ZԷRZ{݉Y >`lC 'A, _I N4HoȘ#V䫩eK@ 82hQH4~:wq!MzKtQW7%seThJ PVeg=|=cCfvJGj%T`JexR7 Mw⦢5 lL˘ Pj6UzE ޏ7-E6[)+ގiMZLiBGmCzsʂG`@{g +іzA1*!@7t7ht_.xŪ( S؎B^fGbJӃ}Ulk*2`@UllU wʗG*O7MWuI!e?1JX(b[xAH,k=U24fZ"]UzC3n/i6=J1%Ӥ?iX14zzZص (y>jPʉxcr1.f'6Ik'Oख़p2x֌H grUmƕxf_!5\MaSV?B .| BQ|<\>X`@)`Z!Aܶs&/B9F3^16m4Fd <>qfz I9.zlm`V?6Z9Z&k/4O%UIN7Fo}Ǐo䟺w#Ƌ%4kN68`;#(^ى\6;v\6/p5ӯ1(zGN1<;a?[l?=?[ vo^U{vQ9Z跈=\ҩuEc+1_xxw 5@B90b .?'/x-1&M;۸@h"]UK8\bߎDiND?Iß`?tbdbcQ((uJҀ@ib8PB4~YaיcH#2gJfrcw8ѡqqGdN\KGF<҃> h : vhh~ ?$7rv3 o7²6gQy|lw߅ ^N\9)q+-ʡG='J{vhx[hUCOm7兩m%{aygo/[ym^?ΡG+N '-R Dk,{C~9Zt4H@%#N̙byAA-~C{0SP\[?L1?GrciKѮe:{5M:#(hI 5CXʼT듹NF<;k1Pvm_;M2 PPة) S2" rjk[ye[܁w@rZ0ݛ6n=S nR5,@f k~PRa/w?A u:Uen# x74Jf(G[:mhOw<{m`>uhzkLK[STw /b'W/OZ݉ endstream endobj 22 0 obj <>stream W4)9Àrn|-# ^#A[P)[LE1;TѪyqre+R{ArZU>Y9{9_*M(A{3(R~]_{SJZxyGT{πNu o햸dfeZeFN+X 6mpo uo}))wzJA4KCǗJO'x 툫JayS:X, )19߉76{۴ItW\$TDߒ, fUz;=jʑ Z :% 6s?c]X5}渒I;`7{ם% tYc 73}| \'80Qxu8z㕣LPmϫb ߑtOkdj<䂜 slTYWf'IgfcdLՇ^#Hw9zUcRbz;޴<^Q/0HfJ,J0[EW%B$d_ =#U_I Ԝ әzgd4lq7uM<jM0B ^9/D`I(=PGꅃdgyv1^q4"ګѡ8 s|`Z^\3w1t9YFȼ~PޑĸOZMZqT^DX|w8<T-fM -5$pȰ88=FpH*46(s4WyC^z"])] %e/K1B"iHfqQsGaļRc?ޫIyi=?€#9s9\koߖ 8x:КZjKV_ y16EZx-2A7;@.7=*t3t[:Xd:lӟ5{Z9&DzDm'P,.a|dNM,9A(es(!mOb$8AؚMJ7C?39C7%&3 `Ӳ`@ `U `Y ```(oQY|hwB~GCL~5Qf*Q(|7輽(ʽQ t!v F9 lvZ/A7I5F9~tFfP*͡Kc'ӊ.͇&V:LqϫM~vdfunj5%KJƫX*=O*ʑQ gV@T&4lYmң2эHzM1@7 L'D@*@  !X/D79RD~|@zܫyf= NmYnШtn$c\kT6K/m P)N.nCMgs#Ϝ*P!q\TUd2$H~>kJQbQ@a O]T^C]euiEdTXdªO*ZWɮ9T@29%%Ϙ؏5GXNW@n#6;t%jZ\r{.W:LZQ:䇀!K'bv=D]O_\jDSL A h:: h6lblZm*:Khq qZBPJxB41rufRƨTK#[BYY)Hhs|L& Nb 6t|lǷ@o[*nbB{"Ї3T@ǁޣעzk]f.B4-9.r8sGA%Ⱥ3\,KNB06Mo#}3.@ 80λ0pKW0ɢ;`B6A5$u2% 2,TX05b B7cX֓ڛP.U&Ʒ;Lmd6)^ZS}mߜ`Reot-G Ss6lof0')Za c5Hc/#!x7MH;|L[&C)[ʸ(H YGjJS)έyZj2t"{ 5ooBe`DH}b:rn\6-VVy o&յaQgqwwl93ފ0c 0Qw~蝻1uc3=qWhGygon=:RUeZ]K0Y~rXݤ5pU+RXS9,OrY .UYƹOHDU|siMёҞ&0.]:8K\>ӥd+P'J;Z 1^ƙ!hhږDrA(iEaVB47QuR Y#*N6Aٜ]d2uV7ɖ/OtCY512nsdY "9{hSنajW=h%q@9!H]^u㺟d3k(fl,/)w2cdSʴTv"PGUT=: ꑜ h(Tz0 ".W%$C< 55qmj':˖!6馫,qc\IG ebd =#khemaDdS!Dz*̯"}= xO)~|6Mi;OK^n gI;-smgb`tǝdĄ;<:vf쮪uPճ'CZUY2fצ>e/ჳOZCv<%[%xxSNui68qxmFN 5-8aG=I83moyr/ۺDi =PV]Z<ـ̦\t2:.ŌiTe񷘦jz ELaߧ86SvI=%7HY=]E_[t1vRᛵVp[ˢE~s/ (7q32xi2C[LXf]*:LCLʧ!mc3MgSN1OQ9 *?\=2t-d 1Q21:b20ŶlPIn`׳cxu)im.k $ ZF0|$UkKթ\![#izb'mфKYPR=G6, #CLѰ Pb^alRLR͔jŔ64^{.UҊFsTi\tYmOrt[M`2mMԀm?uX50 ڐ* /^SSpDz*`)CI5B( S}ReaH@6N3T9Ii:1(&80u+R]5h㩈e4،ۚ}CkD},),(鮔#P>bsc Uj'|xY"%7b8+(ie-$+56JVPJٮ=dNs&&9F5cGx5M#!Z2jhkJeZ{Dm/cA)SΔ"?$)5nM-_d#yMm&ď D]Xu];f2{W'y~)|m Lڌ*gnisPp xd|B&m8fugtKf]_'4:}!用-  J;/DZn2ʳF-!X㹁l,d*r'QHqTH)H٥H$}j$(&eLbjO"1أ%KȦ:N:2OY9۪\ϖH 6"C4]{#SҬۑ@Uy%)MF 'sEPw.@)@V#@NZf6 G|Q Wa lirXAS[}lb`fÎ33lnb..Ix|(e7FAn[RUyjYUe9 wrrG(:3fn*j RN%my8y~bB%ȓ5 IW*DY;sZƉ3B9lNvZMm1F(-A]qm"q[ (U\nfS@-$@=]^as &ȔBa]2)غ8Gf_vTkǸ_E7STBUMǢ(t+DnM27RjźѠC7!PMK#ot3 ԕȬ-^}Yݸ|g=Pi9K,n]{7u0&ec3JYԦps:ZC[$D s@jBOշfe7cGߊG RQ'RUW6Gm7'-Mt4&MАC7UC۠1,F fku(gsT㹮<X:Mc xK˅Zk;@k T=3 $eU!Q*@00NKwe\lh_,>,tSS̻PgM#0*G7&aI0(0D&+,ĻRͨ"Pi&X*m.{ -PfW[MޞV"n ZCJ@h1 *̌!q1Rla ]btӪjZyf>O>WY62~BoJKl^״U kK& ᦘŃ 5 S69jYtӛUɂ TJP齧rRwMXl9Xͩ"֧t'Z6#xʇp%xzysSʎI1qu iY(Д#b&=sML1Dh@4^h5hG^߮(yhuC|5.)f8MSY4mW<sLNKB H&0nk{K7-D7 -k$N@L] !ަͦaT T67?.k: &X:~oKy`븱|7Y`>;BOBl0Yii,X7pVjٶ3|Ywwxζ@mT8Pjne {h y֬k\͞c\M[[~N3VzL6iuҤ+S3gFx)P`J&ٝ t6P䝍6o@4VƩâ6~H_5ֽ;I]64'Bˌݧ#xidx.`ER{q4NBBeɂӈ|ahT 22 CRxWUF7˥X)򀴌bez;H ֪}#N|yDhnN A Q,- RHXjC֮O[rҚF359y^> %X,[bi}+XMjKLӛwZ5bޭDTiv,Rm|&LdY89 j![-zeNҫvmlԅ^JMI^MͥCmz9bE9:@B5\3K k^5e VzY=gJ`a˥֒4sutrm0}< ٗ6΍zx04#i2B4#J {^.{%4Ԇ?2d#G?2d#G?2dd݅BFdRtL#G^c R3K& Ϟ/) x~IL 0Kͮ8h kid#o"%$z`3c6v3:k"?x3'lGԓU:haj L+wu5G?2dWJ0VVz"jOC6>sԪ=l*k[}:+h }F\- A$ HGqiT ՃI17Y]}ddkv[)1K7C-L[8`bצ_Nw_r a@_R|u[j[sVȁᣕVK$O᪯U}ciE}4ݤyko /EJݓ}7'ShU>7 ٤G1){}%O]l7H]Hϲ^Z5P-ע#GT@fQl3 / V 剭%b0s)b]fiCKmL"-QڅE1|X"Dd| P;xX Q廃o@">r(r"6-6f80aJٰl EUP; %;tȼi\mv';VQ%bČCf9tЪTDFK5!= *U5$`}b3HmhVUБ )mhq)-fe;:ExUno?2V2YP:f#>׋&'9TDԋN}tGkȑ1,'>2yCA#&}ӾXQ]oSL' ?ˌByeftP3ffEey/ro߬FyYs*w}lT䭟I04 bC(?Ɍ>I*G'82[{>V:q䞛7S{rџ>>>2::4\Mc`'_fx)yVD̰@2{u"$`=\ DԴ{%2j`TePGӚm}}-6&Uz|]%1#- 82A'0Rٽ-p V sjQ^0qX( ^E@GnLJ[D{fGìr&RQv"ZPC CQ2= ::E}0Gg2TF1fj2W#YpO,deڜYȰ9ѦG?ߏӄјdGȨsgE ,p=υYIKBm~ޫ| jDpzf%-r3 LZ;VS#A/ YcJ]@~?䃼p .ScOj}tX*7uR>v55G |_|0_5yXABd;GH$*ap0?tvOGm\ Ibb#Ld&P̈ttA7 T٧l-(bMHMfs]қ8FHh%j1:˃ܾ|9Cg%7(SmiΗG BDdad W8<ƁqLsR*pa;KUkn*J/AAg|լ="l` CZ[[M,jQSjkR*";*Ŏ"= S$qEʬnV)#wV=UI}_=呧%ƕ 7e,M%\5YŪ' (D5-ZIE,TtW*V\3:~4 "q|r(5DZ 2mZ@MA[-GfvO f 8erW i 5=;vq\b:fD IyafR _$ʖf.`fFSB2Ta @+YJ_Q*%ZPmKUZ=$W-r@ ]Y"σF(:|hv ^֋-UK+ 6*Ym O1Old`SvjoCd1Aw%GzFb ݃=Tuz$pᛙM6f oyCQ FH ד\ (-O͒Q_~=>k&ƊL K8SDҼudPF:&.~BpRQE+PB|tsw*2~PI,V,r{E-lV VUqVB%/u s8rE?J֢a_)`*^8k.~'Vl.B [U}hd~N1+leV~Ճ &]\63 SBw敷y?.^`!H&n6#/"Jȳ6"'+N<oX1tں5vӤI=cz88:9 QȣZ­1CЊe'.l"Ɇ1'K?Kj(erTm$6C=OhZZd=uYEI`g7/ 2وfzQnV}c3$市ա'܍L6;yZ2}zދցexirʼ+:kI&`},320u(|0v+yCmȽyw018 wL^'8)bP }`— A7 QN .5zrX:Ci^nޖᩰƽ 39N2K=[ ^`s;{fq~]8EnJfsr 3Res=sO97-{'8iaԪ5>3E%NV };N׃v:Iqc ,`s6)\%Xj[1f$9F V/R-tNrG?FSoVھeʘ`. !h %cy+)ۭB܎!f`6]I Yu.D+*^9.) ]4CHM`8,mҕ̟@Yr8r2bM1̀byy[J'Z@S5k6Ԯ\X6gAoUyjzёġ;{EwXf^i4m|(E N ;ǹ0EhTPZKm˦KeQ/hdD1ήZRcw_%@,8Yuб#QZ-?Cl  2r0cr?hC]i׻'=ΊT[p-G<,im:l"-GdnR"{feI[U?{nӮ? ehbMA0ؽAHzqd.[oxѦd kKRAmI@C>ėȗ5 JL3p7B.HA^|SMUC]naZF˝#NL! ۾`*z#Gdġ¦:Vt~&Jy:hmB/;~#oUTs-(g8iV;cpjuBwᓨ¶)Zd鬁 ا\E΁n4?c֨3-A)$4ķ|-HRkeRG:P/m?'EUY60wbEk,c!vfs{(%#~EXG Wkԣ\H/N'؞'`5̋)'uP)&t> ` T̹a8U ̀T[$&Zg/J )jU! CjLTk?XFW%!8u(WzNt7Kur#GE*"Üو/3u"49C(sM&Wk]VܹԳ &\?;F#`e~.-zEFZPsƥ5BL(!Э)^٨:g;iYr%=h4 TPg-eD2wy<)q'5eVS.7+,$G̿LqLO~JJ>NY2dٍ 31 ,f; 0ȅpυ3%I b%p٪= diL^Ԇ%pJos3E`OFu=ƍ؅k0ǒ?`x+m @d|%?-\6\ZIdo,uynMMP)l7[=6ѼIXJ^DL\^.Ny{,z/{r@1jn{Ok@nW6 2Wt+zC NbFTo~+`-DlWw5J| mJ*2J)Oxd;^Fx_XG!K]띕AH{2jYies5cܔ)RA}-޶0?ș~0S!+ycͪQi:cirY/gx7dd{^;Gpc*Q;8t nh}~3-G{R3 6hxn|1['^~ |ul]?˗__~ Xj }GLϤԵr_Ր)L ?_~bp<ţ?8EQ$ښ[=ʛ7D]@A҈t/Omc5 OR PiSzU&sƃG\=yUw፥bj ߻]}Mǽ m:+n,ͺ6X׊a5>L ϑ &bf6$m0|T;E jv"ױcY,ڡRǐ\ݷ'ݹD#@L}7ZsF֝cN3^ Sm[fNj6cm ն< 8TͳDD!L A SFN\d(RP5MZ S5MҩUn…HiL MW'"T͈|]"Tkmmx.\RF(uwPWd?t^+pA7O$$_-V34:jTR?S͢(ɴlTo4KoMEޞ=ݼUX@nM:ALGyaWI!ciw_wsOݛjմa6-HUX>#D& Zab Qi#T,L5#RcdL>"L8L3CEjݩMZT:HPg,:ژ=&lrqQP5#0Ԧʬ4tc;wOAjbT0h2:LhY":J78&H'T \PۈhˉSjҠ(N0m\&DJhH܉Ȏ"LndO"(L5uڹVKj+1T?y4 PmZR%L5=߮26Cawb( DJljMdRAF︛ԱtTyzG0T5vJ]B20|w9\{.F:S=zH\AY.v/䆪'$K.M5pŨR*P4{@ʐ9Rr沌C`'ǞSs8,یEVQcVlorUY۩6UZ"?߃ \6Y8ߚNaaoOz* =Jl֪']o6ze^Y~$q43 Q[ʨt`;%rvQ[:ϴR?^X =J ؋~[Q5@fa]E"v~n.z-iE9=$m\otW0M1X I+2$D RqG{4qȷ6".cηd1w -v#`6Z@;D(*d wLoi{?ʡF["l0l*c߱L_^G]YYvнF (#unDY&8vD43W,?uժ;ٻdSHvPCVJ)sWO.c Rg@𖪱-ִpCuT"WmC0 ~YQk{K.(U6JmоRnK*Q* Ddy0QMTEJwQ{#ۅ>ep%i"];T<}4=ӳn. 2(qOQ!vڸذxx:[ܹcpۢ93-B W1u) ڜ)0UGDϵe8hLGAOզ>AH&r;ns@у.eOP=ZY8!Ꮛ6nR(. nj vLJG=ǁpɟxx؜3D $ӈ;,ȞCge M굥7*=7ះEbVeC.C]_u Vy6- Du/pjAT 12 5c[ JV b43EFD(9Of_MDdx^ݱ)SI(W# yk7eMyiJ†^AW~]]\IyUVדQf;_F+~pO7|n4M'7^ K݀w<={ EtTIGA\q-&PBBݾUo/z?"@21 1"86wW;:4RsG2t]3[N3v} oϣG䯙.mFK`A5Rmr: r~Na1r[\40O䁤pْ߱&EάI/}5jH:7p\(?hʙ%CP'(.]h5CT?[nRRw;w6L _&CFd_ZҎp YZU`3IPxT@f{J8P4P<4N/@M/6Y^7ѻkHj?ݛAH$?LfyM toe{`.!iXo]iv_8)4<&@uUnghC_H&yw{|_ү||O*.{.{W߀=}A߀=}=.{b=~~wX&1Ӟ ݲhXHy/FH8&ATcGף1 ټߓ$vB`\ǗKi!&|lb[5xr?3}嫮DvA/]O3 Q`wFۊ[zbrg>RBYZo^:O_{ Ĕ&z,cv{}xK/|%t1~gƅuп- +"n(.:&Sxzy1r j@="b aF{a ȽS~IZ09V'$1zo" y ݻeeSi^v/5}U%(\|;gE|{>D:X8@]}[}`^'$* >qOi_VysQt=F|C_6ljylj|G =Y.Fi? X(+b z{$`K'X=ei1{y5_8kVM$^܍ξҿ)y0]-X{*1= {4&^5o¢>Ὁ3ޛwh-Y.{s)|w7~Q xxox7p[XAK;4tD O‚"hU~.E6xJ$"aE|=FHn`ލ=~DOΎ= eyl⾨`l`/A3 ObLC rvx_fj3'e6AOA1d><ȼw0/ ~Ǹ܊y׋Ao C.?B?ReyF\H>?~̻;dZKKQSJey#)8, &BZ󎨧K@bGRP,4x"K7w㫿nX;b fw U+~{{GPV~|CfS .:f:zm LGe5;K&w4۽7s) gzjvl:oNnf-57~h[GU*H'K-<~$}$ ;H^>IKtͱc" %\uY~DdڧAy,a'@y㠼7|L{lb{ʻ(O$ZpGP}5 O&qd+4'3Mz~{LJ҈g·i,(w䞱|{[r}-SV HB0,"^k'aLwk,Ydy=+_`${mJ|d3\;AIe=o H  7E^7x=&ZU8U`pq}'5͛>!/"o߼B})rcy^o ?I2_~{H繞  F _L0 (OH幋R O%Z `LS[`0>w(j& ̿jw}x7i/#>A}'$a`e 7>!A1q?{v!`>!vܨ=}'~FT]mciƯ1$vO1*~1kOW{rHcՑD_bՕO$Tې_"plaq$U(F=֯0KuI86C\<`Ճ:"9M&.~Lm"cWϱnrtISOT~Ҿ}ʤa$\<{}Ej/)ev:${yEy\_, I?iO'rt<%#m⪎ H Jů`پV)A^OJ5$ ("<n|!H 2HYYѤ i`Eg%J(]_vjE/'1C讞ǧI{D8bk->z~Y;TW'" f%`~gz|E|oa􆰷}fW=^)0fQ|Mo!(`dv~]w}UŹ8{uWw7\RdL0޾bh2%_~mLPtGċ刮PM߄*Ҡ;IHs}*eMniD;)vI^޻_oC%A瑾Re fw%[{f=0Di(K%,^'l~{b64{ظw}|_LBQqNjHXX+)";=k6~7*=FS}fL\0TU Br}_%._9U~o.P!+SK =+$ z2o2)H4o@eӒB1-ilC1 ( & ($^$Q*Q $Q* +HT<"5$nj' >7:,xP!?j킇'rHx|<|<%`<G>L.7ѻ-ްY`<|Mz)yփa_<Bm^W^^*x\o<| d[P@ vxkA낇vx)x]gWK~?H`ӓ``mlmrSU$ s|EMOꪧt&ЯjÇfAAe=O ?xxx%z၇U>S}⁇D ;%xؒ8P +opa֣gǝ$>~a׫?7x<|ʻopv=Uia^uag :a/ǟk7k/>3P/>`or>ȴx\g+ӞC+<@×?vb?u>1!<|%Hev=+\>ŞټnvXyۊ"恇ۊn+ŏ|zpF^lTҲU-}IecUZlsFW~hu^1?03roҊ*,9rQ\Y|c{y2x^훸P'~_c^8<~izջ>Bxc¥ƶܔ?zxm\7+=[U;ه^p{3v/?\gJP6X_,;ݱ9ެ}pTcbaB5~ͫ~T nw[pSzm>帋ѻot_-`:uq/?|Eawz@&y{޸=/XV7\=>;.ӻ+L-]ziK^eCզFXܧ{Y68@\'FIzvpkGN~Y'ߍ>̏oQ1w96>uү/ZѵӀ^;6Xu_@/lmզ7g̡W$phwzaNp9}/]3x\ϠE]ϑ>P&F1mB;jSܜy>}tzhPI=<렮qap39ak53ucra.p!?`τ7U婞Y|wjYc*E:G\G3WChmtgEt?n)q1zs"I$z!n_>upiCMnOt~?wک{ktsU1f?7>8|x?trѷ0mS{fs- by^Lua^o;[?GLc>5wZ l$|Na ط+} VLC </(0(8p2RpL@{N&]4ڑ4ԡ`wj>3V[bo@4iTc1Y+pc 4>@4<NKKמeɌt g[\Y>VǽS77#G d] [{1k&mu2x^Jm5^_|ΑQ.|+Vh-}-SGٝ:Xk=c5L|" gSwͭƴvfz(婬?~m`k \sٟ;᳍e;}._֧û8w {VALi$L/ӨeᦽyO|*ww9fab>&zi,xiZʇoy>ﬤ|h}31>t>N|G-|VBWvܻ7y{ ,+1̽3he)#+2ssXZh5oȮ,JN`G}EW,D^}*P-aړB_֎tg~G^"ڕ;Nz3*7^ǡӋ6"ɘQ4?sɷZ;L?sx']t|o۠%-/4X6I{~"IsL֜?(%ڥ)LU%;RypGh5Q}D?3k/YH!oRf;|2ռl!-l\>]}BL>AQ}S>#ZEd3dnG[/KyϋKĢAlLSk<:y\?ݞ88~L&s.X.I&9+ę'SK÷KKU̓Jw>D2+;zhbZPeP)6]oϩ,Usۜjb? ;daza/PCmd$pt17qj"[yl2Ʋ.?;!z|hϒYQ$5y (N5S^ir?EVώ:' }4}}it_5U(e̺=2gkQuwlXms<If;ڞTCuN1kU~uCmcݰ :HW\N"w{>|ؗ^4@.O95;B-G5uN/uAu]V@3]=؋}.:E%ݯƝWWӒ2ǿk6s*O X8sN?XZ+e%iKj*n\3{7'sx񯩃_i;7ny>>u:SgW׿Mm%[tZ5k]Z}*{+ݧQ,6G"8Y⼗7Tӳ= f!ؤZ¬]R^T}f]_J9UL n4I™6#й-6g'OǏ[j**-|)dJ'+8%hc3139 41I+oI)6(|v[ @g͛_'.J] wSzql7w7uyt޼+ kss7<;uakcsm~.%-ʖrE"8#% RYޑ+]JV1;ffcwd[,OHzo)cw_K=fyzjB1'vARQ^q2E9c[\[k5@B&"=\nK0j꿶-q 1=_IBWې% 2MS ixAjJeSYrJ[lT´R=gN,1mى{=cIzqfE1PSBlvKaSi7}q9 Zx{͓_6`$W?D%m’<u .jio~84ĴōPIZp9=4ǥ*;h{]8߮ q( p?Cך.~Ձ)RS.ǯߠUi]pqS. zw-5p%vb R8&DRA(T?P ?/cKӎP(gt ڪ=؈cB#k0Dr=GE~RH0[Ҏ1'tRPAjWÄM6.]׳DR`*]nT@ThGC8_Ĥָ: uT4 =fMF.c2?h?=/p]ۧUXGDC ծwi[,x\Tl9X>I$Q <ۄUkMa1# ơ}Ss|>21G|j9ZLu`F2NhT(w&D\;ҸZ+&a" ҽ$) F0uߘO P( $#Ĉ /ﻘu?"QB'NnO k: XPŋv=\HHhoҙ,G9xAacc1 |^HbŊDdElHΌ!D((k!ᲢW+"Dz=EB`֓f`9KDTG"|j!$k@EYU,~D:Kht<5Z!z 6NTR=7  ) Yئy5@ >I h`e{q $$$LOG\,`ܐd6S%U8x\P]awX -r# aE v he0? dLҾ?ln,.u$-5mx"nXH B!=fN(PjdEF!/%[-SWca14QńT( =^{5W2l^k`",THb$思~Y)@pc0B:ʰ>],P B+cX{0. ^j)$!4e.k[f=e"<(B&$ dnFy4'czn$[4FroY#zb+RXVp!4T bPyu PbM ,GSU-8Ha g3 $ԉpԀ+LFkJaJ !' Z63I#dv ;rLGANґ`$8\. @8h.lOX1&VA09xh;z$\GCphw!t.> 8l䊑BA#F)B4  <SaCjXgY%QL%wh~^H2 a%G"hm;› YY<;+j>Nd|vEE!降Hؘ2Xk!W!$!꓇I 0˻ QTEx~" [8^X8d0 HL@ɄC2Dd !!y4$#*uʑ=8WOHjZaH 4ω*hmbXOI,XkLa*Ig)!(v+>Tn̄t$qK!uJb~@Z|*=Yw)YQiHq(Xʍ'ӆ%uY^8laʨDI%c jO;!aI59ˑq EYo|7 W!6!܊6̭"s¬ iR-moq%h-4pA@A@LMmHR.>ʧ~<8I c3FԹX @"9"p"9*+8w?聩6lb* 2P ܏<y'' ܮ4yV-!gegLX<:(GH˜#̍9 @'w+HQbOݥ`?0.\W~ӞbҒc7MՁ!(unC=~By{ŧDbvDi1F.R@8+8l$؆^șa ʓYbOٓ ˊS+zR}I211~ttzyw@m[skFB.*PiP RLQQLJ'fwԮSS~"Z,x_6 fP3siÀA(|kJUi?,&8 evYl qg+}(^'"7s%=N۳bx -Hm /5&X)6>>H+|"ͷS"9 /;7Z_;%eq"ĤZR&tN"`jpTff\Ee̦,PUe,MQQk]R"k^XK3NEjc ]$i(%R[UHb_m"yJBGP97#b֏r^PyL' \!RDU .taT =JЋMU3SD!+ 䙓p[(J(urB\]䇤^$8J)3SoV*.IiR> >stream %AI12_CompressedDataxkq& Hư/bdѣY$K#0M=fK'7nUoƹ=_>ݿzoߜ޿zO^_&odo|> /?~E_}$ۢ>}>5b*ox_CǖGfo~?ܿ[I|$//볷n{KjMMz~ȗnK o޼z߽|קw߽nN~/@ׯF߹Iݳ/_Ay&$/7#O _}M1.!/_}@6e&O?fϏ, ?ؐ՛<%ގ1M6oWozM.渭7OJ{'/PBS1\`xB}iM?~Ow޾|ݽK]B_|o^z_~DMkB (yoxv»|:Z/ϾzZ~Gכjiq@H?Mo7Q1"kBiu?| ر/ֲt3?2Mhǝ~mp_ro8{k7oiS~|7_a(-?gw? }}OHi?޼ٿW/? `oŗ_[P߿O'OWc(_~Ն!/~q?_S/O^d- Ihi|E'_wΚ GԋJ/vY)(7_q;}xj7wD h-4ˏ5@E~zxcOE/ek7vD˷_Wꭙ{+Qn~/b0l{s᭿#"'O>Nc_|%1͇w*33/>>eݿ׿6~GS1{oE ՛Ǿ7A[߿z@"/7?{^6B )dijhf ,0S̱[q}<ŧ!>K!ŔRN$fK锞,s9\s˝ؙ}>!?+ĒJ.J/rW˩<-PcM5RkmA]>g-R˭Zm};=Ǟz:>]?g#8ȣ:H$0q?Nxfqg$>ǜn|:&.Żt]kwnͻӻg>ާ|_}~ߟ??;SS=4Ntw?NOOgO4=O=OS3@NsGJ*D=wϨ7ԧz8ۨߕzi$Jh|Fc{h4I4F@Dh^ Չ%f&ҜYh~iПь?мhi&?V։KzB{F@kxҪZNk\[3ZLN۲vM {A;~o D6yyF&=;fK3z2H2gCiiӞ;hwǕ3$t|3![x!4%W0>O>WgۏiNSU#ħZ{ v"vG4n:QJ/ LiR2cBh1) S KR-YJ^)j* R*4('NJ2)]ŢHJ)-%R*4 g_xZ4ii`L"\tAo˟;Þ뻊$v}OsuG#;0^?w9K<~sl5 a>BAΞ)xKddddddDU3oHL<ʀG)~ц 2k$C *Q0wNv*mdLTzdj٢hLTdS6mL - 4Ψ9tM;xL=GhS?NAJPBL ("DQ)FFPɓP{"NeȳREG(/ɼsoO;<'˜COx.~D\RI  +0~> uzw7|z%KtC7Q{=cl_9vopSzl۱k ~wKK>>X•^q9Ͽ߼_kv7uTW^|UUɿ&T3QXe¯*F;E6|$M &,@K]An N"V\q^)ˈ6'h7$XD"LpD(:Ú΃A(:OSEj<5E]h=@EpDbn" LS w"t hQPTPF&˴\DجT ]!N4/}N<)*@IRE᷈O{H''y:&_͸= =SΞzG~|>>x}۷ݪ.,έ`slu`lJ`vΗ]=ݰ[NسϰO,$i`?v?s'.M;E.}4L At 5dQ)X,:NϓXa h+I\YE qU|x' OX0ȦA~hb"b&䇧H $ad'y*σ<蛖#D)VO>-xā(=;G#a{Q!lO<`8?hͯW>H,챢i'n>n=nCO[6ocwuJ޻m5Ryh!y{_yY[Wo߾xꋛ?t)TA@1NK<}!@;;RN`<G?^]_S?݉G?> h=ɾ=7iuڃej/>Dcc_-tf#CgGvOs!…qr5̕Rޘʣ̑|LpҕG*dTH#i<|ďN3C'9|g\y`&s Cn>o<a^]^R4hU=*QL}BxϹѼu"I<o< ^E+g" 4up =E%NApI'_GvLJ0!;<3~>wC0n'+jt= J;:)|B"m*'Nv3Ev3]ޥynziS~FId9xvܹgB W85?cS}t`:Y7'8Ń܏ͳgnsxNGCC5Nbշ0c~ $E(a>=0q}YHf| [gqH/}f ZјoJݕ 3%j9<U+0(>7o=fm+O2nfRYggYſ(c%Y941tݎ1]T +H8w inrm#DrmA\5VՀU7@kK'ck{mK"emoȷrq{ίGYƭ$GnGnyYz}.ӲίCyK?-2"W'#SiGPz@B @Rʸr:psY#<^Υ}{  p?ChdHAЬV*;3ޖwAvqhox7C]㏌Hgg@pmER0*W<IZC0 C-9񱢻csrm ݒ z6}#R?zC0X 0$֐ǁΞhbOSوL^k0cgŀv 8kp*[!ZΧ^}hɁ!Aot9TZ/At@d01CpZA7R].zuGFJa;~VeHYKSi0 Gb-9񱢻cTZG hoa8PO_850tq#Zc(`5HCg"($f{3 P4DZ4MJ"u$rAbOQm<.YGHJ4HDRQ(zC|;bdJ+ûB+Jnxwez&Z:~|L*$5史bg:xbtBWKez-[=־z+[sY-[?떭wԚ_֯ZZl5υCl5c׵_}iMuﭒL)r\?W?7wlU͟>eWWU~Bg݇6 eo??ࢿr? 7觟[,dfY%mk6@~6coט^ XW[t  HGx3H4Mī4.&h/v 6s1 ~4QQe6GZot}w`R/oy$zsl?sXx/b~d-"]6&kYBiRaZOM/iI8NauM,A dU1qdQ>Yk&/wbxY#L ܖr5(?f DZeZݤH#+ o_M-mY(ڸ lbCG5NmAt[Zha>띌L c73IDi DL  ÐI{9MG1/Rх&ɱXoK?FJk9epia^;燕LL㵑Y*d9`픋6b @$!D\4ĺ,~FѶOV#ҶH1lDmq1 sU[Q_ٕg=bsUH-I8!j@4'- oҪ6zI{݇4-g)cB)@wW7Yǡ&d'?ڊQUdHj NaR '6%-ҮnoO!%e:fj'p:Amw攬J4M,L_Է'%Mń9'ǹ;ۖ 0$C +qr|tuBܥ6N {:{8 8 V.V ا|O2;,EK)b@,+8Hr$Yeizt,[)Rlayм1dVK=X@1Md ^@JTG r\V3:gATss]_&"nsà+UY,rw1YBERcyH\1"f Oo"P2UMGp#06!5)y FUpXUAw/wJKM3kمjV2ܫĢvFtn,>+>kW(S@!j+SkxF@|SU%g;V$N2*~9V$BۦH .1`)yGd.Cc6 MY%1¹Maeo^OljfN鉍)oae'\M\yl(>f> QYފͦ=b,fb.mhͼj!ݨO/t8pnE^fkJ1Op.L6Vfv=K5y XKyce3D.{{#oD[a+Qu ::DZj lv4mDar3[t>*@|IyBG/ehZ"0MHY&2l-0R؂oDJ 'I0דؾ50^L jc1ju#dE''j[kX}t^+v0Èi'NA2&mX]\TLOiEhi9+ВNzB8< }.%iY@9[FJ6@@E׬CJ7q#H$3 l!7L[ަ<uNy$;+$,C.J 4:0F˄E cl~R!+:-NqT4W6o~O,l"6aksղnD0l'ߢF: #~Cs 3JpBWn!9T5?¼gJ2TBx`FLS.;w6[y3Z z@ts֠.4kSo[^Mh+wdLGb3]&Kt@t34$"+VbT_s:0S*rOA/hrN7Z,Va^-?~N:IKVW$. kʰ3Tj(0u~Y{= 76۹殼o(izB{T>LSeQ HqD`Ulb2Ǧk zdJZwy!,"#-ՃMS!vlrT Sn 4ˤ ߴMu-@xQu'g9l(Ý hf^\Z]r8s$PEjP tiʹ ޲ټDtx&%yl-~v| !70wMP)Z *~ѓEύ;M᳘lX^-R0.c%˞'qd}? 19zI3߶٬e,L#sbd a' >w)HVf>At%QhoÞ/Y/J\=ŏ^ ?E <1L`fq&H0 ZGâ%|Iu9]`fʣG̕#g=tNMYbmtO'܈+2l R4Ƒ^=,'s֪ 0D@Dʔ "B-=a<^keŊpd qa&]8ektw2a|*u;j͟ CSz vU=Ҡv*omQ=0$VhKp֔`4xX>L<]#fRs eF+JX.xoQ gൊgBx\fD5הuac%? /{>6;kqqT|Q{?%u(nJXcs͌WVYaG*4ڞYC YcӄVSt7IL푁쯫:uMI y ^5oea mvEx6G2\ayu/?iT4g1;,^!֨ˢjH ˱%׵RU(&?7ÇdSآV k&|ͮ O#*ٕì7mVŤ<=]:E+%BATz5"NST4oԦٌYpҙOcڰ:(|Lُ Fjp [PD*WLoyZa-`b/n~tV.}+Rbѓ5ؕ&~'>U8(kێ D.:w d+."[pn@Ti.7&fT:rY]&[u[2UmĻהk@+*% ? *&$f-V; @W7cMt 5OŷOڱ:PajR{3IKw[*Gš^w%U'?7RhJ6 L{!)-0, YB%A2TS뻿4y I2(,lsJ_4*)$'j,v^ECaِ2>+Ѫ!n|z^Yzyi!u/րø#m `\l{JpZ6g5ͬ%_="jlc9LEU:BB^0ŝ{0D'n I rJ޴H>@fH}잩ʊi C;^4dpGTOeͫYE ;ǝ]CwFlq:0t\ Y)'*ւ54V_;ՠYijD ʾigߗfOεSܑRR3+lRk f71|D iY#z@&`BTƖi-Qfy5#^$s4g~^00li\jX߭*g=R飐ir;B3W j/.i%9EJSJִ*P7e{VluvvEe6py%GD l]:UH!ª+"TN7iV౗P!Rb L57pЌ8l= G5,G=FBw%oi9]&miLF|Σ^a+碨фe ~aS:u(y} y~ߝi~@TWZ%pؚ#>so  Dj6~N# *Djlɭ[Sҽ/jm:82\F \%xMr_.;kkS@0 uE6o!4R-/#@^V孊KhoWg{֙|\NmWǦ/=?61f5 tBBǦ7 Q*%[: ~l­WǦ/虐YTϚ^cl3yf2喿S ,j0>J)c3B5&vnjlBB\>e4`(SL|>v8{DžK1wQP| bSls3K}_xߟ*Zi/P] .EӜmjEs_4MGkphz/hyt4ы&E ~4Y 9o*j 7E}˩=SwuΪ"UB=='^֝tE= 5#mm_x4&flC\9ȺoV&.[t0$ݷנeɟeU94ke"hDP[Vq%Z,x; .XuC GoUE\J~M/R ʪ/64 -xճ,{M]>]coΎϏc~tnx.TZcFj7ܗu5Xҝ[?#=]X*$}P$J0wNc ~E'^+!0#^f3#2\]T ia>ŋN&`i5"ٟ3-kys"!@30yCY&ԗE쇦ypЛ  W-[Uaߑ $ 9+-ȟp8lbݮo%*uIIuo8<4'ks49z[.2lWv8VᎲi&=i^6K-suvMC:-=z\2@/Y{m%rl Ԙr;}4wᵻ6Dlq_[Gk53Qֶ!C vuX;׺=f}zY {( YܢibeqB GN׫+)4չzpsc- W[f\G7UͧJq#hf+:r)/ "9n RדK͋#-1r>|Ii1X_du[4,Ժ4-\\?h=;iiIw7Gi.q:)|,D pW=za 06y0f1g7aJRF[#||%C3;xւӸzr ~n只_%M_#ni4gHЂ}{TO"Fx 'M6eV֭V-$MCq8{evxs0,>-#Āar+v6KT3[O\w9s3],~[.n@:pC<#VQ 3d pqsukJU 'FYR8o3&PPP`DM^Uw%"֢x3,ܡ`Oԑ5=No ѯH[կ܂j@8sݹFw!XȍhA ?Y"hِUziXˮϱȆp͢:%xWlN]W?msI^P(ڲk4Kueq-"#N  Ad9,Dmt˰2+5YȦdg`-ƨL~|Iŋs"9(<3S]2<|°]:: rW;hixD}BpY(b?Rg^GBٵLe2)`x ycpEhT4@n#^%71Mzx 81,񢄣EĜeTPUKwfo\z:Y 9cFgv\sAnf=kzM1çut5tgH}AJO~q/>|x-#GzśW_n87BM tSn~zOn/ԭ8&-7]UwCҧţ~Ϳ)f#!K`v^#YgoBbzh1;RK'Ðb+{d"/jh -$x̔=C G /&,A99H dվR;k-FfR$B+"NZ,Rcb6E|⸥vNU=5͑ z`y)MINye%(_^<$Hɛs)Rz4Ra~yt M:I/" sh #g&{F` ll޵eէ36RO֛Vpvx>Ǥ'4C9^{kO[0M|8XG"cłAH 7BH+= h0kiz txOۙ몜T OH S((q  a0HԜJ4>v lNk/1d6y(00HyaVֈ-*usxSJԈjI}6~ &Ëohڷ_.łjF]<1`8Fl =z'.Ho1р= \Њ!@{"T̠ Jذ\-ԊQ"2r,[BD*6aҜT&Hm3|訃j5$R6{%`TSъ={PXB[::t ܸ$ Ό~P ЋR P(V8t$. &5f#&QR p @#XȯQeKި\P8т@;G{]Ǝ=n\8*z ܀i>;pa0(.|3@0a3.r@lȮ6jzH(JX %]Xk̚_M0U\' TTV I QQ%dP'0|(Csn&x"_-Uɱ HzW i lKW ME4Cg}#aM k?yypM y.`V11'[֧勅zn&-&"ty"i@Mfd1Q̧Q6뷷Y 5) lNpLDj-548|FRX]\|8}Fkkj/$\ v^8OZ=pqAvL fqtshóWg B VR'F8e,ȥ& g+*L!' pꯞ15GQ0PG5bpWJQWf]kςNP[)8 V5NN[htUyaXlYq]|2Lz+$9椂 50QP:,֩?euRf9q}R]`FO kEl@)Ha h]Uw bɵ`T2fJ]Ze!Lxn.2)Hַ!5t㹭]a᜶ɂ5bolzW^ido0bL"@۫{2p4m\؋R匁]Um=d );P>0s¸M(*0ŗ Ѯ#ͣK1(^[j;\uf0@0?0F;L!O+f~DNh.sn9Љ`,y,E1j[2ޮ`c@0UD$K6CKFa2XB2glJ61'Ѣ8 7LZF\h 0ŕ11i7x`I,cnjjӞAt7q8߫ %kb0@&G 4YԏM]!0*&}}9%[o"I|30-R (<9a ɏ|#YkjԺi\po >z'  0ieaX(^κ.Vz5X#J\.U+6ejA#o:Sf6YV_6і_ xo(l : './v׸)VU 1)MPX8sd ml[pWv ̒ n,Z@hYFd;MI~4MOPJE u3.Y?o/T;.c'rzZSAlC Lォlš@IL^rCr&n* .J ?m0R18,/>7Ľh-FɃc.);)tqx0:^_>@эF=z#˥X>I*ٸq\6& Ta$*a08.ֈ*>څDS\13 7<*s#q8au%x)\Tp3P < c& h_$")5\ٔ+Ge;/e%YD_V+s5YձoT+*h91/AOJ("T L^]GSe'p}pGU@ Du.`n_S0<ڇuАԁ`ۏNK}VCm #Sp/8Փ½ڽ!% ,z-D&Z/|AR[uA-;E a2ippV=v+:hö땵o nA M@iCmձJ:cCs1"0_ Йi5B` 3#0g={T[!li㌒`LH'Z!㪌 k+ 1F ^dɩ[7˂'Y72WVsه{gȽ{^1֓7RqE Ӊ[墹кGe`5+m%<=)# wU1>cJ+Xyr=\u=V1{7 J@[/ŢWJ(m .r= 5pH"K.?(]5&F j> \j&ne)THy<F,OKC7r)u(u’GrbBm0nA-fG0%a[L z s~"yf"ul0K^D6z7sI3BVqO8Bvh?4~:F 0J ?CÇi9]b0!ڶnx/)çh%e#,\َ/1<@nYp9EW%yEqLY^f,--5vn,GkܱD.x\ wV֓,p1WuxN3MAk8.p+Xnm^8yffNZLͣ#I&]v`i;S5 Ɩ(WE!nLଵͭ| pX"*w 0u.)Q,sN4gN"A@kaZ9Šl-rGW9Y3ל<څ~:4"Ń=ž^uh E沀͊=iycp UxSᣮ澚*N`bn h˾ S=5Z!HC ,=C|TeA\6&6?=uFbL)75 - PȷxGQ:a\ko8&\&.8j}mnbj7?S8 vuFlczڣ 8b,Jxx +WYc*x(هQN$oLmm<"4_f Dbs)% bR0j r_۫ s;+='h6rR, W E&H u %Pc1(q"|y-m\"2;^"eÖgqwKR478WJւO]./|9eggHxYp3 Cs[H?= H8slAowVbgV=[ؽ[\t̖4y͖9PG/&͍h'vY*rc۬ a`|IZ 1n fzY_O>g~ y4t TIŠd8I#\px=yԌw=)#^`j`f1j0u8@h/.%eAY#^%u46"1PMüpA Azs6N0p-k>iX⾢3351c2˹:ulH vad$%h/;3b(gb;VZ'fzasZ`5D=m7ϱ1.Q9#;fMF`AO;wX50m0Vq=Adz)'u@ !& 1La5q믨 fʐ0~F pӕF[sc _P!i(9&߷h"op-_GJ(@3(z8p5 \Q•,yxآ[0өf ;`Bb b 袣| g6MП|8q +Vl^, *zݩlV뵚EB}"{:(V+o0 AlPCv`wX xrQVID1OΕ㞽OBt'Vu:r9PZן%2,ҲaźT;p˜iKDznHXŻ(i-EN3TuNt䔵tN&+^rB(iTKgN7oh[2ٺT}'MUGVb^,הO ς$]BE >o̼O̪M;|7N@pm2EdI=%Q XpߓAq[,%&=7Z) "r%K`1a@.zWubEfheꚼeQ'jTDT%faZ0E*un<5.U]{K NS"fB΁|@Y0L:]ϖq'wLh[Bn[}/i"#:M=AiOsnCXLYD$3.N-7oW-Q]1fd%B0 UHR 5]Q嗢ij+U_V[VU`u| r=iA𒽼0 v[-♰ou8`e, V0)WYbd6 &L+E2,>OȧKf8aaSSnU0-dd1T8=! j9*_CXJ~BuJъ&@ŨZDZir@A Qʋy[&˴@e 1yn+E$87|1}A/Ҽg4X2'E U1vZa"ʰ9e Q}-T\^z.%saQJ?A-tqzqQƐ-9Ǧrgc.[C@쀡cQu%K% \m6dO6dJreðMڜfGLCHek]c R:cMEc$O1/M 4d)ǵ n 6W3Ǹ7 Kic/g5u~$ͼS:5,-O/g|ܠՔ@D{ܥ2/(.gG$#.̏ovNt&]-DZJ6UJB:4${N#ݴhJJ>cY>;+Z:]V+w%$r/gceMD8znIjm}Z;g Cr~is٣{UgYm'rLIbO[;`|_Kjmw[@-l[ю`!R?mj~XEp/TOg͚ͨjW` D`TN l=}WuG,'iZ&SlY7b:sRM!YA);BYYN'k7ɟ/3c{x/Uř@pB'?[6C}C21$xd0  nLJWw)'.8om"8Pzy.ɬ+k60s"S\-EXKKWv-}+ۛ&Q;AK\ņ[4b) i$_eʌ#@ Y!,+ 1E^ }'jez:1/+en8ެ@bn`#dNg k7o?`XY[Vk. lstζOS:M= ux9tlExنlm_~fDNw ,!D qRٳG'U|Vc|ûyF2`[|U!L=Qrj,r+@;Q:J^r?~.NK9߂*4WdU/d`5@.kp XVdUK.ű;4OxkPH䗧鈧 <7h[CWRR`K1|MJEM*Zˍۦ[!;9z"r Gbdjmh_ J:mdȭVC~r% pj l/NY2;ʅ[iaIbEIE|Od[zbw41XT5a7l强ǻ1+5|B`Zl㶃 =8 ^iJwGiޢb`1O~IKTH In:x^l;Q喽jHNUfb颇 n{s\,>TKv!5/{oq ;B7h3[W"g`[aꘘP@ (Eٿl*6!OaVp#] &;U+gX`w 0AӊV(i4XI<U\f` _Z5&5 cb$d±3%*,*)"b2*P0(ǻ,QjA酗!LO! 9nRՕ m8IY*e {*oz-E)Y;TN#QF>@X4tijOIֳ 1k͝0D) 8=i;-ف#!!hTbfMM0D f #G(?!× u}QNpj.iyDNSK)pK*rQyxs"\p:j#8!9 ܉!-m+mll=)B:hZRvQ^ 2Ae(gaCLTdd"Q l ŒsFO(͖tELWL P8pb qvߧGtyjK22 &ݭŰBuߛo!ˈ/ (ЛEVbvعc4p>DtȬbtXN[$佊jmJt #"3F׉~m%c?hm3J:X; =D #c3RL^ExVq ѫiob6u#=i:fgq&"A}SD9:j* T%Kl|cb6L`>SC5c 4shoO`@5Ќ~YX%D@ V'w*} D|9[!f.}@!8Ĭu&e7sl~qk'K`n*L`e`)zd)rYPj6AB08<_T0,97 GA)" %RjEF@tOqMx4.BSMgiiek#&jRGnl$O )ԫzJ4S*S%$\E0gBAc$D{񚩝AWaQd!b4?ԌY-.iU45+[hlKxЉ{ 7r<̃ܔ06agjԞ Y=b%4x88h>%ނg"7փqvX?YkZE#E)V)M0OڳӬϛ >g1_-&+ 0SUUiaQ6OUAS"u.| VaJ"f'ƠYM`U̥ÒS Ƒ5.:Y1yߦ\k(ǞKQU1iևUaH,6  ݷ&m:x>UVf@L願-%=J=dkY jnZ5tk=9jS] @ ߴ1YcNXDpҹx32ZυA|`ĽFS*:uK%{8P`lŘꕽ65t1 6*{i"bgox Jբ~=!Jˌn?ب-zcn Twyz1T;w@4kLӁ2G`pR–Eë =P69?@#joi(\ @ 4'ldq>X`-D E bW6iNExtz~ O_ʘKaR܌+Ep +n)21'Ƙ͡TYbubH`qNl޲WOnU]2CɮES& Z_Un. ZVڭMz'k5c'V[D2rlY_B]])-'0y\I|YW+, ̰XKA YPMq. z+?b^BF!c,T7 ձ:!@B65g1^TLaEvؼIG1$(Ģӈ~DCZ2I6cuyGVX:}& QaSΤjy/n42Z;QLxՀOubQCR^E*VRpQSXsas"mX&BZw)œ&rhر2Vj~.!ǐDythH8B7} @ >0% 7.&p `\!FQ0gӀ-$*҃WcIl0Ď2E"fACۀCUbhj _RZCICsIφ1K /MEsZq=ԩE*4V[+)c2=k}niIĊ6;<"'M'cnMشG#Z)dT>iy.jyi=.umO(0b%<ꤦ^&Lb)i )*NSmDg (gLaQ5$ p7KCvf8V3UR'ⅧoLAFNgMdSpZ}LELm?qBsbVdG _2L*)U]G5}-gs>^^8wL Ml[mLB@l**Z܃!-Wtߕ69h8lN HSmmUk{ofmūf)]WS*Dt.zwjAXN3k @LH]0c"dd.lsNϔ9Rqhm>znJ).LЈ&gmH6l@Z5^1:K\mcxdUq*ZPUfBt 84CQǤOW^4b4Q`JpvS5)5Z4V|ZQ*k420^*TXnx(HcY89F`CQ4R1BYcP쓶Xb^C!#ykUx4a@$a_S_șjK"0ađS-%zKjSѝk4yJXMLLTf>"HAgP"98@4ґh&uN=:4e"P7 nCl= 3(6-ӒYB!GMqȟ?4N4ʵK-u(k kZ00|lTփ&64uij뀖 zJ?Ͱ6諯yrQNF('òqzwX-$ :_b WIg"AT s t{2ȃ Tqj9L"EuT%ȵ 3I*.EDSgS r9[n*PnX"&jɥ-̅"Z̈́4=?GS=zq%V Ec ͖'*9i$6Y`B4輸olv`uN Ovs\Ū9s&ض%P--M͐ k%qukD%YLy oT&0kj#AG݈D@HmUk-Kc {,Yg1ªh,+15 `odcAw9 9(^6TDžO'y։QX b[&5 4|d{oVYŤT}Q 5EИ[? 2DL?Y9E|ƊPMθ5Fi#d!g ,VRVY8Ndž0vS6E<`}I47)VN2 cѽ>*mѐyyŬ.vLb~lYl)L`)oΤas#kL5&[ΩIPV"ᢱ$In< u~R.r*kXKTqCh$1Ʌ4(AEodsS;ֵaVO#b< =>r\:_5D12[ tq kdWR"qn+xk Y^f0l&i*6WB޲] Md vX 0, 6U B2iTX4_vŲ` BLJ,(t&i3+Ԛ| qRY jjڨ}& Q7AAD+k:>9ZCv$VYiP0(6Ȑ>B8ԷvYbVlRRި*b> (Sktb c7&^Ճ#DׄEM@1:Q, ʦ0+ OfH ޲"'qqRSI8z1Q@Kɖ_5$XP PaThE]jc-sa߃0a-u1#~=) GPV h@|UV.KEi]5D\ ^G`ME !4JI+" uLiӈ+@'2rmcb6a4x*XfGګPai5A՗Υ*oӶ>%\Yjҥz$46ڬduӉN5,:Q; LiIEu[!_gغ@z,+h!\/s /r5 82Ңט[Vl fTie_F}j)Yߪ[ĩ, \ 5JV'hj;jZTg"._chc8e4l~{t=+3&V*iRB@xKQaQx} &v2Slt»ZDkbJSp-"Lk<"B>^&&Û |B{$]۝`vdE͵pl,Z!ꮁᭊ#a !H̥+I (S%GL_,-plihÖ śHPL\D[hmx=D+X|񎱍a]P3Zߨw=rj`=jӘ2A[^K?u~'}|Mwo3-:iμ`5C3?CO22CqU bK:`ouiVt!ZȱBl* : N ޴~gV95QFjbcɀTv΀«I,/:H.7r3~K̼.TwNnF!;o$M$4|䚉M;m7_~8-Ay10_̥R s곦73Cʏvpk'TC%mY dK6Ȭs$ٍ\1wA~~O50Ǽ֑\mal5^ UQcX ;PK7/Z% ?ic)2*mFAXjL-C@@T)` (lS.2иiNX}9wo[?H0ƵEX$B3 6?)ܴAy+Ui‘fj2BYqKUm\-4]Y&N*5uk EU )BIW 0ݬTbx *[CTrl4)5KsT\4уH&h [^^LCO.5x'jnΰKAհ^y|4;Jȅw(r'zb1| ʂ)U].;`2Hj#,uSY,mQ%c?PHjY)+ɎNJ rf b G>ޤNNE fUA!UsTJxCe:@'t0P#{C4ꟳ5MO3 !wYSu *r96 j$kZ~nn"NY0bkw` .MECvq(WAYU!#BAKFQ56="T Lb`$u ТϼGvDr5lX%L78] M?QHn[U/.ym!R~RMgy!mAB0,  6:A+>CkIp%%{b#7*+5*@/l`0cnNSaL4#PbF5c#`YֳZ, +ǚÞU#Gנ/F5mO-ǡ cLأF >Ak i?UO֦|Z-U(,>|1b%$%54VbZwJ &?JF:6ʣ :k aI4:s 3Xd"<|۔͈Gz]V&߯B@Qٛ܊EꡚTƧUER.ʽ$U݀ujClӄZ;t&DPc~üSWiXT ul5d7]D:Xvf=n^SsnCơHQϱGڳH\gx\:ch 6pަҭN]kRӀ.Lk!S.Ck,PI ɀ/يNܺ>(\2=NaGF/ƪ P6漫bJD&5 H{Jb )̓y %`><' LDuK/11RxtQABaFǝ̟Օ}BÍy ""}Mze,Ѣ/҅5DlDfהEx;z@SnUQxqA i0V#8#CĪ +ŨgS.~b:w+4 ]8 M2%E /L,O*u?D-g",iMHf]S,?% 9+!X9HBZ!oYҖbLYR!ۉ]LV)f+@d)k^qlv:$mI %1оHՙT=ߨm^@ւD-ģ3c9+HdBPT[l#;33^@9G6]NN6T07gapP8uNEB$GXa9*u!qĔ:7@Tj1b2m7X{QUC~1 u^ʟm 3A͉nƙV:]Y6P,I $TTb%t1="&vu H CvatrjŌMbzaB{PįI6&֯%:MRkR+' LO"Ǔb@x|sT8]p`-0J)؝mSi38!Z"xU #;p2ossDfu=D) XfYA\'FWZ C^iYzǂ_??կ~~~|ssz})ߜ]ӗD>3d|'z?[?Wx|r˿}d .’2~J.%WC(A&F4Q?B LKYggހSt;z^Q(}:ȁSvY'FJƞ3);1Ci W/d i]D¹҉R鐈|B=GWQ8Ds"vOC@@"zfԖ2#w@}VA C&"&5ch:2Vdi/6aI t:DQƔщsZPb 8:,ơ B3/2:菿=$bC'X#%顱Kb`'bS.-A@L."XkCصDs=}2F+anNHk'9tgbY/31vL&°ԉ~(+O7f6]I)dmNܝķ=H"rP")a!@B,j(d Ob/=ȝU):L!9c(B/=Hr9^R O?J1|{0 !+茨׉=Dw9.].Ҥ"6f[(4m2d'RsUy>HuK̛d> Uߓȓ8T0,>}eӔ'2T17|1H,bWE*Se. sҁ:4s**#ZE$*+ѹ',+<(@P eZ$m"7t@#=P =MdAbd}#N| H2;)<[WV1>$VE!m$zFuo<9aӉn6Y% G#JKTbQq9_ ,ۭrʟ \@ 7|/u+{"!c$5I$X[fϬl 0caL+ aP F5%AVED8/H=c{"o%#wZ: "8g4P_JqUP1-[Zy.j܏HNr"+dZs~?^,|JPU' ] # m"qp7, gZ m|= 4UL49t\IX,; sZ8gș YtE䬌>qP-,Qu$Ivg/B8iS/7.bc-7Wc B꿷]$l]kpw'f.=xڂH5BRq^y+["OMdš:Oǔ=6gH{d G.&4?Rk\d(nYCz@HI,VqM1)n:ktFd P3ZhCBDGk 5綐}C\WT4-p@lWP[#pT@=_`r;I#ڊ1$1hd8*Tore:LtO&^ziE>p޳hQJdP^S,HoB D>"H*F>$%#̂,kbG,iղZ^ႋdC*:5}/|e1B>:DH Pڙ86]27=\ M`/tcRy<9[.r.-Y4+k`lG%KGRa0¸)Ƹ[xIAT:ac[B%/55e1VVkCjONw т<.BLHK2:}Y'fS eYhB߶Z1aO !ZJT-FtIb;D8`F:0Ё'`\ N], 蘒*҃L\\Ef$n8LNLBThq:HEAO}TQDeA/Dv@JbE:9渨ĥCN 2 7vWpK'-X @F*"_'jJP'_&t؊@D+vYlSLPׂ JZ^7qӌN7=B]0ܽt8 oB$u$'%-)w 9rYQ`R&Qoޜ19X%##9T:lT}VXY ϕmYh4&B-ّ;l ~! *)L^"{@a'v#(|x=[mꄸ֡='?Ѥ}zȖ D~1j%W BJEM )R m ʧ$+B" iLegZ^IkLt=~IqUgGIt`"U]MjH_AT uٮZIWC, ^DC?tHJ(&^h At,J><11&LueIE KUAfbSma p߄,'R-h78i,r !uT6*]!TCDwQHbKl }Y&8!U4WyK91ü08ӌTKL6Q1³YwOY* &sh4eDPmaR$W}Dڅ"Dgdh"R=pךNyK8^!.AS2#{#@zaGg'2-BWgT34p_ qr43t ̂]~=u!0#>'f! pG2mFaݿp>/7ޑO(Ad)/⟜"PFHQZ)JU)?ԧ;Q-whH;Å_˛o=:ɯ=[?wɯ|oo_/W/OϿ;;9<~7877{/gǷۜ|{vZGO׿=\toVp|F{zͷ7?TԺG.Ldz7n>7iPSO_}v_'x7}ߴfsNLzpNOn_|ه=0q3]ѿl6`o\toH>}|C?bƓOߛ[[?{y'7?nq< /99y?M5563]ц,]q?5}f=OʃlWoONx}g'K9o0γY7Wכlo֋^lvi$WнzS3=4нCK:{DwPηۊ^+{Etѽ"um&sNϿՏO-?9t)mz2R;myΎ1mW,ngǗyGwO|^nI_> +bF[0җh؊] z>$+t'9sz\_]ۏ߲b){{T/GOO=Wfe̓^~u|rVgrW.Oo-r6ݭgvrGդ8K m#jEǿ/ ˛#= G"ȵ퓽+ȇsvŹs#b͛_n F-fQxmqc[Q|F7l/_|~v~n8TT?: !ϧߜb]wRښ<ݹQ\L=@WWϯOO{sJo؎x`;f/l>aUvNotxyv~E$k۫ocO7]t= ܳ<6w2k;a<6nWxͧ+Ѳ!B~:e6=KNmWmwBSvlsًo//OϿ8=?=ʚˇ6z~l^~|rzqzywQ8m%mm9ѭq.]y7<+%^ jvKn3r6װwm>]&H-}]0᫳󭢸wa_]_]l1+j`{Dٚz{[X1CM,m>ˆXy@㷛O7=۵ՠ-))˳P/j?xDu l<՟=Ԕ/.ӓ7oW2753NO|rI_ʈ]bd6w{n;ۈD:剠ζ(rO B?};jKGۚla1]` g=#m{Fg{FT;e/烧8{6g6 / xp%@wkUwKJnn}~Ϗ~e~cIA<@oĈN?y9KmdקWCQ'䶘(L ܧ~9pr8xg/O_]mV>wۜ'5_j҆b2i ^ФLzlbS68pl5][Yvwlwwi|mg@.zݥ濾ya4/t+w{ln3=ysg3zODʌhSwʌ1zUOv-~`g7^l!Nt|؁'~(po *{9ǒw{p!{!!05ވx5o;rwi<{vol;]ae^\]v]r[CՏOoozg'}|/ە{Yу훿|o_uupIj×=8{;q_ ||];7Wpvu~zO/: wآ6VƽqoeB@ugonSs'wzj~wFzX##;y%'9~]X^~vģ.\mc=\MwJt{7:N?iqNb"7:N{7:N<()i;mKӮԞvJ/`Gyd AydGaA_ZGhyn>?>{}=*<{c5Sߕw]{mx!ڶ?{xC}˫R=nZ3;'`lǑxky!aZ+z|Ōn1;.v^zvlWfKTD{5ǶO?iwh4뷧ߛϬ-&mB)CMm(OKB[Mi Ifod$CRx}r&-f7M2{̣'?}ڛdֶho TmŒbW^W'7:"t2d'\0SkSەps_9?>&]}|rv߶1y{_?ԙI?vGt'ۖ_1YޖHlK>IqJɻ4# cs$)YWoWctEÇnpTolf=6ʏjR~stIjWﱽ7.lL}vf_ࡎ]7;=>Eߝѣp$BԑpdX$k/K2_ǎGtz_1oIr/=Vl/%@۾"هH/"=_ܹw<~`{Λu6HۂY|bleFa'fŇ~jyn>?>{ÏͷT-?Ə-cx#3?ƻw0}]~w/F"T(v|R.@5W,V|9Ő/|r|*|ga*k KB1Bo\p95B=\w0{x,} !|l%zwX}PS9p0Nr%va]u Z¡1ԃu99Ia :rKe_H]k?WN߬_O*Kiy:ϟvroW7Öp7ϴ,))Z. D 1>g026/径a>aZ}\,[FTa>ϼ=֖ÖD->>Zi8L/=Ѳ>[a}ϋ8Kss){mCڴmwRB/- k k,-C,.!(p}̎KPB _4܉> s a= X{9PTR`$‚>>ay뫃UxC_JZ?,G?nw\;G5Z[ǵk;wb:WB4KĈo-ݏt||Onnx_nW!O?q#]i[Htw; 9ؕ;͖Xj ]cE|&5cptqNB/@[gl 8gv JQjtJ G"wB0-38[u/> '>ٻ`g|1U_63Wmh?t-i: θ>% G^G?xE;KG֒` }kB[6XapA=g$F}#rяSj`UKԨ#}'W,`cFg)֌Y'.۷┥>@b[^*9k_)+9btد":,vхh2>{1'׬6BZ_N]ASD"!UpYD\ua_Q´F߯˺6Weo.҄?q<:9^:Qw~0KŠY~Ak vp&[C8 -M;v:HV] y; ]*h"߷;yjޱwl̝Gi)B${OaPwGï]kD~\v4F~&|Pp Gcr^~>>ʫ9 / =]t'/bE$"8I_ jaOtqF-[]sX?EaYosux'G6fx1h1̻EHKA%e8 | Oēpu A,^i%4jUL }za`Xpxzt! w4"KՍ28t V0na᠍MO=6x2Or?p^ ywֆKB/3~Dh]vwփv|z=2 QHN+FS^WM'@ڀ ;Rd΂\ ܨ3VGꦯ$-{,ř(rRQ{~v} rtjNa!S}To/K"Α0aH¶hQ[75Y\~Wढ़vq> Z]bsZ|vXY; Ş *-e$_{Cg*\77=o>J&no)-n5saZ?q]vlH#WJ]u1'.y}Zns "q[.&eQjywmw59==`_º~$ YZjYڥ@e`=6fU!5UȜ@Db-AߥOV|m'eYQob]38$w 8}Q7uÑҥp9g.M͐3HK3|x`'"?exZ&Hw"īZX0gȽutvJJ=lQձ~iw`}K{=BA;S+}A,t"ah%*S2uYԥ@WߒF+i#A }{v;/]?"ɢϠgDg=ܣF7,m} $c΋C.g&קq4̀` .xxY r JvG-4FdTiOV</)QK5~>03s*=k'tw׽ %!vYww8[nAxX\|H89'~('X^pG-ȇCOW^_kOJok"47D˃o_^<{z;4!) Dyyg皰cmϟZ㿟|\.;wm&wm~+*i! ph+c݄^SdM>''S$G%ڭ:w"Qx}S?vz|oQµ*?pE%9]h EF[[Fa@BqyA]},\;cke8$H,ކ\` 9iܒ!oGJᖋk{8][ƩŌ6lHN(uzK\!JfN4 wbKrǹAy?7]dڭ}YyAtpr81E>g=~+7W]N>@oj4UfCoE׌sO}ـ;5UC & EcǚxZx tz+1!H4r'ƀ(Iӡ&&J C@R+DOyWgJCw'|%Z9UNJvb,AOgWrf!tޏ{ _:P;ahxow3Ja,E8R01hCM.<.4b;  xw㬃3r?7b,:9)$p۝q\L'gq3;qL/|NHqύ G^h  :-q]أB]'l!&⧩6A`<v]A=55 )z Q"!8hDص}8tzFt4~]~0[}s]wA8|ީ,OB L.$06C8o7KDv?w6:ݿg>Q.x޵ڼ޷yptjE 0j`wpF]C@nqhatj;=WWWO.|~|ssz}KKs0W7W_ʁ_(>#+:Njp\ ~ao0}VN7go1; was-} Հ<: &g Ix_ 5DIs "{q P{+eWɢU'2Qڤt*Y VD{ĝ4"QGQ'?UN&B&~$Ev[xpŮ8;7sZ.~I_8ɉ&"Iv3dMf?!s6'\Yt̯/sm/^XL vs=җ>6< qwˋ@Je9;#5Fvv Hנ_9>wxx_ ; %="'Ḍ!Q $zpp7]N΂*< ]S)]g0{sKDp\jEZI"'Z?'"̬)e6 tBȷj"EQ?C2N2]b0ġa1 lyrG}6_Uybm Zp`X?q+@gJiS U'H9.Ea g=m!lOٵ>I`>h@ }mO W* ػJ;^a4+-* DfT6F(p)}_㏎"jQuDUǂpeUSFnCDQm2Ehۉ^_Ʊ BcH3<ߑqzpJ[ZRH?B>/7ii1eG?$~=6|q&N0zVD:']Y1S2Юj 1+" X6`Bȉ/>JpA?ʰ=Q*-ȃ4 wtXlah[hC0нo~3\?B~RBVxP/t  <ۓ_ՉvcJ':E*,Q,q+dD$TS K?>wzzӇ ǥę(7y nג鱡ѥ# y?[D?75GX`z5!URq$z䈾>M"J6W=0>'LJ8I-9$3"7Ph'A1yX[2R9'*%2jdBxIAfp(xq9r-c,)DR:g\6شY1sD y $Sg7$ws4!IMۀ%X>ˢWLOB?P\:#IA&c P6Fq%eh$  `ȫ*(HbR@Uj1^@-8Z`8G`:7!t2q;u0@ZjaήBE X|NEbB`ER~ExR>[$ gl:^wncK7 O$f!! i e2 :,j8|ZgɈX*4"7+kV\$CG|B^?Bh_ikw,h`-{l.Ш2 Brc8-"3uyJk /Ğ8IrXpQ=}/ 3Oef9&dPC=-#ĤEϩ$@N_>t[TZ|&}I#<ܙ #~ [ t@"ez2k!1 HlX6v@>-Q p)88xG33 $%FHtXW5Q*\T.2/óq04(9rpET P" tfnXتB(F1vE-1A !HXH@ `Ø袔C ; AB7+X~ܲ): Ti,,=%p֯fKO6uV~C|PSu#؎vx +tDБ!`IZQE/(!^̪+S-/RU">hB?ޢLxjvI_vޛLd镯^ZBEDUD\}@.`; ,Xm|WcBpZE6poxS%%#-e5'  " ';ԞHk&wSw+yS':r&å!ּ,ޖ_;zkUs!a_Y H,<&*a#̪WӑdsFo@K!|9f'{/ (}7vepkXlT\'5+jg I޻mN]nMdT^{G^ʾ1MP6Y!Rg~Ĕ mxޟUw׹C<(n|ol̜b("`JPM[?@ #{bZyʷ˯hS\V]'lx_E,RZWͨ=b]g{KO %V #H^_PƮ_Aɑ05PM CnޫI¸ /إI| ޤE vWg2x@֮XX7c!F9MWk o 'vpPYʼ^ ;9WYYi 'ӏ1gD~@=Bi[ݔzbb*W]bw}4+fgU?}@z w~ R"g{ ]T 48/h;y(e%Ĝ?}TDgը_!|DQφgDSfQg{߅;$!G/ SGńmVeQVAV"{ 8/3 9Go4@>~C4JK|NL@d=(Yr+vdK0nbY̢V#iyGp=de`ڌvw-oK(u-$?+Ißh`;/.4#FH\VZѫQzĈ(O6!qiR]͝blzf 9gߵ 4֬IеE%\u#{@}I].I>C`Z=BAQ$vWp%Bq,6CS9 {j*GYK$DrDxnΊsf s|yr༬4Bꢕ NGE㔎}'Z=?AFH{ʒJZ-5wEqYa#epS)hxGٝ`bS^D*ʃFB.l@ .jGxFjE2ځt[uaۅĤxOXJT9%dz*GO (P̤nebQ ށoZi$8R,#d0Iƽ#ǀ=ҫq_.6 p9>_:{ZQQm+ɬʒW36|`%v'z)x#g!Y)n4ËDZ@Lj̈́:= Saiu+%*[]NXI` =~+vjH?A}A-f\vzJHl! d ZТò|^=!{Xt2`ne+NÉOPX[=]l3_*c qYm%C(^˵A)Bw^mOg˲JF6ûPk;3<}xnwU0ؤXGvz^ y;7B;䚹{ ua.=-<ֵ"ɌͣB?`SȡTE%cDdűqUswORՇ`L {"M8lיThCޒ?3NnE`gmMSS"Nڭ_&a2)`h߰YjaǹLJ@J.=|w)R]q]{26=J,} "!fRo71OͪOiGz k->@5eTcMe2PJ1T,Z ذ͟m]#  2OE:C2QH̝r )SR"{e}ظSvGUa2xRUeeH\άSi|OS|֌\wFj5C(qF+Mk ӝ-r}|7 U8A L5#P̳vT\2)c=[^3s%^?\۶ ygS9R7v|JngTSbiuq|a *)Sلmk$"e:o*[(qX)yQEk+O0یU3p9,fbftIauhJe߽Uo dhU~3gY7Dj}(rQBJ>e{;=vCDH;Lz^3.r@?S\fiv3oNe~t{ W<Q<,}r@!am\9U~)U%aѲM=c lv|6u s|g"Ea{|G'8} }QF\kNBN#J+RͻЩtΑؿ{j `H FmjՁl865~4ӨΞ-G {/+&c] ,M/=%D[.i{n#o+&<]+.J,dI[."4:ORZH3ʣ~+30z8 _w]9d$$$ukGH8Ƃ}{zƔY/aXE c-s(Ji~Ǡwl[* Y@[!Fʁb5AT:K3^@e?yISj3Tp H B YB>a`.^3p/5qoh||-+s^$X{Kŏ/ }RSֻQ)WnISɑBԓ`PȶּĿ|/{Ӿ^:#e,ߒ8ya AH0/T#(8"^9MNOo`{0P}GZhE@9L67 <GVvs} &#X)e^gJs ˜tMmz(sϻ{<1(AUvip-ll,#_uV ٴ8`Kswؒ}mNxNV]-ݍ̒JJGc-fV1t5lLy( FHz9$| Rmԏ?|:ǁʮr.vHH [Q'D]YTnGbо(ҀM8/?Yfbo ˦h#2h~4ҪU%HYFE}$*3v.#.,:~ +SꝺV]7IҮ< _"ɿIfpdYEFr"|ݩŏ`O(K($S݌!OΘiV>V3i7c =t##L]%)jT ;iJhއV[qK 0)RV1,/qD7)R'Z' AcuKB1Hy< ;q%'IeO֚Oxեi`&ClaK__ (ϲI`CD4j v鲣_ iDek2,^nu+rS/^h?*U !ufjVL(|e:ч'@e#L=gT"Es[Nǐak:{`/7ΐF)j_U6iwn@ZI?7&Ukv=աf+02$ rWhbw馍$˞j b$mșmJe׃?fP3SpH\3V{b=Ϯgϯn+Y뺮?jWl8E5}K 2*ĀwC?ŒNIRQnqJVM6 K򓪸ȗm3cjPi1ċ뚖 :0-v}B ˌ %Igaѫ&%[x=ReRR@j]V14B94*v R8wvɠ,Ɉj_V2ǃsTZqrgi x( edp6LJ?}pYDSڍ#.be70p#.`r`FuǟYCv ^vb }]·`5GJ҃JPE0h*7K}'x?ā:nO;8LV3Ôh%s(#wiOc8HWN,<LOG9jRj `L['8JAiv=MX ,؜ ft FqnS$ؙڻ:G$/.$Ц#yHI؟z\Oor\rs)м"q ـ^nF\QËPъ8 <q9Id(l X"J9Q{3lHM<ڕǢWA#W?yRԩeQI1 g!Egq2Y)[(U-/V Xzƶ$/hi1o% J>ݲ~gD+ >L.qʙ vݸ1﻾3Y @/./:ʅM8#B>{үR}fuFP<=^]"G;y )4J;#{hr~ /{ OX(jiŢ2;)Q(VfV-JecțL6߆Rgχ\H=F;VP_6B83SϽCZ Ȩ?\ěn>Ѫ=ߺ{|+G(< 7Z̠ {lW`T(# nmCQ;X2x]x_2^c&ɘ#Һ$rRV{P}K+#Q=eUdm0<@!=g03gLY$pr]hA-de T<҇e4]\==USe'a۟ tf"L(o>_,,'U> $Wy2W6l΂nҍBu}XZ[R- *t|+ߜIp_HE#jgS|:2^[pM#d$n?-%*%uM_2c*ī -tee%Ɩ{Dvw*0d9v^tW[)QB@+M!z3xh12) K캫6ƢlHOw)+yJ@(f̔|P⫢TV S#|E: 9[s6fwiZK۴?-g+V6tp; yQe[1Pt?~'y : *QjWc䡂V B%j'?CV Z^Fa⭭/tr]x3g/A;6YQ ]߿Ͽ?_?_~~߿?߿ ?/?xvr7o`/Eg#W__0~~Ag+Ο_q7ׯ~Rh:Smu@n_~naZS5 Fp8hƽU6ܴ>EO f)墢?̇a;W/  eicH׌ Ao =xl>"ST􂤩7pR921Qj?̴'ሦ -~T8)_1bW--$ XׅBV۽~{UT'"(\lnh X'Z8`+wE2XKS2asD׾{ m`ZzM4:)ʱeIIimYiZS"tI bN0O}x,.-(t(ͧ`;}TR92Tʠ#AK1[_ri<ԩ(cU|"9@CThh -ĒҥZm6 }B[,.&Jѩ,xlq(k"fޑ rAͯLlg6Mdȗ5+E[tGp8#ZʵH]7U3;:&n,$4[#Ɨc@v.  Y0c-.V$.B,~ K] ŋ>uV#WC׌<җBhjЂRJItF6!Inӷm޼>]VrUl,FUԷI eRo(6햼ngPk$Rd&Q=1il5F)@sFlޙ8c.; DEn_jĴeSzGnѳbA'@,A+b5^,ɽC:ͫl&N$$FZPtDsĄhd$+y4DY 6F^eS) pzb9le] \_umx)gߏ;Xp#›G)@x(VJ|jNW]:DkE:{RE(8Z^c-Y%'×@$-:D7{ xlOxGY':~Hyi[fُ E#2CC(5b!d3NԎh;C"QAY)>b +^]ۻ,{JK}܏UhAрEpm?i&*3*' pIN1JJ}Ę(nvpmBU\0]2| ;ab Zi*`ġ^d#_*F,)$ <"{%"IEU!9"3BWD!)pGpKeLk1}|)u]vh\q8fC~MQڣߧhWfnP`ݝwZf^xUKu6?'O324L,i(i_JISvlNDBoA5HܥӍU (K6cmd^̩fk9 DfAϗ#S (r 5dF4]pqM塷j§'FT}fɎ45CsL*,{Ie1*aNgq59#6Ji[YYE>-F{|RkK>S` TJ6DK7vr2$Uil\_ R_GSa2xxSgncn]ì5 GoxeOXQOC9"LRk`Dg٧VQcmZԔTM!bM .F}t^iVn) MLx1FBg/X$g 4|/ A M;ⳔA^şݩrG+Ȃ_ 5W 08haJAb ,)߃,8ga̷t,J OkECe3#ZKl1e01ZHNPf#Kf؝H'! u?Yz.HE8-#YS(U[.Df?ARD,5LpS(0࢜i^}$"k6JɸI(1ޥĉޠKCe9!qDW1x~0 '{3U=}3ί"`G/PO7>4sR-1?D5jsc<>!B P-(cn;.֚ R.=7 j׌ JV.˽"hR M(22Ӝ}*|=z17lAGTG0!85y& CHa XL0C ~н.qY`n$` Ǡ6,V/u02`L]wGd ̍D 6=>ՠlЕMRޖr"z endstream endobj 24 0 obj <>stream !*%wFu_,8C|:Ju=s>?t; ۨ8kCW0k"k[j&WڇCZ) bZ)~TO bj5aEB1όn@ѭbjŵݤiBWY&1. $/rWt\O*F[ :C)ʕ{yƪ,x]!XCsRޱ`E":4w@;}WEW>")MҵXe܀+=Xv$ısi\}g+)W85gbԨHEnU{ˊ.}׳VPND\B3GimVRxEf9^KTOmyQcM"6vD{)W%+PadʦXƻNE=U@~]!z/P5TMEz,w|W- ǘUģ/=gx /Ͳa^h`H]3;L/zupaX#22ZJl.]#y?D PEĄ>j>x*m:JQ|m' T&qF *_G ZQO˒0Xe4Pz D l?i2\v!,)ֳ5-%@,L&] e~9Pz:A{.]i:ƭoy2R[9!1 [1g` wPaKUXW%f?gt_O(a`qc\P͚ۡg0yU%2j+v(صfGaKp;uOD$ p91{~@,^Hf+NB{G]U+kh*kD;t G%٭F)b?& zbU(Eҷw>'όp}@oqF'7d;/yƷUaX_~d&m`DJmݷS7?Xp<XJI鹳gDp&d6}ut{B.YZa˃P,`˦ĚUG ZnԃJa҇[9*։ovU@vyijz,}g\stFAU]Px%0@#hU2=cp'aAI_fF g %o&z~׺rePRQGk~3 HQ ])inY~qS|#8%6\_3jC̠mVL1QSO<%)joz> ~1hC_ȃQFQAT!1ΙxXTDaϒ8Z%f`~UI'fzCR)+"P*QWf蹲P%w4Q+k箉D:2CH]uY)k:VcHەs%፥t2PEAɫC^#JGun5th |=Lҙn6Fs^wq#DU446EoIWyJςGig7e5=~alT!󽌉{Դ(*I]Z++W&PFbpFv<^g1-#ϵ+LX]'\^)Wx~y0yT3.n7(@u"Z5<£,g 5ثR>|=jSl=!ψfռ(#G6q}[$x 1vtueEN?N`Y C=Ni"Fót 5"`gӰqđyrr]g瞇RҢ$x'V0L*ksQxs.JiPL%SRiHH!k{\Z>K"G3,(S{K-#bȌe! bA)*=2QsXهs Uxۨ0gPZ B3Z|h?ڱ4jF[CKlWP|ђXw?\R>}ؘQ`(PGm@y[vZܥ2H;3yEVp ͟pblN";R+ ](ؘ"-/J_"uh!^,-J&jwJk:⽩ o bVWNxotU2S+?FP{+ÕiHb2Ԕc@|xiPLM }z-;,jvE뗍ÉRRZuOY.j+ pPev,t4ǞV:g"bQy?* I0zlظz+Le+1O62^od|g3NZz6`euq2q ߔ߫G]"];;p"^GC:Ը:F|7,ПL-] ZR+*V BHlɮ4ECۗzL_-?*uݳޫF5:˻}>eD@ǜ!gE-f㙫קQsl%(mav]9y:v)$0AwZ&ᎍ`Lhs g:q|qNSoCQ}3Ex FWE'v^Mh~ȍR9&KRrt ehH5` ;V. цb]]L<0k! &6%~s2džĈ=p+w#edpK1ouTZ /`hvig[HE^هc_LI㽇t"R20&tI%0!Z#KQq_jNSʁ1eD 0^@sAewTx_Abc(?E:F(=0(rS"ŐqDa|ظDĨLDm.HTO }\z>26U<6πt~ԏSF~ f >Hi,I8QTh)l /@a/;&\=A?6`eTΚ7Zh s\xpviRzU$u[8x5U-ND>QJL*,t߮?ꋾg~'f^z39>Z >Fݠ5itn-gmX #*pk&W1pGSn>=Lct>ψHW $g鈟Qe}hi] UFd//:(Xw) a$;j^D"==j }1S7:Q3]%t\Hp'i.QhKRy:"E>idzB `?쀎Jz>E#:_fg&^];>~ ׆U'"+v臝qѣ#i9)n](!%x*{>*! bmWT]c.o .[]Oaq"F%bG/QڥLN+$ %-&su[IJnO.`QGLP;iB^  yVB#RA54ɤ0cVPvGb@A*svpr4<#!`-![E\ |MŶV"Q 1p|:ChrQê X&33)mG!( \^LྯBq'< qW&?}褵@$AQ=I:ɿoBkZ\-(QBN]"eT#Qx5ޤ~=&uHuy%~u~osodlHv2>_AY;RAo0(N@+&e2[fyǏϨv$sdat=ok}X0SEwtZ"4 ձv=HGRԕ#~~3U/!%{5->ߣٽ^_{L39rAv37 #6oOKΙ:1A +`ϒ3(}4s2}U7)KM0O/|X`; 4,}CcDS;f9^:5GmGz6F:Iו2 Rl)v^}wU.J^zW%CƗؽd V! bT|E +pDBP.oB! =|vb̏hw Ȣo*fPUU;ѽ>w_ !n,VYA?*4 6'<eM\08w"l9c t9d5 #ׁ3w9G  ?277l#z[6#;녌} ]پ՗-\ E}>5DUȁ*.}ůwBmX=:Y^1dP2548x9w|-%NBalZZNHyuHJ 1Ec`#-꒲ܴy\|:c){g_Xv 'l(u)Ӹx$ SiYW+pj4P|N U\ 3^bkS{xaVoYTpXTGR{Ð:25c!<Ȝ`)vw9&=pcYzߒ&(CM'Mx#*W)S}UWXq: %w8R%֐? jvܮ]8a7pٻ٦;8= Vg睠 Zd; Iɜl!޶ mQ>LR%CP`j<=f"sp ) f.x9R,.6wB|I?MqRweGάFl,T1tVh]ϲAX(SH(L`̭|78472dB]5Yk=\d O ֦Ef+n3}C+N~:sD-7tOw$x|j`'wCi[:'o9Էr*\#ankχٛc]L;cBY !eUJڴ*Ix%rrWpƏ]%3{Z 4dw̡2kg؇I`N^|f`M_'Ab$P1"̘s.a-ʽT F8:Wߗxeԥ^ZZbH *-W8 p*ktEYJV,0RG 6C\k1]Z}0i053AL::k9C#Co&G6I7oc‹~X_i$Y:U)쮥gӏ* rZCrw閼f,dߥ>gOf>* .7 2唓^.Ӵ& 4x* 96P犓wJ IAzoeuerzgCZ\*7">Df?ݐʹ^PIThXa]Sg91Re·9%&ŏ;2+&S5y<^|Tv;7PwZY!,qTҬV(j~'2k ж٭xd+v{R4t+]ҔL[l+(ati,-׿jY?>\04&IXrVwҩZK;M齣U쏄lMiYQ͍z籭*`]a|p7(یS @g'* Pl`6(F #[ZEYuԅE0_1ƜR]$E52V[!)Kca̝ktoPA8(>!}F@g* =BB2f?g!I<_ee*onWnŎ-r`G/.yT9ė%i諮Vb6čx:>Qb ;H}N"!m: ?)6PgGtE*s;׭D[Ɋ2^8μĕ3lsdކ{s*hV:+ݱKkVVŏ)@HK:/ GIIóm{VmAu/M#Mg~{>bG),\_f0Y oV;꺳XtR 4(+. "q,.1]+I0r*ef_% ǝ}:20MO[@e$ZZ)t['x4w-ԅ,UDO&>1ngtFc`=1"Job­Q6M1@p)%TF84SUsd9)a/ QvuVEy!̣Vo=4ɰBA%cZ)( ~8剜h2᫢xu k >"ڙ¦Ƽ_gmZߣ嬏WL;s/;IA<ΟJ *KR">( 霱7$mC3\>d=țAzh0M}~2KygwfoVԽ*EXAnxj!V7<5] ՕJ꒓%;f .=&~#U;^8!ѷ{={IJN4V,A(u |FcJ(R[>aʡ'GpenRʞLswV3UR%t+oW>GF(-+K73ہnxg >E1ǽKtT=_/_/1GLJyз0@ o~`R gd|{.Lݟ߹rH|^3QQǟF>+ k֭<&d/g4}hFC-IUS gYDCr~țW2եδn:k͞jQxиIXy1#6s< eDbkev'J9-V2d*+jBnk:`{\]lzn_>޿[RpCSTQx *Pi#|K!P˱(Ky(2Z OP< _-C7i{Fs;6yKUk] U Q(C7/;E,/b0NLfUw>ȈkR"D;JR=!+;JB.f.7RSvm0b~(sk9JÎ/(KFL5&)+4;ߣJOy᝟%X9^iNY|Ŏ %\P0T9$4htsc(]#&dz>w*%C$Iΐ96XKRD#;Ϻ KRc 9VNH 4ӣ B Ty/h?E_ވ)b ~4LNJYCu;}{*?:e^hj@oz1n܅>'R,~7gԪI*uA2J{VȎRe>+Ni[UoZGZTī+`qk#pn;GUux#gUIfuF꽽%Ac 슬c ۪Rë" p6+8UY|pWӥzJ2[N. m]T̊.bJ"V=G2 huUګUK (p}Fl]nBQ! i<@/ʠ1^KRUp%vg| ^Tl*D,4 fk:fxG/Bf/@g3Aشb *rU?#_&K>-uQ2N! :2EfYj=Qqٚ[-{Tp?+@ W0z ۱ew @W~DѾIҏ9%`.J_(luHp6 q"m~ɦ2m[`Z؀&UY}^K.[K`6Y|C;Xiγ4Y0"3# 0B'oNzS"}s"~tWd!C!oTLWW}G[Y-MR(+쇜g ݎ_N+uR~M;L9Z%09bQΜg@M\%QQk.4߹3]rWSkQQYD ?.-Ȕ@kNJnnPũ>,ZJC:CGU1!DhIHQr+ xf`ͦ2-K C+۞"`R~oCKrm?+l0RXܐCo_RIph%{ m9aɟ͙:Hg[ُ:?V* S٢ c΢k5CqBT\ӆhl,{+ŏPjϋZ?({2X.^ ֔ܖz%E&]P%lE.)dNlTI Iq̯`%f0sŤ x6(Kyȟ3!#wD)!=zfowI7tEne/P!뛆?0T?dp w971ݒCk,*R2J!3'R)I \p+]\|W=IO&X/|&=>s>_L/P'ؕS:XsD+|3'GȬS]ѡ_ Rԏ 073Q["%V%yC66}ckpg n|j{& LS#3D̺ꠞ{&rT2V\w^sTC{,|$ib_mQI_t[οRSN!&Լ!ѫqZy/^$NyF#Hsj!kD A@D}@3G|L Ma?d]R7,sk9f݉*I/,Qem$DΞ?]ٗT.!. K}490-eҼ_>1uUqٱe4aP`nc+ 9w4Ki`s9р w[ՔV7t]f 8u@ެ^>zRnha$3-H+ƨW1߀ Je@*Q>J׷Xg ]Wsђg3> ?ˀ}k}i+J73?[vNa6y>7UvnJBsg*_P=?'hJ { ;Y 7Di;/;FCκ? nB 0\W{x q(G*B ϴo`t˶g{G>30cNQG]5$R:@wrl'+r͚ު_jυ3%s-eEϕEA|ͅ=|lP_rh+]}Ҏѝe2i1MLqMFy2knDȱ7ׄBBE݊گv-K/kTM5(׌A$:kic>"fY>;HA݇x4EfF޻A'8]oPrAXw>ܤף΅;xa0Ռ_a+UW9#ml1ieM3['׿hr$ZcSS9u+.z:xm8/>sda[9[ URp :wT ?zH.J=tVnJ ͋\ S_/5.zѝ14=57Zr=eرG܁2p?C֣w~Uh* \Z+>>7NHǨVojIwz`*+9(o-h1" )ɂ鱒tʯX#ܖ/0Jd s w]rG;QGVF20AE̤P4x,W?LVQ7@ PSםqoD!q%Y]3_gDN>)F;./z! 64WL| VhEzU݆9t璘xwè =Hbs.soα)},) %-7I=wpвNnz:ce][kPpWY%%2kk KBJQnGiģtmC.lM@Wx`rFy5F[>8f(FJ&Tӯ׳9"Лp{4-l"ݥʰ 0KDFȑY#W|~U$4XujcGw1GO6Y *h㋔:&clJ*hYXOANB?.j)f㐁 &_Qqc\;nZa2y48}Ez"OCGtV?CR"Ρu0֡FzӁ6|F=/D/ofU\,۾F菺U~#e]oQk!gqGeVK1үfwI Z-_:åRb>7JQ1s.f{ H=Þ剁kWἧzgno,+aCE]纭F}龊dtf3`bٕLp83,vD{y3VwL@1\XIzIHd'0&iӿ:\L"a"ʻVP챷W3fKڼ}$ ;2SP;rn!)U<%Rݕbq]זKm;ܣ|QZgTWσd[dautn pBڀCy]IԹh\;W]9LTWKH˫zŠKJ?wM~a Ł7~o;8BiJN(ܶH<LjK8WhJ~1" [tOSB7iv+cy)5kqzv(\3ĢqQ$$skFfӍNӂm`: 7*\w+F*m>""zeb`_ S _.H<ҖrBȃXP'E*nT6(\"4fmuшn)~;A~|ROOѥ f:tT蝆k #·NT\Pt{9n3 u~= qhaVD>^UN*Oql%9KyDgH9=lly-K'ZCjc N J SE:'kkg|Y>_ܨjd[[@ok|a\I t~?XRu}>J.UIB3cBHq?] s_9c̝QBkΫM}b!1XPj""{b2Bfǚ1)* 8ΙV> ʂ4[6= CBmߑI~ˡr(x,pZH10P3jG2<U">q\QHmX:+ {4G L@R-aq#H\YY#b*S!3`4TfZ+CNǘO]c8nB-Fd}o89[!kd2ozįzBm`sJ+T@sɺZ%ciZ!,󀐃Ki>1O2YyDvw(b{ڸxżY{E#h|Zd zh31/*}H'b$\wC\}.cXJX[0`Ѵ&hVUăG`xn߾`~-|k! 4  zI7V \8D١}y*N(t/twHdžB<"=lGWFDi' qWZ3,'.-{읃 }B.F8ڡ2 xHs--oWpyֶV'_GSꥵ;ShBwi $<57Q"b1&ַ{5uO dlݫHz{Qs^'䗊Yx8ٝA=%L1{lMI}K 5H|<9³uDg >5b/xU-)R)_<^뎪'ȒH ὨsI2LU 竒$7z/<* ؐz&RE!fj}x{gPXgCP7R aYە< Nj*fu4JA|;*P\7 e*e*wh0^N45BfWԽa\g VԧTgAq]?Wܱk:Lg~Ysq]HQ'ވxa _p` sXH䷠8"1R -&kh>6rFpx(+AR<1ڙ.(.n-U>i?jIȔ z|")J5w*4BgXG|+<%3W{\lYE;3ySC%7 #HNH]`(j8<}G> Trn H۾X/w.74C7i|D -Cט#& y ٤?;m'2rV+y2I&3Y%a&QæY+HjxyҋJ[8f.CB'8ӕZ!֚4hqSv_j;~~HEE[E 24:=]h[x(2?Q.XF워XdwkelO}ɹ>_ a=i' e20Vk Yg>ؐ4ާ]]!$mʿW,{K㽴hI\J]lHsGn wEYgºU޳}(4qPWU%weċ?Lj޵C;K񙧅-&*}W-jη(w{,EG1֬ gМmyzxsdߴs $zw;(umC_,б`ͅsK&ez UcnI(6͹l]MTY7tDȾ^y-<;UC[D|Zό`@l^/UWdϾT?v&k !Qkd'{`M%1#Bg1&-}w|]o*ȥ$>?|ԓ<Q>>${?t>?j#?Aێud'T~: )ʣꔠV:oBz;p~OSӱz]q (R v-;&. W1Cqú_?Yg;F-.jˌV +8 ~Hy\uŅa$6%qXQ J-.' :sK_]7{_܁/|%Q"Jq,IY݈gh/kLgi zLѼU10MYbvtO}(@aJ||g@ʨ k>$8H߫;w" vi.)Qs)(#z>20=G2Qq.X0t&t3M:-CGw1 .uIr~U+D<3]@}*F)e7-2q凘X\PfL{ 0~I'05|c~ۏOR6;V;}?i"lS=B=Yis Sj:19zK1)rPvg"9h*{{UOdwz 1{{QgL*Q+d?}a0.Θ!0aKj̟knXK M鳒o#' ~W(BL }d;xj5r jgz~~*L[Y}@~J Z!Wz^/rToMuUK& _L_e$pGo˸TZe"-e@sҦ 6tzIB@-x'M:v_$ __#glMͯ|z{} r_URJ}x><_MKDj=9$_?J=vRL_缚H 1o o(]֏ ߃WwiGe #_Y[.fGNvʈ .{v_ &^_v=?(!NV;*B0c%3kD{jb Gci {SJr۠(ґ1;եc'=!*. #@g_V5'zfW 1.r߃W+`PWySj[]ýPisKIB'h Ygm40ՊtQ˦fގ$#R\{;C ~g_-dG즶\[WpsNd'Ȉ6aP⍁/ 6Bcҍ)D:,6]lj.Öo6=bۄ:9k Z7x}Sa=_znx+ @8OT^cї8(S져x9 ,{W\̌ۘ1ײDi0t^a#̈Y;YBLu `, i>㌰9CR#LPÜS ((ѭ71뛳f ';H%Ȍ.Lƿ5_'VmBGU3)i*-ٱ"]4=d" eB$E#},1:Db@U}OŞ]1}iXH.F3Ń`-_/N-vk d4̸Keאzلׅl †a;3?,xȠ@gh94e0YaAUN⢿HdAm>,{zDî pKI^ݩT* `0Һ*{Hi=ۋ:;.ԫQ5>ϺHE9Œ͍rWdN7D<ļF@Y. ^ @#\"1!ްf6ϒ9rj%,M7Ri}MqpTtx*٩J>-n,A)Nt#Ӫ=Bik)JXa$lC+T4R ܴ }i/n ^!cAEyDV: t{P}2ae/ y=Jq~]ϕZv +%}ݪsP-,69}]T\'PxÁIh}*jGb} l2y53m'I0pI ;d*X3YEu= ~ 'F"t#/; }w9;|Zh>P1?MŇܪ[_0sJmP d;b8Dtރyh (8&9;6M;aUm)8.:/D"2҂AYׇ5b,Ƶ_q$BݡuGlt1c}V7Fc8k΃@X;udd_ Zx?@[8׽Gngr(il{\ܔ\r0YkW)׷F+#f57<+ˁc[|I9%k]LJ5pRָ?]$^gϖ{!z>_*X2&dmmf>i欫Lx2& XfiI\Xvp0w~U򏯒e8ӓYl {ֵGe8QT_đn l'"M˟t SÝncgݝI Jz}Ab!Bw&*@ά'`^$_u=f@5z&RF>t(=nXsv$5!* gH_{.^IOA"_WX!*{D%}gR/1OjyPunc]夼VϬWP6ifzIJ\ \ƶT;rt,hJ[,YYoR;*o~BwA;R<~VJ3Y^cgٺ):Sԑf!PKEmh#̃R 0Ǩ~>}{R9MOQ],ܮֵNgSf٫C 쪲gqwXOVg|)Z3EJ0rAK\ gs_ŨmDi> RHQDfn3y+9{E!yl3 mR+,[%7MdlweҲ9կ` b{v%F͡}߀3T&P`#W2(ե\"OwIIK2yeSGtbt˔F.{]ƶ] P]Fّn2>r[#ݕj0pO[WrK:*Oy.2ݑሬVcUF_Y#zP=rWtҞYX~WRt4bT|{&+^JqGDhåŋBÚ@84c=?h7ʒkÈ^1ԇk{Dr?VW<3=},hY#'jW /3ɡm&M);GH>q=}k#L6rklf9Pʵ0"y){o%kWJ~@K5jt?=J"gXQ# k-7qGw&RO ׵z*aJӺcǼ:Taޟ̍EJ`KZIF06-g ]C()P ۰7/1%"0o)Na7 .bDuGEbx:y=4\\h=Y# 0!ߕmӑC_ .*㯯5]lȶ'٧!Q'2Ǒ;倠⟵1ZyVÐӮKEypR6W*!&&ulC{TFB*EflYH- .5:#&XwMhQy(qF9T],]*9Q2 ܁lH>TC m˵*3cN9Q?>Ua#06zU.aoŽhz/c&gy7UJp|24/ 7> OUJ]lx]Ekݲegi NUzDBrH$$6A딊iIKBK-r5;< $ay̺4ꨪ&E]E,I~ AHFWQIMVƇB9|z8NZ> u5{鵐ZaRvQ@jJL) I\$ȎƧs;k XRRóF\䠪ʿʋYC6Z.@`W/we"HIoFWf=0-/ң+jT }t%.DZ4k?!|9r ȚMofj|ŽhT̈́,v젴Պqڃ"E-YKb:cZBR6};`Jmq˒ً:[*\H]Ô9hȦIڥ^KHC?"v4‡tr3(<0v m+ /0!Q|%|L%k>pXM.~{boG ܬB̒ &*~lm,Ica%154SɉK %C*c9EZ}uԨ_ Y[ @?W(j_Z#K!h|ݡAg-tn{NPx C a'd;zƝш3tq$r;"k{/~rR>89K +Ap+EwVB"BQP:g]{)L|z?yʂo<]8|{h >`$kTtH>L2PVT_*o Uvmg.V"0lIb;Yî%_z/&vl)#ܟ"ԜR="s@$fфeV.!WȄQ:Qq!0{w饮Y{Iz/>/U/Io\<ꤲ#A{S_MM鉙R}η[gףU!۳F#j.+}jP*6^jցT !ha|zmjĺ)@2;)ζ;MDtu,Sx)pqu]]7"qNZM֪Dꆘ tAA(t M@Gڜq/a6?RM@W5>hrnowp?=VPͺr{܇µ4L)CP)9Eə諕N"n-> $Vـhx/jP)bH)ce-C#}K}aQWbR(ٞTb o^ƢH'Wܷ5P33^WHAa8~ 5¬S A`C(Qb+rHsJH!z[=]u=֚%J܁o"-?s :b+5Qf0GP!=8zo@RA0 zcVԫ֌ .aat,@tݳy $~?!\Q7&~uE~GJ>~TdxŨq"*jìohqg)Š4AyW)YϦA顊Վ'(Uy : TN앁2W:~q{<{ij _ЇXi#(łS)/ԟ`X)q3$I*%g>ދ(tv}gr_g6F9{kUoz1_K1'iZ7<"4tTN-<֊Y B ww,tvDS!~-NEKI u#ALOk0oj6@7 8)ݦD"s$3)ߦ"Ş̹1BmXacK_P*2(ɶ;@JEB-b "=0I%i{o>8W/>P +%rp}+֜l j]qW[?A:ؑr۪HOd(NHUNlU1$2 YGd!h\Xb0ӨVTT->QZ2/R||k>pu 8-yM%Ɋ&f{o9*,4:?*>zlc <&S7#TQs=l SڷEq}xK# *꩹;m`Ul*:]g.g}Jٟ1?^Wǒ6> "\6.  ծJih4Qs`Wv;fgh9rq aU*WYĘ f7]n찀kX ^}M@U"WƬi|ؗ4bS2 +憜c8ZWhTx0Σ$S[[z̢ZS;ZGrGq~a,DT"0KtFEDj!޷G$[ ސӷNdt-Ia-UmKZoZ/~dsܹa/6B .sXC;]Rj{/DZpr`r ) q]P3Z@a{<γ[PdY-OT51>6%|uk.Xre*Sig3\S(*#?b|]㈔i(.=>|zA]jЊa>XQQgruZU fyd`b,/a SD c |aG /;G.t^E<|UГBB!>҉1␯\Jm (%I2iY-=k>Jٜ/8|U˰æz)z#UnCr0 gLYNyjHM QY@i']gʖ*uЀרbS3*iDϔbR#yQ2H! Q#xnZ: X =G4DN-h&:WUfZg ND$N!=.|hޫswMC3M_*R4i<񵭃.QޠEWVcUTM ʙt,cQU5:֫^>0!&"Q1XhQ/ڢxE+ /hlcW BW,jQ=fq Ҷ!Gf`)nݐweE׆Ԝliķl"!+4v՛cLXb^U#B:(tAFtg2ϓ& \ߛPߴk nקQ5A ۮO]X7;Jm^n)bBk}<.0Zs?\*PepZdC[e:ZqK\:}`ŐˬZ#%GI4bG0w<" ]?5 r,UcZqO?xKm}^ vk_vNU)/2i/c"s|z8wJxˬD3:gwy-UFcI|R`KhExJoC 3cSh,ح}ԡvpEghզKs ie>o/CJʉ+řwݣ.sOf(q MB t,0Os Ňpt;p{3H|7# [4?j46oH'5 %c}PfS@BGšL[Ѱ47+g %&g9Hd־գUSGxea O= {QMoR Np_ 8Yή:tp=zy*m nQ2M,5 VkjtLl%ʞ(jͧ)(KXAiN%j,k> :XHL9K l*]"FlV2,'ɩovFAIaC(7dcy^1}F'"F97lKa \ Lu!,EMbglfA+߹ {/emJ5ET rf`՗1Z/f4{?:?cȧ@1"8L~>qIXG` 2hWPD~F=w:3~fz 068@%lO5LbM@[D N)W9Ε?A@ۯ=%JUe@ϭH"-B$!IQ$oYE G {YpO}%C@9*&##"YTd8үFJK"eՊL{44O/Lͩ1?m-":zFAM_%|ȸbM(Hv~)>4 0H45(- V׹GYCH3BxBɖf(]推AXNqOZu|5RP(<^lq<^RYu$粒BZwal"vx>Rٱ[) ;"E~#-iߏv)uqp5hD9zQMàZUuXm<Ų{?jGIsN` Xl^g ~ Rg3d{5|d48NRU$U]yY퓆(v)ݥHm\JVWIGPA4?kUqpmti 8/qg_ZP? `+ WUODlhݷJEڥ0>M10ZU8EZuʔDac-0#R6sm@7Mi{3f6vDOA Ft> 5Vቻ,-aO),O\{M@Vs"8#|Z,$8fN{π,b2pЊ{?>ۮ| T.C-ڽ$yV~8h*E٥J#zo{C>Ak}V5VU sMLsdzubq_w z`qJ_D TNO]#3N%? A>U/>9w|~c1=&)Hz gO|+p * 4]!QM17F fQVw.77IV81Lgg FߥjB[V"@/='[+@-}qV=W$=74+Odx{T51T2,OXioaTi!>?ǤMq"t5➦c 7fƕ Wި}hVbʿgM?zxt?G&p 0$n1u*ls:"~qk`/>0(̲{5h)͏UإQ{Tq4hie>5dtw)kblMEK\i\@!$,z*/n\J?jRԻŜ]tO pl&@\Js;]}I>> ղpM˔]+j*&DPEVIY@Mîm9/9Z;Cm񾄒|`/ $ .RV:lG [D6iӅsz2Ǭq ?zejf,ث:UCm~YbvTJO b-v8Xo/;pz™pbΨ!1 *\JuON[Z 7 \PZ0s_ǘg~?vFy*f+*?3IS>2I|lѓ3˩CQr߆/*W}+X^׵")d.QC0-^1C a ֟]ZӼrΪ(e ~fDǔ1L紤buPs+1J7~E+AA~CԠJx@zx[PBO#NN$r/@OV9PU<ۊgʽ0dqMALv#XQT4G!~5cl=Q}uOvYuЙ u6;=3 0$gw*0US3}8}Bf4mjj}J mtNIY ^S8Hfe$gN4*Jke5#= Ytm]r%ǭq/aD];aIO+9~p rRqSbڨkOݣ/r?r<φ{XHw}~jA##7l*WՍ gfi׻pK#d%`2Yld9+t+l(Z]LQS?W]B_ tβ1@x.7_+\\^wP\>\u`C)6'MBA?0BD"rB4-HٔT;x@ZT/Q9b=nOi4qs)gQiQz罬g+Ɏ#Xy$V|3deMzN:@i DM~`~!gIHOoqDdh>:Ww+q ?U@f}䦴?l}H6[uAҾZg:aaywjJ[]+Uhg箖ơڹ&{/h>7}V>mSv:Dn}KL{#d ̲mN<C#Bw4mOp5+eL 8@YClʫp0 !@-X|ڋ]*&vc툛)U~fVa$(hRk IɳVKIe[{p(;`M.(! nſ> {Mүt0iwDn;AHQeu 4?8'pTW׈c#V[2JyG9_ɡ9lc[QuNU Ǥ5Ǚ.DHLDegoCe F1|g);0(V\pU~;%B+ " ʧb$k2^fuBd@]ǭl뎷Ǿz^|w0^A6)OaW."q]NoȮ35dRQTmBpѤJ xVm57 #H]'{뀑BZ9 M 8][*Z؈t 6X$U>Zƕ`\W X`;3kF\Y'Zx!뮲|r;r =Ia{?MmQGއ; Kri8\j6R&Y[~Jg}sӪ$ä#BfS{a 砤ߴ\LH>R?˲ǿ i/SU|# ̔8FƝxaA|=Y̜9^̭18Jmh Ae/v?%NO 琢PK["-Y"忾bYwcIz@+5hUB25̦vŧ sHg-ҝN"k ?LLJ2#٢RmAMlmJoEB_9T[ .vcƜ[ӗkM t4X_o}|D&VTѲcH\iF 2 dؤDL#6}^<Í-*d\j M?ɵ^Ǐ?6DgOJPC=[9^I/mP`>ݑy3B,Dk+:ZZV 5{r"[G'gR=ߨL aRa-VHR՟ye=RX|?*Ob TYt;,he-zg kR/G-1q-Y6up/OU5V S&3woOE?7#%e )=գvrZ4e})s?2%< ZQl&tN/v+xNE?f?__RdR9EYɮ!WU2|V)LiߢO+>P\ۑhh$Q`F1@*}D҂2Fyaa_ipooc4ȕ@ui  ɓ|0MN"߸j9أjrـ,xJĎK0+λZTD+Ь@V3PH<^V˙L'asJ~Uw  CTmC779qgTq8@^LֵṐu*1?4G\~dk2BV%ӛ}[H1L^ }3 hMy3?A(ZmZk^zf2v %/swWM@+bv?0 rպd]!__[v#oEf)^|*|Cr]K١:2?9؈@} kGgߖwC];ZOMqAn*xEF3I7Z!E@A}x՟d>+ XBVȪŕfp\+?v~wF+#$r8j-KtH*]0"OVc^>ȡb) 渽&#n^飰2/D#XWĻ3z! |w2hD@ I@J0xs\he[ 5*w`fc?Őo?'*DkHX !PzS;˹ z&䑗y 3'*4H(x`WHj;9pʔ0`åEĠ+EdBEr8AI4yJl%;~@eNoQyՂ-BYXQ%U'1;SdK7cT';Ǭ~ ߉ĂEt'׊ r^ଇ|WEXp'[)"tZgcdF.s&E9VNtWYu8EDloor'2J.kMHؕKSri~? ?d=kݿ߻*KD> BTDrQ`0~@4-CuXmr퍆Cm:QIf+ =৔V)a_h&@S&Z/b378E ViOXD@r^es6§ m|R}j;a`̹]E.c`j-ID/_ѐ 뎓Z>(UyXPV}10n829khپ~N5َ4[>{_01&N!=G6 IVqJeޣ;svbC D\Um5ntX݋Ai(b7D @k^А@~+ qUBS ZHr4y7/~L%ꮣt77Vs4q0jIH'=_YAZ-fMо[f8Bu,|֦l T;&. ?KpXQc Z&D mvDK?t2ƒ-eTc{˧r%xtGӬirm~&{e<Z؊rh9:m۪#FT8>V5'd~NMJI.b8V%fȡYiwyvz.QtA_߬~Ub?X?)^Eií%Ւ{A>GohҲ[N*#iYWU$iQ*EGì#TNWUÄzr[g.;̳| DueMmF-rL8Aw71Z =[\^CR퇈Xn#O )lc"!\ZBs*VEV1XlXw iJD4|Nŵ!LwBl^.ޮg%tCVuų z*C=b/㩕C0hܾ@!%80>֓|@V}08Kvc&S]#WGr\k>`Fx]c `hByzTլ c0K͜ȹA}pHM|FR˞[OGT6zjB=QFB.tWx\'!l,QvR{N=9Ȕn#YjWZX 0IMዴ*Ոf"uJ7(I 5bT!N UkFuXoۆ_ _r̄ZW ^3ZCfcP5p"摚Oo>bEPu&gMBRgìXAS%s Z!Gp>AzU;.5bcYENM,W%C웳A6AV7y$aR uEs-JgE%~~wL~{KI_'þ3l-މzT(Cس s{C0Q 'ժ3-IE=1[WHu-^⿨ӟ(܊T:o,Z^MVy`e)AuHDul FoW'tcx!qD 5vce%ALiZ-;X ,g#g tԣAw u4L9 Y]qد JVbDxAOєI(aZwؕ߬:47NABJԹʚe(bvVBftY쩒”wcW~ e¨xݕ,MpaڂuetwM423B], uijlè'1s&ҩn\ߞ5zc,/GH0$o!uN-@lR.%;)7 oEm.~F /o;_ye%6ٿ0Ґ A4nO{~&C 0A1-QfFO28?Њ'X۱KLx}r|*sMv^_Qǜb}S( V}UʭKf,UJƻO]pm(:}*`MΨ2)sP^멪&Б;в`b>POd` wl"%2IǖOp('%}nJȔOlpo)1*?,BޘT*j{Hhl֒L-ϐn3 Oe6+1%P/Ÿh#ۦQQgfdvTI?-Y \ x4"1S\N<| Z#p"EGm]wƮ^|}U *N[-i1pP1&'zBm3YtϝL@U|93u$ rg*q{%=`|zR2h_2SKS.|~*㑣E|%]MNveߪ|~h k3"[Wd:~u`ʃա;7yO&r)?K)_z-g^#@Wн ykר/ϛm۩o/g}VgTn0)7C"hP9;=O㥜&qP/H 6c0J3!O` (GN avPUɟ]%lĿ痃q\ɢ({Д-] SgV!rCW>Vc=C Z^W|ӏՐ@%yXl>=1!9iQr>W'E>Y ؒMQsw͇aށŸ&<: k\,C;lf:?cek:v~GΤva$/(:'Ojot_-A=bEs1[WGvN/c9L:=RbjJ<̏J϶ |=\wa1o")1$9F.[Js}ˮ2z2r=bu$*^x8W$EvgJGS > =C/DQOY\8uhCS!/I暹}bR$E :dQұVAkFg"_/̵r 7/HOa{72d.zmβd^GaMLjdyň\feESM+u, eVΘ 7V3X=5spԠ{#}f5Hk9ׅAbkP~QES>ڬE#ui0:>[=e x]Pd$ۈԷs˟a:w/wO†fOhla׭%vEpGD]kzឪy;5+8k.Rsi()QwVLwm y+wGo)Ei;E}v9b{[ aN wp]q0* s$"O6Dv2t5~.1IIU-J=BT9EQfSNҶ*-aGV8Ʌ*9K/,95gސ3oYm^q臈 _#{wY >v!V$v O΅)y>rCO Zxzg(U h\Ժ`?D!MȾm"X#e ##GP"GMss=ꃲ5}3vHsH1PhT ܡ^x?g9*ptaϳAD(Tz/^j48UrC͈bJT=UU PHX HfXmjX3Ff/}?gj}y?m(T ƧP$0Wmٙ٧'Ղư4R#aH[nQ%f`kp[ е% E>%lִT8?^B /ht-%+mu`ow62 Ug}"{]ZBˬ9눯7 Ixlg5Vt=ߙ>JM8$a%1*Й!n_(h ![kյS3SN^c}3bqtd09p,ǾEk4BTφ1t{}B{t̩SƒV6T6_a;e=>ɐLK5ϥYNH@O"1~i?e4/țZyEfBػQ+#Kw8+2(3(f?X#7W{ʶ +7|iɑ' )\r;,wG?d$X|k}9;놮W=ϯVIyCCvvȭXw/߿(MFso_?(21c_=|X۬$sѪqn_0J#߿Ho g)Qvr~>ܓ\y,Gp]LbuJiǕ&h˅`||4Zr}|}:ddP`ǟM\Pnh1˥(k ܴ w$TCђCw4`^ $89t^O:BZ(y:Gظɐ smW}*x7kEi繟@5\ I!8gDI`MY {Vredu7U&g [^Mwlf!04Ew!yϾmY3H!G38v5M󠦩}alfUf?{@X~~n=q,9W{HkƽOU|%{<L ќڗ%3:ww:BMG^}ksg#`_PY^*CŖ@>#v\^?#پFzӐ n#C-%I7t\%r9\a3F_؁YK@ ʛ R&13+R+iRYPJ 3(Hͱ21W G\.W4Bp J@{E):XCPU* J +dH҄.5O3J2<."aQh<~92f)pK]>[ʨBHgjL) obU&R"6N(K0 C CpHW^H]IE*eZEYO!sXTNZ2FS- )ܨ ]T"@2 eJ?" Rx3 `|PB!H]/Z "PsT OKD \{4Y FB`:_en ^Q$*Ғ^)濘 "C7:ďj_ ]$5j\y6^?&u$82=ѶP6iK&NP?6 $F,hIPI.Pl+E[1&FZ2F@ɥostmԔ"|Jb n^ M,@4_Rgب4Ƙ^?JjMV>!$$ %zS-r @PAɍ 'RU ɃN*2c*.-ENAՙc"` VU Jxqa{F R\HoL8jY㎸abɮuJZf uy'z eRӺ+1a\KyԴRDF*ɬkД'mR(R֒J.f'& ek9M% Dgy؟xLD|y 6<0WH('TPJ_R0tqy@BjJ13R?V%9 uRl3/s$9:`h -:AXp5h Y*")-gl=Y+:s@u(e|TVJqqaBwpXK)rLF:#둊Z@KFUقA)xjSI.B`#Y^*Hgm(Ivx+ <_n"8TE $Y( q vkմBQ{'7Xc( O ujŠJDYIfJtQ#BA:/([^3pL=NQ, 陈f "zc' B XZ1$;i#HCΔR(3ђJ0jÓVH9H'KfƱ{)E %ޗ#W-0|URy}];80c(xX +!cek;()p:%R~jN-ApxJ 4]yǼ>PW'ڃĒ"4,#ģuQ{ΚuBTnlB,0@o;`)ԏN1` AqXkUZQJ5ʕD紽 }@dz@9B6#<s IïpbQ&@}0IMΪ:6,-## L-pՆZ@8'3 V:ׂPbH?$[Q+EU泽OA ]t4F=i?b|D3J.KA%H?.}t+H1yTd;#sEFZNJEදs,_Q?q窖y8MUP3G%@e4U0 6C%RKP:Uʼ\zF!, Y^b#pE"LC.$TйjYoG2XܤPn.E sވZkVZż`0]R g=&"6QlXi=atM1H v|ݜ"joеMWY@U0xh@ :/$P}QP ]+Nbq4;KZN.Ṷ6Tr#XD8uIGIdbw2ZFFCTAy) }ynB\0NXTI}کU0jZ#C\x(,SH` }bФHwZދhCnRRi/^:K̻Lca:J$J?Pu bJdH"j-ImK7 vP%a(m ڡN >\N.)O ȼx0ׄB N+]cv4JxÑJLMben˴wd拂ewU"#:UbBt)2\ -my@; !izăfΥJϥ}T2%(h"8+D;5k` >W;Vq)ԖK8Vܨ Go1R"+d y$#1NJ|F#R-v[ GbmgFK|yEY< Jɉe2c!˸t03 ?mL b,J  Be,2k:- )kU,-OA ֔UYaKɥC=q3\ґ ]+NHd)3bZ9f}^ŀdZ8N6K7AiT/hP8^(h20kb[ƪ]pXzgQ:]h:c5g5W[p*lcd{Ё9`Ն7^-n +[;% vCR= "䳪Ցq=װCDD(&5\7Xjo0yaKQ%%{S#,T@zcŊB@6/&)H4`̀WTr2.GL"OoKi1JR 1)9xUY~:Sʕ `ε̧DŽb݁X ^bQ-( LF/?Gjs!Dj47ܩ3)2VF/с!\ r@07j%,eı΀dg"bY(,8J Թ&V 8qƄ9 } WkHUqU6^:K0.@9/*ѿJQ;Zj%p&Kbר&o 6vr ܶԝlIj7ꆽ.n/֒u͝]v`\Uc;=f}{w* YH\VȅWFjީ&:'=_:& ]b~a`670v@g"/(2qUD$gH0"9<<⢧]_ #pX(,*ZUTR:`)*:N/>4̲>.f ȒIJޒ+AVFj\' 0Q Ә9܆@e(lA]P,!f̜zQI MAf"YN #'S!%#ǂ>JؒzUg\g&X2P lV&AdJ`-pR?KƁbSʒxy+e9U`A B}I)f8s*BlE:ȓiRKɻJ 4a:$9)wœBAFuOP 5(amu);>8Mb7P;'sĆ!FRV֤z˩Q2֧U x¬]a" ˑe>X%@d# j䥘K]H0!X3R\dW:&I -cJ4bɲ1LySs!V9)kh#Fjtf2N" 1DD)t` T*L4\u14L{+[-h D,>vD"XY%y<9 ""bWA4KȲN\A`υQG Tn<atO[egp+88ZAT"A].ի 0*dZRiv\a?HrM)ijΨN6\~JRp힧aLB.6hQQjKi.7]H0u&؏~­{z(]W[}oDa(t:PrhN$H>MH9 ( ]"j'8NI= 4R|Ciuϡ◧ɩj9F$ JSzy ZuR ZJ ';҈{ D$ h9FF`3%Ɯ)K% ᣥ۷fF,OL@JzaX˞PDֲ) Bz3ۂAsؚp5IUV̈4@!(HH`N3B`T†FZc݁K_0)@g^5\y'.\[!GE`R=ڿ抶_[D]ip4lH38 D Z 'dex0ai' d|T|3JFsXh`5(TbJT ^=bEa:d)04t%%ܟ(k%Js?_b`6opͧ7ӣȇ [v8/8iFhd|`w6^^.l6%\|ED13_ۯ O%ChL{{I;_9)viߜ˰PV^dn=""S##gE mDgD2u:}ZM*7HRCJ?,'`)F)5wg\N'̀q̅@|cbEI% 9J_!}Q(VR/UB*, m@F2gEdlaz*&]T?E$QDcK!/U^a,ֲ~wpɝU+$☛oDhF.A3z# !>"E7 TPϼ "q~((ZÄldk[$? c%W!{":CBZyhN1L@;pEL5S9HUM]00oJ -+>W(ђ=H[0d-(P Q,+])i bP|02Z$("LqM[%P(_CSJ8oX5d EsER Au?[UZEЬlmE3y`2 wE@qF%2!:yVԜJ*!8Nd%.g;=#^*~=eFP)Ť4/5 <"[)|~;^LP- J<9ѵ-5b[$}k1PQ8j‡:zo8i 8C7Ur5'>M-*TF^(N+/W v˝"K~W'R$K`yɣ n@KS! ռjDli#mE,DI{Z;V& ֎Lju&9 @B#?P~4S3!fiv5+^9ޯHoo.4JZb*YQ@ӳQ)''tJp̴Jv/Uҁ_9_  N8kpSI2JX|غ+EN rRa6Ro8Ӽ^=E#3J;`ÔB.+͆l+At/ j8ydF+`F$[&rzJ=KQAaSJ\}H0 J-jծ2錌QDlnSZ_fC*14)CfF#Ia_]+/TjŜJΊQOZd&!$wse$ OZ#B\y<x6hh,2 dFKAb-_ƼAL iyf%q,ݲSk I)&cJt Qt  3N_A;PI'eQ &` C'p/AˇΣxЌ16߃sqg<9{s[P~ϭĔtM:B4$[k6.v m:1 l0> nl Ϙ5ôPF-$by f9$GCl>0.w!j 䢕a8ApM{]F先0jNc!M̺'ؔ F #[#V't'u .SI*8HKF nK-!m71*+#dx+(D&mGJdfwl$i^ )XW`@[-5!qf &(&*B=\GAt1\6$X& KHXbc`SP;^f4ŵ,UYatgU_!@[AQĎ\ QsJ:pR5EL8&aLC\,D`36g1@\{0:N"N^*"BU,e8&6b{0[ UVl&rVUVbb6扫=$ی7fq"8Gt aOLR1Wq~J`".34I9`7Ia;Vq|,eP5.%h[IIM1 T W_)=$"kʧ \\T<(Eb=T@JE͌t^ Vߨ#YتXs  Lp[_Cu}RiT ps]:-ƃxPvم:hHVkn냴/f,bo|-JbƯE}F?Zy 1[+Ox: kVNhzB`!\λ@ ÈdĬd?%]`ovp8;φl#<ێe k`|0k eT|}g||0r8pp6Csۺ]nEPB5ïwW뎴Mensx~q,h  |#eO)llj}˪?mҿg}MYϥ1&I~X| ?7]~|oͣ4M_7]VgbF+u璟o~M7nELxvl6݈l($LKV fYNIU1)<$\}xh6¯ #I}EwC?LCcPK!LQB1tv\QL[h Ƒk P|7$1ڗs'U ;R!6P%uUSiDHEYyԖV!H:$g}5D P!9T:@pFXWbT1ARPigŇdd2P$HJW*Җ4rX60SY8<;7TԪJ'A*H]eOɪn%Ivo-tl&Fs n!ϚF3H,Y|Aė]V,1B2 F5#u/OĂ4E3F+xRؐ*nt7<j,n{Yj**ՉUz˅;G^[t#VŏȔ=_!t'(/vڰ20tu@xV;V;W/ٽz%$Z=6UƫB[  7g;Tƻ)o1] $D sbϐ$b~4b_ImN^+{RYߣ@r؞aHjzt& LU8/WHFϚHr2;ѓ @  ͻERTƈ%OQK!ADiyJA.0D`f7~R?[:J*$L H_4JPMxY,Zڙ 䊅Ia5-\K])̡:t$fEacȺ5Ά6))Z:<1C^ju2ͺ}&ˣ/^DƁR2BX4ӰQ+Tr](nu,-,&zFRMV:Z-s;Nbr ~)cJ%<jb+-/r\dEw 5l6!X*T udD{5mW펈竐 +m=NxgUe-J2XK YZ>j ,|y&YFݒUh^k8Wʣ VR3~+>9F g MNIS+$& 4ݘuFW"7Go!;.$"}\tHFֽ^(D7EBc s;w"YO U'p͸Nnۼj/zcDCfZf*$hd,Q ŷd!5\gāeݕQb ,P% H-Te0lF#㣗0?G]}[D2ꨥgoh:@KD2YH*He鉓|,%JD*UEG<BUFlhqBn&"먪6s-P=jQ)T8jML ~ D 5'jii\kL-8hHl<3I{&ޑa ~δ(%aAr"$[,Z5kQ::H]SzPMPs} lYhQLLJD@ L5dEEA( DWk} M^^N7OSifJ$SfE0NT<Ѩa }o<& MB\toE-AqrGR#.׻ =uw{ {8ٹW_Eb)T4' `ەՑT(HWIhIRH*eTo&8 Mp{o;myY^̵~ 0#^УČk'E…GPr(ΩSXw&[խ#5jtI4,*ߝfzQ[3N%_S)"EN@mSIxթTQn!wJǚD:"~x7,ߊ )$UBh}X3TrnU-r^9Ů)jpH)ދo R,1N.Rzh)r$Zԉڲ=M/sZMW`r Q}_K^(&"D@yrA#wo[(n1Y[}/V68U# IAV!IU˭U9]%:ud-EI5;zEKh0C~Q:rR~Aax&ܹ_LV%ig; \y6 x_rMI=y'?Dd*#I@#I]E߁ͻz+J ./%S#p ijWڨd[6LUw\dK9]&&+P(,6ٮC/9UHBz U$SsՑ;<Ôމ/TЏnz5ۼ SL zP""wKdXE# 3u,-w|K Hu] U@bhL+FN&rtzg-ֹ` #7ӫNS-Y iWB+aj Vϵk"+TU8"p"},Q$?s'I|06oa,"EfW{˛a:{ }^̫XCtUh/k*r} ?H񹬘U!UTA 2U갓S;mqKR dJ:q%Б#QْdpHs p<w^ܞ)#) ̚Sا"!:+Mw͐2F-1Zr:.( 3T/IM R.&7bUKy2P$ѓ^S;'7Fxͨ%nV b(ԥ2 w4( PSM`A N5s#0$Kg0^G,+IԽ. R0蒆V^a7M[Ƌ}JTr R'9)  bI*Ƹev^a[NL|oY hM(%~F!tFk:7-aEeU'>1>魯bNjO'LurOJurOMuqɓNV")Vt"NNɣ5:yZKX{G.Jtro?Jujo؞Nn݊NTNjO'i [AH .RN<`7Ƀ:|%‰Pl[l.V!5mz'ENjWQJN M+=fb.[w^NKF>L5 Q6R:|U+~,o@vףꯅtcKacs"V'^k݂)ҋ 4r/u7ޕ.{wϣDj4.KE5 1zLT>%h)dq_}7 -Dۓ-*& %B%"şAIڝª{5Vwd0hՠe'! 櫎{*T:OExmVsjf4=ޥsHb1B}!jy*LFTR"QtT/y:x (cLᅛ Hs"eHR0%N:=5U?Bl4S܉ydLV҃Ԓ&ȘdYM&wؚQk])^P\q/= &n"fKD|,&7޺Rz:s F,z}3 Ӥ<[qޞܑb{rG RJ\ESm.BYF+ gbmp̊zƾ 2ʢuJM˥pB2D)z odf:R<5*`Ծv Hx3 pQ%[$O v_~ὙUaXG>DD,hkŤn^bN`[7rVD穣"|~59*"j[Np<D{_}UmF(l/$yq7; P HÂüxlh:m|$t)Qmdb!@xv/+C$XlQrRjICUFlcUȤ8^Yf@2P"˨(/cH+fb0қ OwMB͂zI t]%_6\PX|:*p 'MVPzTkD)E1pr[R/M`zgDƯal2( ^4Dͅ(}~0~bŠ syj8\ܐ*y';ulqң r`g/9.DCC9w!R;Y![uTII"Wox~T7TCWI\VZ:6y^&)[τ o"]xXd6^LJf7P%IӅ6D65d%=nd>7~ZCm{7n!5d\( tNx|ݘ^;^ s-Ĥ+@%yk [Ss+%^:'뫚 v&A)P6nQ3~GOJ8g.1CƴcL,)v%e;vB9XŷKGzԞؿp+7equSܵDM/*Bu7bȀп`tʊAB4cd٨t4JkRYJ:qsGܨR-whYx$ endstream endobj 25 0 obj <>stream 3#{sg@PZgڴ=f ë2*\ >Mgab[ZKW/R~am]TTk>ތ˓*t5_{wޛ5o=nr '&+n.^ڹ'mşD_ IGh^؅`+oŸb#\כti:0__W}ɷOܛP VԝoE}/l4gM_ut"h"A`3NH/AJw^Xh@A⽓ntυ[-㯍wMoē.hFHH<]:[  {bzߤ~K2oY7oӭ\v ~G1VMm7Zpeo%5fߦtu$d{Y]ڤMLlxM4| nd $m6{㉊!_˃oniߜ?xq;̦}իJj;y/8j۽Qﻻ?olw4ؚ- NOGh~?dt><|6Ӧu6/զWG;5M[r>pv4OJk{b~q]gIφ烫{nC ܚrt;ߗVڎ'yok:ͰiWymeCwKҽ;Lt136o?ޚg2wƻ-+xmX?ƞx-q4e~1]L0+Q#ɣ~tRoO9n;|?=wykƋqN,{_b0=Lܝ5i-c:S)'! ħ;lV⾠+~׍ >˧ [6GFEt9,bM4e~x4S|=_>{h89-ooȁϛѴ]>_̎{2Kc7ooG񓣉p>M9'k>mV\MWA2aU. 1:` @L*Oɗz9e)S.yl|e^$O^ ϋ0_GٸcB_V, j"5OPm?f}S+\)\",Yҟm:g7I:ો+M4(iz / /jTא?&55=xq\ˢNHw6_7?^$Ԝ_@d2ÂP j\ Nj|s(Nzc2_^& >)^07^d̜߯!+,EɋsqU&ԽȟA^ FNjs YLZ϶98q P'dv_ Njs1̯!4esD`P =~9&A^07A69/ udERIǪIu65@S_ Nj㏅}=!{<:+Lhk  "Ϝr.!./8.Z fm] z.(ߵ9T=y"\*kc:ɩ꽬Gǃ|ĹR?^7?^Θ zgLize^^]p73^d\H.9&:u5^75^\A&`,. g]7=ޞLr4v4~?QlvGd2~:> Gg̥?K<1sortӻ?o7Knpܚ }}x}`q7FV4lg#k\yQ٦|ѿف ł_8rq;c5\Fb_OHxɼwidL$Cd|gjx嫡OcCnpq7`lwvG!w+JN1tnA{ǭ;jҭSǓ,px2vV;L?Aa?/ѝqɤg-Fӣx}`>>y>[g8 8{oIu@x\Hj{H4|GgEc~ ׃SKl|7.wƿ@ Ct=G^\aW؅S?gL g^'3?zݹ39挚0I;@x.{^ /yO;ig6\s|Pѥ<yw'ӓK؛/[Ƚϳh47<]0 3fm8_lA?7]?^D}Ggg׶/o߮X흿w{Q~ ެ=_տ0 cdh+;cGG'd(.d(1AV0-Op.ُVsqXhF@?;N{'8bGrzU[NFHsoW^.};Om;?bY{S[|ۥN}V t㥉K_~h?z$08\0cqŰI59EIh2C-CeGpg}Q hφ=~Ԯ!}QK⣸a:K԰fjrhקrFƓqjC|M#iދ7\׬JUv .XZ;4{׶oa* zIvMHB0EUl_mqC~3nhe_{%MD _qSٞ'6rQf.;Y.g#wj]KWKFTh`cMV,iBtC'Wp~._Ϯ 'ҹum)L7BC/Bhu,U2a,Uos?:{R!*y֐+]ͨmRpMcR*2r6{T׾M谕=̞,W^q_Q2?cѼ2t{tx9yV>aֳv{^rV=h7C*&lMbMӦ߲jue>5-~KZ\}Loi12;cJ☷nEϖњFbG^4n~?sm*rqog rvdžw-׀[Jܡ9d !Twk1r(q`x0oL{.jMRqټ a,GZ04Η|7hVߚv_:_u0\<leH.LcpDgyGp}G2%δ=2\<]`pMmGټm تZX9Ѵ{П"t.wN vumm~磕6ۯErΧ.~9Z< 3ʽ/x>=-O糣x=-ԉ>F͘{8lދvv')C8qcLx9OKš OOG{0a&>nG[e{>;ܜNrK꾏t F2{TM>Jπ1K&yrvWҧָ [gj]nʨ}I7[ ggȬptnq0Is쫿 =NӽQo>߼M]a-~6{vo>{2~(aK֟F!D_V:_;>~2Ɉ]}lX؛-;AmUwDmB=h8/C8:|{?xuQZ*Pq^F{~y7?Ư=,n\pnʳ'-Yθfk8ཷ{e>o]/?~|?h~Ӎ@oFD۩ 9ilu8vVM'mhJLtv>=xr'4~Zq?.7'm8 ߖ{bcr֎gѓLGOVʹd I&f֫Ukx6l/Qk6( G6nFj4\7m#N}bv7;`Y g}݊M,|8zN{1Wƃףl|}ؓs(&ٞ k 3N?JPO꽕;GR[ˉ~(899s@Xgyp7}\g^֯{dk/A+KI`/Oz]y'^_ؔz•oV-O/w6 O-}bbw<ĔV׸^-' Mΰ+hcq7lsxږOZV:gt١:NAqNgUI/3.y=C-Yiڶ=P.zRCZiQ&r DĠ%,9Cy*5< Zw#?Cxgh||b3ۣ-Rlz"\LӰe=q< 1nEu]ӧgbl߄-WMWK4Q*ekPT_,Nx9qi8-`3.hdZ|DUgX rA`<}>Y,۵\coOelk A+ 1h? ]/>M/t_`do{wً心 j)ɋ/ N[q(m{>`2|kExhw{CF6mL+bfO׏s`m"nޛw\^n߳O5"'9;#y~W$3N |5 $Ɩ&r8Ϩί8tHOr^&9?Mxi^лN0nWף]e` ᳣p<9X A'x3Xzl{{OHwIgztƛYZH3)OFyN)H.Ks4I3F &JPo]aN3yGwo|~,o_S~ӽ|ת>Wյœ|sw\y ]|x\ި:?o_lG[ށ|÷w޹}_|qYݹ}_W?;'}\m,?_.}'3?εwows^ؤ}M? r[_Bo'~ko;||#돮? #nkV[! \>Z _vs[aᓢyoWv\7U~;|yw{Γ9x'7~SUߟu/ͻwŭ_#-rJl>nv||x4jՓܴru,ݺ|o?4ܺ㪭G=G;~:loŕg޽Z}yɳ~|wr癲;Ol;{&,o>}?>ox7?ϾꝽE?O^'wk0xW,>׾iU}1|;|K7oe_Ms`~q雏[FL3O^7_\zrsO#VO?Hm| D#`G4wt82&kK%uyд7~_:;m5=Uѯr3PQ1ssw/vx{_[Xs֬gVJ?wk~!7#|t࿍s-b~+V}~9}Ŀ,9|9䏫M|6=ߘ/jυkcȷY'7ծ66mN<So5ad/+n~/ٟKedȯcc-d~Df$G$7tݯ}_C_o9gY~LhN[W)%k~'&,-\h,6c(~VץSjR֠uDLg#vBZ﹯ c /ӝXt>t'ak2R}aB+N?`vwo}B >%"\T0#xD =agO1Zte+sϫtя}eF7j і\(7(t6(wdׄ'm2ی?V$}'%*\~_ZI&E`7霪:X6G<>|'b@bDh_";Ux%TI^\B<X¶h%n闏q/[ү8`SkA,7=WU 8δ~XƯ/斎P5? $7N|{HcV Ag:ױ?4#0MSX0j-WK4i7)juHc,-<)ɍ}>iqo}?}!nqT\qfsK$ = Zˁ -tB:#Wq\SW z[0ֈSUAbdVgFA֏ߦ;~/sp+rI RQm|?JMTۑnƟvA@ܳ)RKũ|Y9;}*- M#z|0_fP#9_,%D7;f.c!Ml2ɔIP,| ,1 4d_6㲪?)|wzB"K/6ztB ĬVOA~ac2N[c1՟ww٥)O߭+o{{|qD`@s~}__| xƵE}QeA~}kr]PiSqK X}?tG}'۳Lny_=rDSb&k݉2Dit\Ύ8513k||ڜ"͙,Qߢq!oFa$oq{w$3̮c܁:K{5n.p+'!$[$D 房B'DdVV#@OV0['n)<_Fz.{ [go͝Y^~2h3uNt~;l Po^?%?t90j`ܠil;6W>c%H9%(clK?||Z!ީT TltYjղix Kc}OwF/r֛Y1"mk T/ߗqҟ2 qH {4):i;"t[{iRN~GN{j`49k2յ@[&vW٭/J*q&NK6/w9|%'8Tg1/8*NVD<ǐAm1)N{ܴoG Ɠ?;9Kϝfݠ'۷F^Do}m/{w\2^npҿcK\du%k-!5ꐥ)wgŹyRÏd#;8]|ԲUDXܷ/~?Z$:{ufBUΖh:7-nR.,FAbՇk {|s_}\n6a ɝ?`Tצ]N6|f?:_9bpTL &=It6S&a hgK-2~Tz^Փ|jVaVou]+g`~ J +.0N-!hRX2rCY[(?nIǺIOnJL~#f>F|Q:<{_y}oDž ~Ir|Glr7y.>Eş!yNnw/k~BR"tUOAbTwPR9JT!]'z0Sx&?RaWArUdl|IeAG!/r |;_޶:I8UVHeb ċ۽GͿԫ<80w6l_qvqdBO۝*; NbGn>F% d?FDŽM2y&43yL9Sv'yPM+ZuKir)kD]KBu5t>WU'!lSp9yvi,+N.Rrfˢaݗ 0>;@PjvwDcST_)jno(8%l5xQlt ƕӬ5ފ#)@&FUSohYvY+鵈[zOPd<'#=(6[AYkyXBg5[Z~Gtn(7kCA˷h7r._/vdd&3ӞeOsz׬]%>? g-nΑ͡8YFwAZ\/Vdg+β~BXr+\er2Sc<=͎fYcn{\Áw nMDROeyz:1lp&y=?.u"a jV7 :]}Qp;a\tmӁb yʨ!%\o9^ "8y'FI(oToW=E¬r- GuVPQ̦:{`jO!am#&jiTkȨI!RD^ J om`۾6kwr,HA헲:tu&.NVoJ%朷'EEU58ąu[ I tʶֲ۝c1; {exVgXEZc7Ua)wؼ.rB*}Mx^L7v18vYH#2W- ^Լ nr(7#=M,8َŬ&jM,M = MVub4σ;`ӡ14? rz[)[sO"o[yhqUSRb1vL#g/&'+)ǝ,!CNlFY/sHcrmۗ[~M׬"ܧZKc(u*׀Rk%ך"70 w[|*7p:5z_,%@YM-=k=9k{L$9*L84X24k6N`/a0X.dz f_D{\J]/;]; o㍆;۞wa%: {&/xzQ86 );^Jw#YG]\~<0M˗YS9[S9NSCOr\ 1dU]*k9p9tG3LjE]3=K6.vS]JˠEp_BK&2:OձQ7j4h\ƒ)AטTx_pP;T(8c)5^)hp6kc/xsHhiqXc̨6׷<:-n^nze'l=P,dhБ}(8k!\g%jp ,{t~tKV8cfطQ7doIO{!>ƕUؓ,rʿ hzBF3Z:^ME. [yg[ eQf_XY3}[;X?-7~i=Ť:{NonNglZE Q0g;e5g׳Tgι5>IYws~we(ev}&GlH8IY9+\#M+H0-X>7^}M\Fl1o؁duvX !ZyuFggVv:J@L% Xc ?)e.bVs<"e/j< *BV=i-%^#hGoZf k]69b*ZE2 .*}G[;*<+*^fݪM(+s Vjg!~N *uGN oݠ BrHFSyfy~4fҹ)]Xt|fkHUmӞHԲ{v^'>xX̒/) P4NKnxHm,0ZdHw %;+O0%5;_\bWb1|味s@MK2+d Ϸ@Đ0̆ƛn̜ROnY`-X낳o= {rN1FpzJiI!ӞTi?ϵA|s8ϝ mӉ]$(K 7Q4R 'OI;bZܥZ[CVkmu׬eO|J:e*?%[AOy$I;_k~yhr~&GzɲF D6Z}MHyϧq `Z%\25l ^f>&Jbq%`eV󶃻+z(+`#:vD W9ն/m.VWx̬GKҚ KEg-n+7^W%vfxˠs܉r@f: bReUF>Oڮ3,䨜HKh%Ѭ0?×Ut+W2cTd>Z"2cCv~Ade%ȯ0Ǒh֤vO >S@FK^fUV55 ovE b(iinГUym޻~6kc+n.cO)UY\xʤd;=fi7#f&3nۗ+ ˝ٽ GtZv(䁌 U4Օ杪<6f ;jICCcoڗZ HLRk_~*zHzt`5@oo|&NgnPm3Iz0ۏn!y~J_$"]gG=e'Be/׸Ml4{B_mrq/;n,ȸLr F$x=˙d!4}Es Y w˱z ͳtUf9+ST)8\\V\n'ȫo#W lqy؞4U) ]U~d:1V}ƂdOd>JM&Ԡ]jJKHx@e@`c_&WI) JwMt ?]k{+~u=ԬͳӅ גjOh5Z)59 AxU{H\cxB;5H-%}hKt-ma(cMUIኒ`lzROI("Hn[|ٴ}.P 2z%X VP Ѱ2qmr)qPT!v}๭fm~ T>kÍjLz!"ټfD9t@ڋݼY(:{4]e7uZEm8sښm&js&MObMٓ7`m?NglUFh:8K$M6C7.V?}F@R[^z27slxp"ỲSv ;f}>hȥ-U{Xkn,C`W71e?$GO$Ms!4Nhָ̗*놄B ):XйN̫buo #Z0Hd\.Vcxچd$'94$||e÷ H ^z 3k.T.N| 4|3A|O^f()VI+~RXw}N4MƑHezzi9 kp#;p9>.iE5BALgΉJ|U 3K<5˛PM)S VYXy>\nLkrIŚ IK5*]Y҉ JcU7 #z/v٭86b!00$aX1\u9c\}FiϋL"qVQU)i9)Qɗkͻ-v},bgl;itVf"܊+;{t"V5O>GT_*,' m@#d*+E(u[VΉGfSvD kcsMu/EObpi(X1? EIn;5zt'l>EgUxH!4@XYMQ&H҉mv0hpdvʍj`&ĸ[s=aIJ$)YG%C&05R6[EyY=9xYlͬ<Ȑ>)HS2dĘYVsد>)dUYWAz7W:}zgnpASêhp[o9nc|NNK.3,wTz-j1$}yp; g޴0qwkgwSeH2r9C2\L Rm)ҩN3ISȐ]'umpz7֝/2&`eB1|x䘅Z u,Mu7l?1}zL }' _eɤ|~րFxM<ϼ2xBd"7ygwKai dr=vU" B҇2HZ&WQkD{$ḥãگg2~R sGT Zޑ;M6m!q,ё;ߊejiMpQz8Br6S;Ii}r_{9P58и刜 ζ$IG? ICKǦyuC8>.FzJKyϹg J8]d:7*KkWAο^k|ŪO9}Э+wd1KI2Y-VF4,c'|Uz،SEf \~e;<|)suղyܗ${]{8Ky]+# ZXTZf;|KlVYёxR BDy!$~K6]fe.!+ORQHR-<0^WWKW ZLf fbw!45F9k`*`ao#}?@)bS6}t"pO.9ou4ׄYf|QћͅFS:(h,:ook2v<"hg-4::؄{t!,k\yZ'E5G+a[r=lur:oM5YPxɷ/ z ŝǥ v=mokp^ex F|[:Ҿ*xDG#OdTaŔ)]Ւ\,1xbp TRvRTSn~ߔY%pE8оV: M|qNxKfYU έ>_(lwS9dYWN΁0i7)i]%8'&LgJﮇPe!G ų0*'s9ҋ >I~gܣܑR 0Tm/;5E-&K\߃Fo5%#߶3#'YŋvZv% y{Y8EepOMHg>k􆙊mR`: -BIYVZU'ۗ:vzdAT9l>x7reXH G5QB+ݴP..RNE_(jT& +ዖR'qzs+I.x҅!㑧8+n]lK5={!WK^^09kz5}eRmӖz2ހl~X+DA'%PX.:Wzu9陷M ]yN/c{1'bx!L#,c.ey_=@''iw|'s.,hgWn5Nᗌ%O h-.$aߡR&L.U eE-RsG~4Xҷ `Zy+&GF,һ `Mdfp[`ժo|*ze;oݪv H]j|TVCў5jP79Bk(tt-of, ՓѺЗ0GN QVFyfmoW7@3;_ZTkW`ӣn )4@&3&S +}V`J 0ikV`@p6H\ V3T<}mԏyggܚݴ7-PB*rFs.mz!pz}hcx7HH={mghx[ėO]>4:w%8B\x5S))VtccqRȆZ78Nr%awKi-f-wBu$>aw-uӤƅi:w|NgXV&loA͊Y.5*up;e2:v0RWfWڪNMVMs'0+?dilD+icZ2Mȏ5bM])|=gnttc [x}mvUfVv;=/ 8mX ǵDžw$In\.(\}8=cʍcM ?}ڟf Qtyhዥѥ# l'L %&pB$zۃ;~$=xVm>w'޻إ!4mG1žF֖o%fuMq•Uyd |ظ -by0 rJW$;*!rQ%wicCO<O&TqwLk, r9g95f3&_KmD "(/IYm|&9ddj0mxuMkV]}JfhvR=ϵ/{bXȏ5XϪTBVu%>.6g`H֤`GLM[ETξpD6RgN֨+E:Z/FJgF('F3*[c9Vf~L:58OBP'ʽUb\U2KGib[+w[˕F\^Poܹ .cMXI==EF\vr`ƛZCXY(ԧLLYZnf2Msn ~7w]PQ875NO|eViNlm}ʗVK璃cd+4థ hHѩ.A0U?O뤋GϐZ/-T'zcu,=#ms䎅.dz3b͞t&E%6fUZX{Lwa!lknn@HcΧscȔC5tA7EReMlX(UÝ,1ӳ[iS9&L(?zߠ6EPvA V 8ihI13LԚ^YZr5ҦDy%֠\̽,7' 40}o9jN./L2OP9pG$'CTvB8I#, JsR BCPK]hSfu!@Ϭ(&DMК*[VZ~IW(S"hZI7Tw!LB ȓ`Ѫh)3v:>%LDBΊ]_3=Uş8}d/hWE{쐜V,$l:GGy+ lZD  sɜst;?W?ke1kYf=^ZJ^ 袰5Wp ScO~a2/tF:f ]وbSSpG}G|Ⴘ ;OB\?[ޜХ7.gkg) ;rzɼG5p|b{ 3D 8Jvprw}P_ǍP79zY!78.`(xOߔve38)Af_/B?mm6I0}rTBRh˯x#se T22ΣHU̱`; نu _^+Z>-&Li*ΙY}5wXz2o-Z6P5\u*ȫplpmWNDwVטJ1,5*NA:_;gmy<@vRuYi^6(8Y7n;[+iߒ8{>vGRZ#HNϒ #zu\" 6:$nTv6;(KZN*Z`Ag/yS\dir1pEv9Pb__HbvГBo ǷKRP-O8/ZBZ(7v& #!~L>康.Q,% aFNif1>"3GN~n2eH(Qv y׳56m8hVtHZb_w_6ZEEKOU-TC/MmӗWc]e=ZI˕ʈ- CT@RCLb=wq3UZ7XRzXQ9QRQ72Xvİ|R^(h"3JVrkP+<@5L* -'oj +Vui^7)ZYG7iQAu:ֺĊz&=5Jg@y_hIY=):CUͯ]Lud2qO*6J1_.Wqm5!eTSi䌴WSJ|zYNWnVQKG#81SuGkM[#.JKfSR;:X4yuSc[SPLG~&'/y9/aa6J` ^b XC%ǜ pg$O =#Ϯ!QaKǡm7W Ii)&f7wzka)*ԣ7>y$f= xP`+X%h^sw5pVB*؍[l2Ta=#jض[oeVn H./vEQ͝ 9@a?uEXKnnH~tS\GAw)οVѺO8ƨ} j Y;i_OzsCm v4 ֣Z2OhoMIjnhTR[^(Tu>ä\{Y?a=`lKnvg9gwK 2`q{W-9hnjW0'GMv#I4Nsn&1xzMfԺ-ka^I{&=|&?Ov.70S?D$,+誼/vs]!zi[w 5Tgaiq*s* ko6~0ϵl,&8Μd2}LJaSoΥŲu$c(Q|m9 \PQ<#]qf#7_˛#qyոlyqv5ףOIkXjnliؘ?W-{ { v1un)^wmL@`:Խe[ػjBDFb9ܖƏG.W2~OS,s?4mvYukd#{th&\ QPj_OѦMwQm-3ˎz[̯e8lli4ϹhV17Y3:(5]A"!M-V\>[#Ń^Y1" M yS9DZetco_g X6W.u3/ky YE}Kti&kŒ];V9uܳۘuߗu"VuXyn- ե[/ms,X~׾g>!0YR^$`eNƋR@^ްuZܲ.T!( ɾ*Ta4'OmSi#N=87 W^xMÕzی-"p<3?0Bazf)t4v­sYDʓ[yCDhA]+#)?0|xV"XLzG ֵhRlzlIByƯ}35_|nitnD _>???;@Zv`vGA;u|NA-rOFT|)CSLŠ3%ѢSC0o96v2L~Vjl?4 SrAq0IKc9B /$S`d^a$J=n tםZ^CǺ/ gZةߝ?:x\Y&KgMHXoxI/M_?OgK,C;K>!Pk3qt: iW5IE ?w?Zq3 іգz[W>©Cj8Nӊr*'ۇ.7yxRB4Q,I9 p] ^u!o3)sYzkJa7siI!]vŶ b3U2wEe4^\e&=@Qߑtui˿$/$7+BM yﴎZ$zgk<_#[>75.;]iA2}9w^qox5{apOHz *sXڳ14L77(ydeВck7@&k]"ˏ+_؞7RLѤЄVMK. kT=PPkĠd!shhQsLz7oߊ$)&B +CiaVVb&3gUxNQ(64F+m;." 4PR rC6{ʒʄ4OбԝDw:1GiWM&aP;#V9c g1kAju.KZ_On:^ 4W/'d4SԖݾAUQm+:Xf1=ޓ`͉.(sJ8:yR؜8"&ڢp Q^h`4g#~!oAl8YY44a!"L]-ϨHSZ1ݽ^{SnwP9)enb͖w"*o9 Z)cYEA/P mv(6G)=VW^R _UլI"̄G,^K}^9L_9y=c!B(g9ǐ|͚ra iIn8k7X>ju!D :V|Jw{4 Tβh`٪2?<& Bzׯ ;aOn O|r a[f:HT޲#h/\G0s zu>/HIX\#bݬAt qr5=rfnW\ؑȓT (ؒ0+Zl$ϳK ^=!\,?J]2~wk-oUv[&Ã:ApI/մT92?ѭ%̑INRoiugzgIxT̷ij7ӵ8dŴ8t[i@deioFv5;:98݆yF|]}O=)h+]͂Ľ]O!/Lj&*/+1vupҀ+88WhwmېN7Ri.FT[Q?PYtie㫶]";wQ۩ Iu7f,YhV6PsUTظhyv qIܛ${70#%)=lEw5!~x|LWa")%LZߝQ-=ٶඖ"0Z^^wdê}Wqi4R5qŽvc#5jd')}Q^Yʛҗc\D濪,Ird*"KA<`\/^ J6Ee^,r:U11j fk.X.V8*Zu V>K9v%\c;L]{_jk;<d%T[@\pۇ]?F[\WF7Yp޴Ƭlk>?ս8sAØ,$.zKCgp{vSI0ݵǺoܺNٜ7IțVlD Ͱ\:/@xSTGimۣ`SYȪT_r{]G4TjnWMd.Ҹy/<5$u(H 5DVn K;'%)4+ iңHrS4K 8)*X pjhS~rFq5R4 45ȆnqA(&Rp/V,s]h$էn Sؚ,sqw/L+)ڍzDeoz4G7]kfv,y~3H̦=7l\J8 V'Asw5WP'O~l藖uaxY q~،Nf]ƅg5#v ?>Bُ\6n0m8(CwC(xE>3Ukjy$]`d2)PkU8'ySiy)!f$u԰s~͗e^$5~CmѪ)w Ng ̾+[q{?f_;a0qc=-(^ZfErS!wT%)%adkYsC-cn19vR\hCY#_]}צϿw'tIW6g/gyK/`_/ ̯^ ^=brNXpaAv0Cܙ֒O`vU̇RH T C5[d#|g+m%6D; \ X(%0b]1)OPh@O~PKR[mxBJ=w"=[...QniC /ʄjf[{j 4y<oT|Dq4K&DeCM je(6ti/{V!_u GxȬ#sS@QCQdΥ^劐YK5*+Ik eگX<* ߋ9}̬e,FVo~kAuG)ؤ.³Zm|WvMMVZٯ>0NX -sGMZgnZf59,5^~5Xn0$D湐gk uC%0a텝6J1i~IݲozH0>- 'rmk$TOޙvQUw йuKkگ~=kf5_=93<1/ˌ^ ƧY~""ɹP(%<psӓLb.2!9PM$ּJi~R*<6hݩ,h.DZ3nPQːhs\ љ"gw0(y+J ;}dtt]1cz{-nYpr;Yvq漜d}w7SUJU_o𼵔PlL!]?ߥ9^ô. :h q|m^^LfKW5f{FTw鐝eNGXLN3QK3wl].؇1J )_P*sHz٬n(F=pvu;ezИѭrVxMtWgo :cI]e򔒣A88(5m Un]ˈ}A!uFܹq\o%=d5Ir8iZT1kw]/,wÂ/9׬kn-A@ mXHaV[zb2iJ}ZjOY-OfYܦZ&.7A.?hrk0i,2)&:RC{Vˊц-[u5a|NՋ~6oUqhNYuNxͬ>~:n=*p>ݯ`NpЧmmGDN7j,U>, RN":ynAfE\ ƜuXKc^iAV$ܚnޡ=[1&. ˻HmXI;0[]jMK9v,# C|bIzcca4nn^.de`_jU=RuA١ (<ijuvl;?Iƨ&3PfZ$˽d䅛X^ڸt3d#'IUϡtPhpnN ړ;5;lBf!|< =Ao"T|xC8ث_J$+]xV֑?ͭ`( wӶG98̤L%(ɼ?n"h%رN 8fʫb>ـd^ׇ t`g~v[0a /jC=8 I>q_cm0q{Ӻ%RɄI?PXsىG9K鉎صwjjN13_Xš:N;^Poۭjw”͔񹏱y's5Q3?z$7mkKabB5]C'_PO< #/V[U%];3ߏ+Ӵ!QLTA84cĪl仓+hT>gtϢyt<N492)+&i?Udʪn%['v:=ޠpGި,!'!AJTtß9+=6$2UYo&9aw) b;،OEJA3;֔HI(_q)tEgˀ7x L2~ ð&P}Js_'04bIД)o 4 QXv +(_Q@hYWBdĂ/RW 6Sq@`l%UW*Y=%{ õw[ӵB_g\Kʥ)6-VD h2S{#$a6+ lEUc1R Vt^w۠pmOeKU]u-Hx;{$zuFk^?UW+B)<_BmFY_9U r]>pxˆÆBs*px~Wf&u{ Y(0Ԃem̑n8Ao#O|6?C2BzHj{iEK'=}M46rk] 6<|_J jUqؿu'zbWڭ\\ڦg)NJ;2)tTvmtNB%Tr!(oz مdI7$Fs`fA ]u"]xcC[ņhwOW^c3ZB8 r27;[ 6t'&Q Ɂ^I[zq{}>BH?b<75]»_cu͖ 8"V{iI;_\GpJ ւ)mMgOJ/gVzXduc]k5jCTWF{Ooչq~@ۍNeKjt,3>mEnjGMUȈbS!Њ6%ATZ_ _E~+;oƈuFWl7>8z*oXB[] [3>Q$ů&/'7Tm횼T7*b+(U-y!  C{4מUA67HWA{ e9"6Ei{y['''7cɍ0_I;k,xpLhzZU^,4Bu9eK?bT0G`<47Oo/3|c J*Ჟ glmdW |/2:e8akVGYL- A<5laRvRr?tޛ]^b,CEh) n_rsPh,9qv6FY T~2Dt.~GO. j2/*+C[U=4`ka"nƨ/mU` 8/TӋ VYnI;n)Co.ɓ+_W52 k0ϽQ"BMuk 64zy=+GYKR`;hИ3 ӂ #twO$vA}+Xy⡱z)dV/?$("&Ҷ\:lw8Ԟ@A5oH K'~'d;ʏs!Ȼ5Xf|Y0߈Zse<-&NiJT*pЛʳ𗾏& = 3 ZJ+X}/[, 0*м#va/M"8}ujb/]XǮjV^A['Z>W2:[.XEME b߳= --"[J[6z?86- N00;-rMrCdDIJpǐf`:Nl@E g\Zq﫝ufZϓohQ'n#^n;rv: õAѭ,Ph;HC";u_ԿcL -20Yr-+ıԭoՑ+E ipCB{vc?]֝b˳'\PbF5*6yW0 `sQ| 1=ɉrK^], ! `la#kv⻪zAK?O+N,Ļ'_5W!dC+fݬ<۪M.ȸL撷?r~f\"[Y _sU/=H deXjPϦt:v ^Yi;z\|$ng'[⇣sU6qSK~?W{`r*??_/tʀW5Rs),%sd4b~~/Fv'!w^qj5iH;/ 6S3۟|L1BB~-+[Vuz١C-.d&JLrnEZs:AI'SJʭ9Y"Um~yp<صY0IU=d8Aƨ˹;;nALܾ|ЊEb5&dcn) S-{w5i ] jk!-s6gPA;4A52V?Izc ]"?ݑXpG{%3Y(FĪzfjqz5uZ2oSQEa`6&`TLl{ )kqbĜZXTtZCNH06?)wvMˬ OJm5 uCƚ>0.D1"#^-Msqq?^hRQ"3X;{P(OĜl#3B 'fe[|$kWo#C6L22n56 ˻󀦺ND-Wb̥ ʓThJ|tO9UtvR8>~Fc`u{3^/I7.Zk:i6>6dgv߫Rˬ_Ma΅jSJn]cڤ?W,'Oulh\ΐ02oݧ]vUR8,wح/BqcT 4\ r5%^EJHʫ(1:V*!*l)ނrf2"AXj6rT>'LV6|8u6qn7Ħ 췴I=UD{jsմaq=<;aWդ/ožYxWH /ZuN¢u ИxAx\{ج%n,:@W[ltcc8]R!SP.=un+g1`p"cs9>3?{#lmT*i.e^ڭ_=1EQ^7:l5]Oz<ڣaop ^ FGsc?9R9,s:XIuMe}sYJ{=^T`_ uX\Y7kV1vQGoú=F}.VJ:,gbXuvc^4YN]Wh2a#)힨6G_Kʂ SЯi%uk@<晧Y>C6ۤ?cL,2tv++ړ=+ma'R>bmetNN}ٱjP?سO{,x2aݟP(رs;'5,5u^LYz\+qEzĪV<jaAO 7gCO>!ٯ1H2ȵ4[>L斸=fX_0] (϶r6fJ"SwӴfՏ)iVx(L5j&ah&氄8rPgX7]8l rjl۫a_c>^LՔdu{^5.uZ#"<;nj9t=ڀ^eS]圹oN}<ՃJUjy;BUaV(IM)MWȫϜMgfGǖW֭SBg,Y"psJĭr0ґ|rrh<os0f=g% G۳"ű^TNk;+ƙ:k1!A|`=pr`as:گm{XL G<^\}% "RoQ.Kvdٓs#Q'Gl{:9%f}b_e`vJ6 PdU-| EK̭dqvUsʋ>wI['CE֥nܩ N=4YUԺ,)a*Ȅ~Ξu:82x\<5n¸m 3j' us ^&)]U&0Tc`UgJ5_) v󗹵 IR \{uN-N8TN sP /7G=4uRk ΃d2V=k:P~JT>7RW2( @{rk0 Ll }~Zp\@E{~7xB_twv]/cό9c/&wWlOnˠnw~"ypӨbZxFXV ӝ%ýkrgĝMY1 Zȏ%`[jG{ڹi͜nRcF6Or/ݕ}GBF9n;4_b۲+Gmp-#F-+r>F^3k.ۏN*+zi1.k30%g/S\Q0V~{L/)}BygbGB8 dLqekWV싡'S8_v94 ^b"$s_ s ~D֭?3L>_A.]3Ql7(Gt?4(^B(]a[zq4w\oFi]><~-05`P^/c}iʷKGU(ɏvQNf'X{Z{>gP|k,{r @6\g T kݰgupO~['Sho@<ѩpX6цzF?SzKƩ nevn\mLygj&2#SmT˾WR^`)kתvIj*=C1=K(VU҆ 5x8XAH{ susMזa%g!%g^'uӢJZ> EɗW;-)SǹP8|M-5[GwP9f' vЗ$e p9Bֵ w.o7On<Ʊ#XM> 㖻`1JJ)P989Ug'(X}.d,/BvJT!ɻ_0} .2#V'd!kW̬WcL Glv˟?:$9Mgn_#ChR?{~# FiEKuQ:b7ܕ۩_9{U(wɜBP>RC쌞B*8Hkr; 3w.6ngJHCNg3sn'yeݝZM{Rny]W8͡Y.!&t-*L%0QL;rI`7;]#E:X.ʲMow%%׎rcsqЛ̓5DNdY]ekGUܒ#ԲC?p^5k:1;e2k&f!v|V.rYgs81Cw؝=jjT7)H5B /C#h3T?;drc~gAtG!-HJLvP??}Bi]5WƇ@kW <|;"ɟIg9?Sj<+FŸX€3+؍a 1OnyJ!)+gʛFX&7\Qn=5`_B']/U9sVo̘[K-2C]ݣS5k0؊ =ʥ'vqe|UIHD6\hZR}g-re< 8w2̬YQv{+v֛)};D/q#qxf9_+{S5kF&Q28,s~OPjp(~MD3teC?C%w>\xO c 12]ՙӠ &mTU$6A^s%6=IRX‹ҧ{/)xgcyGt)uy*\ JCO_s/jȡ:qȨBfE((x8ߥK]XUuѲo;rg`1Z:)=ҏ%&V_-Ϯ%xꩰ.{P7QUOvwn M@:]2ԩ}[;HSlΓD6z#óQns=k]UG"֘4aӁʈ*3Q~阱X35nJ-EhsJŃ1[U'=ݼk[X#1}ZBRzÖ ߀fվn4͔١{K-U?پNd7qz޴u.w^ˆL)l}o[Y%/M5's/|VDɕMpui/u2fC/4OGiY1it(_#Z]o:袑FG{K&m ܄qSoEVV^jST+Q_q@kPqo#ruSyhyO`AuB{կv (S WvV`*L4HL؍e$=7ʹN{SGf.wm@R0nusP[ۓ809ah=хg䤢j# k?DymTluzo9lKSG S{.fpV[WzjadMN./rmL-3N5N^ ұ~qERכvX4QC^coh8.U⡮U7>դ8G3240ڴ3\ыuyetkkw"O^KTS kSrƺ8w:3yP 8.PQ[㽂>mڪ9Ax~hv{ͭC{hV.}~xkollUoGdq_%;sʤj8PorL :c2ߐXg-fcNH=5zAZ޿܂+ ڐ޿XuKUӺTΰGxQMέʯۤP8X̳sieз`cg?KҔJ %kuL$ܭw8$ߧpjc!\bZRٙ=ڊ-8?K É/sk~oF5̍%*K̸B,C}3.z*7}^9'wC;l;i Ms: ̈]~\!9'?L1і*UMAkdPѠL^ 20JEǞՕJqx$)W )ggŴok2K'K=tms S;Y !pVDBe~deؑamS1"xߘVϽ ‘@yus;Z z-K-_ nP]~-)՞zC+ОZE_GV415 ?U$}9on;LY'$R^aW{-э ԳJ"[E|fOKpҽ g-'w0A o=ש},AźH* !t &vgku־)D[2_@]^hڄ:13p]rm] M VlS_dst}< ky_䮬!_|+[Aڶ&<V:5WM&7q5:/9,iVA*FډK,7o-Õ3MUBx!uUs+wr!@p>֯Jp&zfg%x85*l*<_s%gnLp:Ae>Nu~˩cyp-og˜=%(\1mb.=YF$v 2n 7}~pooi߃&|kmv[ީxn]gn]>k B{ᒏKC`[Ԟw+&_D e>{ t^ڈ =|b(ot OT=CmHjniQyyN%_oH!lϱyNI=~n˒eC RϨ,,n?TL.w<}hD6tduϳy|乾8:+?l@67%  n9uc,qyXUW 2(=!%6[PgPm檻o@ F/N4JC څ;Jy[SepNe4JZaf/o|Y!.1}7<ɞrB'=\H"I;B~)!Zk{ J,Lg (bN`egM`Cdb2A~qaPx8t. Dqv;p`'#ϜƘ;&_L/<8 ޗIwє R,'ipFA}|lRkPOڮGE3W 5)Ƴ{zo ? J~z5գ)3 >#Uk#8_~4oZ&d[=s1u}TvօF(4#Lfj*d _)A\vމeg'wLun*Č/IkYᏫ%LS}#Ǔeq(v.}駳VNӢbtZ_/~V'F'U~΢@ LZ)[ȯ |v_]X\6n+6ybNӽ\Eejw.w:qSLڵɢ"NW%/4_Kfa$ZUM-OԬd~~< 8VM\ZИDW-RqVM_EkcXO >& liY_]-Tu\`?ZoY+-BΆxPZv d W>7qvW4TEs{^q.ŏΣ! q`B݄ {=pġ+K Vu(3~cL Ӈi} l_G']Dh$aևx>š2EQ+Εj9ƅ-:MlN=P"18i84Bra ! ծŶ6}Qݸ`G}ܢei[<EX~|6ͰW(%zrbb (wM!Ą՛<6m : nΗՑꩵ40Jxq=zGO){ }6!}rT©zn,^lX1ۥFզXG>ãkS2)0: ݫ8C`GUbg`+DiapS}kL'f8MzAɸ^Lc׈k*Լ(/P=r"0VAF,Jzc 5g嘕 dӸw(mԋd \uI+]e&2ԩ]ԋO}Am?l`(l"HQ6]ipXfA\/x4TvtV'@5_$R|f,N$"?oݮžZ7vtS-h7ڪ7]|}Bo`@4=m[/$أ#'a^9L&T< nHi'[v)$ƶPWuqlK 9]͜BVL ϊ^a},{a<>']k|1>)+q/t8Js D`^aM`WV >7X?=F)m.Tw,/d#*]$Y2eS&`2T,:|Ѹ w+!`bs.u鮿DJk?RXm=(2t&ʹ3S|NR l@ڂn aԂ]XEOM~9VUyo[G#c9-|ډ6gx9RMPC93KͣUZR!SLޓ=Yu?q,;^ r+mqr7QnVrFpGn'-lԑ׸&W<)_G'5^봔b|[9:ϯV≸8n«TmyobGǗg)|,3b~׾Q|]%-6fXMz0;"u5k6%CBvA7~HbsVhVov}[E(,£d.`ZmGi<rd&qdM?&C1ܳT)Ad)|9Yk"Ua(3q6W`å[ឩSsN#fyfkb<`MLskג峨&fcAǮ#nW/ʔrH.l73sCc[$?@l\^5u@n|uK~ր/תo@^*ϩpoԆNmUR#lD֖kzt%'βZdAwS ͏E!.ץ-~ѡ=xܒ+UkO[9oYa)/YrτcT |^@2ZKzrC S?C%\5i=I񋩋'-oAsʸ 8mc=pZˎj:oK5K>„-^bC}o%0[ Ck\L{?a\{8V KeȌKLq&ˆnYu'g d[w.$_t\\G`;X:)7u>j5[x_boQL.?~H|>>L>q>[CC4dZ UYtMx o4=OEuFQX@Vt@olj NIJ{r"{iu_`[ Nb}6kʓF{4r*D~_{Hǘ bTU"qH~S"qtqȬԽ) ^vp] LsZbTb*Jwj@tm3|51t!x4*jwʏ%+}7IFh탫%ZMvlc 4ګKiտ頽{P bԜd6cV[zK3CgB{IיfDjp9{g;_Xxbc%NUث Y,gNarQ ^ñl]]}?·#+A·+)ED?Z#2cEW z9(o^>]6^,8%>x|Ix_~fo_*$m"\?)L/ܟ coNskA[zpժèZګ^Gm2di kZ?*lnİ8H~IVv"`)5Vr G~1Q)]pPڳ?R _pKyKՃv>`˱ZV ﱂ8sVp&4ճs~-ɻb7MPY9-kN} 1A)^yA4u"ѥVj]ԍzn98qMOOzΗV.Azan r^qWjT_7J#sog2Q ,!W'gא8֜rm;#d{9 `[GUm܄kѝP`8NnxzW?gBtU[ Ƭ% 6^ݱi0́ <^%}&Mۃr-V5s풆 ;5A5.Ğ_(),xIFS*&$1`m&dX߮EW=NSmRښԯXÆ,pQ38HSy9| H&G [B-t|h2(eF*~4GCd1K~MyX4#l Yw-s&9:Ե YF.ac!~lmVD䨏-*C8C0=R2eNS:P4G{#k6뻨6lZDnu>_(EOs;@=xWE氳۠4|ʬ#:ºUGS_#I? mKL{{̵e箁4շn R=l7nf߷.Hi\N ߳\<-2ٵF/Bvfi}ٚlNlOaB=?39vȏ_ޔM⃧:-]'Pտ>MPߐzxKc~r[kR*ڨI!LhY?׃QBc^jH~,Z{~2OP6,,JG̑b)'<Zp-(k' ys~d ZPR p[W\9+`"*gaIη_N)o vd,Β[%a l"6Ӏƅ=ooZ5\Bu >0erSޢ!''A93, ioٸ }Nū% > y6Ƨ9D>iL A7m%P@Pݡ/bL3aOAu|>拓+m1ePrJ0bj{-ywZ|L}E,+%FO:4> 4Kg_G_j3PlݯjU{ո\ݾ1eOYH]s}p,bQt }gc+bBWԩhSv6h8t ،j .`+ʼч:wM kň)w\#AM-kUjGX*ڟ^:1C5eU N:?ڰJ@phmhKjQO~CZou2JF?p}Pr#O"\iS%jLn"VI3 ^\O+#o!HkEr8tZ=޳zNJ'{<иPsSAh#9sERKѡ [%^Fsf@~-G@se&5/<7NLxf,@RĘZg6S%U-7\1{5T}f鈥k?(+>]*6rֲ5 _~`J tX;`LլN(}~jNT΢d[<+N*_pk1>fO7|$ sQoDIԊI&',~FSJekIgyTFnœc>Ioi.dr5UXg*9}K7Ÿ~:UZL~2黒77L4f^C&ڎ!\jskҕ{Io-D,{WԗVi\n)x5*{,}95Eܢj_v 䥽ZhDDfm(]敖C:/>oZVj|-Kc)UQ1RLa`ë]vV_T*ZayNU`ރ@ ) nU85#T:S( &PgpyOniiչ ޯ;Jņ DKߦ7҈%9ʁlĜUygMb **~ce)g2nZbRVn${sIO-e?)fT=RUnqzdB Rme[k䘐B@v^G`KyMAogsWȋZoĖdqe(M? E^^%|3yEh! M6xُ3Kpеd4D^zn3г$]aku]J[dsk ;O!HKb|iPX uRɉR2g>S5J CKkX)N|ťɏ`~^T2SuX[AhtXt ΗF͊v5&V9b00_1YSk8\ת5O nU{ =L[DEwV{j[6b,Q ^ا&ff kJgEҒ]zlYծl[̑$*IE@9s9Ϻu_ƃNz֪W^.vw1]reYmn|},U `r?r;:t {WiMSgP'8[3>A9maK k2Cnw;[~Qa/YKZ]LfAM՟Z4uS4PB~6sjlKgX?cˡrjQqv`$Poh_+i+ݎ#qKJ`w2Ћ)#Woȳ/7/Oߵ9#`K/ߊe:ޒDy Fb*+ T+(2w%!;EA!!3i;M$K7KpM+^:U{w1%4dOz3nݭG|njQ &¤vL'oꟕx]qC9Y:;#8x1Ԗx]/ uQa 6YL^ f=N=T_Uڕĺ3Eq57(q-ùPd~%Idݩ35U\2QM;'Ũc\n 7#5ބ؜mgx iML,2tq$k[lG.,`UnPlz*ECz:M.w^'Qhȵ;כtΆk1G/RTm.ŐtrںFR+3TX^][a:_w6>fYOtgfX+VJ `mYfo&;?:(ʍWv6y#'GZ!8ax$3b!/ǻ1>CBbTNdCiدFM۽keB)zA&bw y>(z"K˘?/QNB*TA|le-E1Z #s^<$prQcXh;?Bz!̍2'YWpRe&U0"*" TȰ,itܖ!&]}9(&or [\1/n}Sb!I#Nw"jK{ Eêݤ`E]9XY㲑LW'9mI̍'FD MDG:͑sèvw%!M"g4rV՗sӸN㡻_ew[Yxh[+U@m<y&z:07 }*}bbO9<=/ydE#p'Ng'_/4ϴ4jժ΀ÓT ~5 Syh$J U"4R}!T1 Ҭ\AEE}za=/"&? H2cW^0"ɮxZ?,$dA c.~L8OPh֊wa0h BM(ƳbWBY=K1TX8m:.lgt$xjiж*ljfaI+٦߱xB3J*Z^ѰבBfݾ#66 ^J+/|q-$X#)c?;8iߎJңg9Po;fvCV̻\>W_VlS0=Oq.~r'џꅻCͣoD^Xk 14Pk/yF6QUA(Vv-Wx*%Ӣi㻣_Ѱjst4]kfjóh}d )n\:Hjx-߿mƉ-HdMn^Yʽ 'J9_7~4?ijaBFw2\we*X? ͖]']8+] *~.hJI~!CՇ?6y\mzsڨsǐL^#ʹÜʯZ9ts1WCn 0ix*·47$T`VIQcG;us`y d0lrЕbFB*u?4íREZMj& !+܃E/vXIniUkKoP\Ø) M|MM { T|~Y/3Nka\cRY^hYg!Ջ[]6nrTp'_6OǏw-/fq=LSdsŒKrAN%JfC9. 'uV`fC=P˳>sƚq#SaxUs3 ^K,xkq׃@CV~?{ =RuFwx,g'5J@?R@gsQZLE2k,iEg#0qrl2zva'-ԣ'zTŻ|ś}]>'Z=X˼dj=.|nڲ6m̖ U,E)W*0)-}.c|'BԚ j6M̊(Q֖fޗwQ,j--~K>ڔ!#p CFG*gy;/è7jek%j3ՌRW(:%i A 7]9$:Q}m+vKa`va%bJaL ~3 ][ z.Pa]Se89C(W+yU5OBh)9⯬{x q)ZGzm5q4sT1~!m-7R!7QlD&/J=ürfE٥el7 UU;5ƨZCS;Zz!d3i3E^ejW''h(Q>Ot!fE.PPTص\ zwOe_gz;KʬB))GF[JFb ,&\rfQJ$XfOtr=?%ӊbI8% +"W56)~ bMs_Z֫v'`M,7h,GzHޑ aԲqQ7.p_˃2/9?U P=[{|: /WH9qѺ#xeZ$pk\d~b$Vz+&?s0#?ܞl* fE_iPmDUh߬/_Z=xAr`< S+%I8F) __I&@7e )FgU༜)j1X3ʡf곽.Gi+A eȨA`O`w{{yy ]}QʖkQ .Z)R٘2FUZ{Rܭm _6]3j] :I>99jb$3Y2K-m̕1+tqC)bYOm?K|P{('v{ !/f6 ^aa$W-e"Gvafԭh:1TҠТ[`FT;Mc5:X_X2cKH#^T^](Ⱦ㬝캫UO+K_Y-g= L.Dt}S1U9rIQ]u6cĆofIW_F^v'pPuKu_[sqſݻHsKC8Gw`$WY` $t[Etlz2WM9W -!2[V&;r %'t: sx ]n1^)Q,v^3fI@~󠴔w$" DŽ_MoI=gݪ&ҷJ_\b+8ByĹ[7TXjɡa˓shNs8: nXub~8koOqhVZj3p [{`7D94.m~HN tJP=t ؄'^_جrge[7K>t2fH^=GW?d 8hYՑYH=\~زj+ 3V*uLjwn\qОv-{rAF [t_UZՍ좥[(QbTcv '=g Sx5iqJV[hQ,OnRH*MP.jB'6D2~rI<^/tj}wr-]t-{ݷ?57t]Q>?Ţ ~Rw>NءB?+ JG ǖa`gTΜ55KS0|nR裺/ԱFyHwJ$[Jdn4`\rDoI[wOõ}ho;Tk1n3 Wzux6CD H) =76EQM |sSxjVlmԘ3.8RunZꭋ_ǡ-'so.RA53kXEQ`:q>IAӌѕ)Vk-wEzNb3a\n aXSXe\VnlL_<ڛ>kPQ%][RQ h)^76 1 YّηijR_S|~.zWnBA>lҮq%=\/= 7SvPsZK}j#V>\*suO>kr* pVDOd(%^щ0lE *'ol0w_ZZF0_vT9fjn>^eWI 6TV>^6cʒBpEf'&ПkFˑFhO^Ncg*B,nbnޒhȦ_v_VafW:Jw`źuCZ䊐6NϟK-K]5PN t5ɸp"gtdTVJ?xƨUy&Kf@n/>3 {)Qij){Iy0SM@бsh[}(})3_ujAZMmfG ɀ+FK:T?-'UNߦ}#V#W_{_M-Ҋ"Icu\/c?!T 1~uXZh0@u*bzb TBcI|ξ/Nb^LڇI; RMM9"7i E\_y*5OEcYxشRIf5뒚W*!2^dBo;_uŲE">a.*wpoUa_aluϙ'*UGŕɹ E| ocjն&L:Ö%X}p*b~WD/|i\FVƵt˓0ʼnQܙx &~5LM4ZHd:qw|c3[9S\?O5J6m HQk Gu)>6fƈmXg~ˆux^ۮ$Ĺu|>}ޕLP0:sY`n@dqU 7m C+$w;WE@vG8_,a@/D>!y\0ԕ3>A cHg$W=#l9uqHɌ6܂2J<@5'#ÀՐVEM=4E^r~ȴ"\cWd՗zS#ّ1iyCEֿ˰!dk3kWK7s=nw-YMsm%w&~#ǖB3T @ޯIJ62JA. _+w_@V 54\pK"/I\^N_Z@%wb0Qsٓ3ٗ _'yJ ~E](aJZ=Z\6o -y{LrƑƕ 澛V;'7·- ^HL񬿒FCP6c[қm팝Y_(IH`Q srŏ|I,PRkT. wro,-M1ek^҉UL-C 4y4Tpdlj j>D\^1j p8aP_6Ibp8VęZEέ "%"#%yb|n>[}DK`"ͮ [qݑJ_O)_f~{R,]:2zkf\z@\28zۢ_DU\ n3K=b?'ξTKT] SFm Vs[O='Swg2hB˹bx@%~~Ee:q .[> VY2Ч q]i2eb׋iVPC],ep Qjt-TgN)=)ɹϙXކΠ]xvehj֝p*Jʳn1 F lȑ ,ˡ{8XvZ+`4 '}l=d X:@+łHZQ<==rz|I+S˴=[ў1Ҋ F VGk㏔V>GWq`/>~Ȁ"xiYZ.E謨,=FA!U*S?!KrrxIJ}B5gQv][p_yz%]Q揤Ue94PhL,6 y/ngH0iK.sp)>) bgH JXp&UM4lR֕b-aCVw(6U GypQ7޵!}~G3>`*#!p38QHCU,n}6CD/N+AQ|Jc<զtΆRVS*ě<.t34 ٹ硾zR}uŏ_­Ltڅw?./JR&ʯ!RPNܨ_'6$ywGLHg*}yIY&Iݒ sd|tSr,{9_yqaCq޺_崔&wU)cC^zk͑5j7ؘ&7[e>o+#RފXʐR(sdߔɍDn_*C#Mnp*gP ίJQmzk(XţanBW8kY(]RٲFƓcn=srkG @Cy#pYWn˻~fB\0mY:< wh-s&!$ F/eoA;;n3D-8hL(b9Ųg&3\:G]=H@OnY˫swcY̵K [۸< !Yg.oX\f|BʳuuLIS]bUeuGA?_G*nZCQ5 ׹_O9_kVcFtiù=H>A7}xܗAiۘ):V|f+(4$0.T͠mLz}yH۲%zTD93h9)qY!D#p$Rq-ї'\i[czs4=!Kb ir foqa 6&%Efa({Ӭ%&{R5{7l&IW(2B{kpQ_]1j2Z&udžև )!YDPAW@yFZ}Sitb>WkiW (jWZi=$sK1\ ۾juk5pŽe ] j\5ΓibhO[b|d?`mBaʡ[D o@dK PmiÒ&Oi.?vQ {<;+6S7~fuS |tVYV7 4D|yZ-N^1xܚOU r0`ٗ endstream endobj 26 0 obj <>stream v "1w}׏0{[*4A v%D< #6BOMA1 7z -8|hcxo6 fhpCmIWX)/|5FҬ}HrwiŖIO\BkJ{Lh^!Z쌞p%Xt$aEtlE^LMO5Y2&cmsZ @#yy25Pq˼;TAp|6'nӈgnۥ s㧧u>۷"oÄGH67@4~\'7]v윗ow i:!bzs:R%"c3Vijg|BjE9L4=hG o"ֺYBDUCamOb^0Iw#Ш9녝d ,o|ӥLl]s^~ vs"VfO9ctܾWtBsF~UJ.U~'q{E02P53FEgc5F08t$4-쬄6;>#WQBWLӑ3_fd"X@$l5\lփ YJxxnLl4˪Wj ̨VMJR4"Uhq=M``{ήqe#6.؄tlP#wo½r(?L㯯FEQxv17ɪpM_78![JiۘFL{j4˕|%>9tAR{uB+өGH-Tcg+<(R~|Vz؊[N0rda>Qy3Q(0$ukqi=323ԗE*})ZM,f n=wC^ VGpǤɮ%,ѝuʤP.rW;KRwv^ -i4ptkC1YEKK-uoOqwp~PIf"jmCs159%ҩ_j.٬9mtHDx_6\R:ih'<ϏP"ļGZu@Tfga#2?2WrPHRd.eXjKJ3>&+/GȯykkQǿNkg_y9mZɽuTzד^3Y{c;g`8 $qvC15]E',հIgI;gHh^|i4 ]{@wLF23Re?NLcpo hΏ/mq5QN:ɪ;0巋'{5Ef[-?EP1({u>i˙Õsy탈|1~t[uդ_^ ؐέү;wD'7m|wxz,n_T^5ݸ$Q× >ƺU^щLJ&rW[ܺiԵO<MS{>3V޲lsu?GɪAC55^z[Zr,{4tX7Qtسګa,sۛv_[bVƑ;S~tvKеXiڵt :L_"{#pHZ~ίMQϝ{ _O/#5gX%gV]?ۉ *c!tFhץYfJQD3R?=k*t-]r v*gR : ܅R0T*'$Ɵ9?L D9B p)!=/b ]DjZtF?gǕΫќ^ :G z HtvUiE}At ^_>X0藳Ɨ:ԑ  ͮ6[i!}+>-7a@mUbs9mVVX+EdZ[svvG׸J%a'!|THgi,L*UѸY1!^pUy cBi }=rҚ?#&4f-;\~TtX-Q[̯{/Uf/(wX5c2ءZFcgՔ~&0F(jvDo3ݠknxڡ3|}zL xN6Yta@{4j%uLB\QhMh_X~ߣ]= hg [ |a(Vعےk; +EɍBG<&#wI UJ՝ή]vBpxKo֗w,YbXsi|~ t$;ڍzZ }͸vW[D*ۍ1/o¬vc-Z5Zg\_v ]āj-`-fǡ,jzz]rFw>6I+0f?mu|YWZ]іa:CDIAv–$znn`;~,phƼ[n FI_Vg4ToBW#xSIy.{QZsgouC٬4WˈJ~zJ?liDWZ>nڥٙvTQ\:ȾM?{x=+kИ)TgŅU#1l]2ѳ.'Fh|fﶰ_qhp27!hXY;ϖdZB{q]Mst)\7?u:g'Kٰat?i$SV^aPPP-7:E)&ee ^`mΓ繷7=NtO<X TRH;j:ζ>GueBRx䛧q'?7W9TCo<. -z3E~YYZ*/ F[W,FyD{sO:z/X_D(mEcoaP\2K8xpo\aKK1]TRu]mT178o250g]6ksV2f>AKzKɦ݆s6֢W߲Mf f1+ބ;1B5Ok`,{y:Uu7tP/w׿=֪xlh]2jŸ L._xzhT[KMTkVl nᩚL+ϭY~V6]Q V-5_O}&U!5gyF&izDAoXհ>I%qzq;}E}QYr2m}lxN[uʋ5-DVd {fHU|e]j{&S "IP_FE@1;+bîE}֮F<MTܜ \?'[?9N?fn]po#̜XPz"tppVޟ6E7^6%Q0Dę@pE@/#656cإ[7.* ޯ`˸$f$RfQILY;CO1ۛqٟ]Fp{X-W,>JGPoWhZhY&rп*4/4SO=mdCWE<"8l^WoAO:HS;˙n<srDjk²J$L|{z5ƶ,%Isx뚫wpa!iahC`TZz$䧢$xa/>n碦dy;œ߬ڕ`oA5"$+#N*hk魣*zM V?o:މkD5iJPB~ 0~6()}~ D)Lwk]F5[\cBXKr)pn;:mem_O#@sE;)B5'l[hgdK÷U#_+B)-17;\7dJp}y7 8'jc@>:`qշ =w o\Fҋ8d/FN;Ç ^gʤ+P ڙ.Jⶽ> { ]Y;oi׉9@w1kXU@Ļȿ_jOj?+a]0r5D"% 0$.{*d 5ޱ<(װ5~YC[\h4 4Ŷ ֓ \w"&)&l4G_a?\'e_zr!nJ? @1k؊n"~#nzh%sO_+u{D|/&viYMl@jdxsqbܦ>~TJa< م+ɻU s6<5pI o,7yns a}N"SܺaySfu+@ ЛZ @=\ρ䎲VWs(R>*T_% ǽ>M6TI<Ĥ<< |'\MVuJݮn h't˱}?XYM8.oGCu.BQ_ܩG' V/nV׳gi1Ι҂ 0.;(좫g۞&Ni>"/ѱГFkwX7~ʋqyJΊu;wy@TIh6bW,F?~?U%4GaQ/ci|r+3ΪP~n&eڦQ9rUtdkkzG͚=UϰD~y|Dqsۏ[1"$*/{s#?+!=籓?mRnS / ݋܋++؎IwCrQԲsﵪkZ{R+V;Ku *y+d=6dLjBMK@-\hQ;%Ge}Eӂqh+:L4LW uXy )ATXVi\!e;>Y~ZA3\GC61%YX q(,CɆ\lfhe"N=W?hȬ/;] Z05mgXy $R?[ ߮}|^J_X=ޢJH/8*SZl=uCE~ݸԝytɧ]AA'R"*Prh#d5t6`4-&84Ou:5MvZvhjM0c`_%WssT _ֻwH-i"u]ka)&>=+6ɵ2;3^JV <8B^V+oZi\)kwK,B~*$2M9omnN'l묨H6Cc<3~iֲj;?XlqQ? `bx6|i7Fb̨udqntxc{]/o`hwciKch W`G_Dj?Č;/=3̫:'wف}G_؃l]f/hƽP^(Z4Q tͪm_.8%.Fo-q"&ؿsS|)ghzBh)È^x Y|x>ioPO_$ ~#z H7^fI(fF=Gzcl>U<[?p[,,/jHK2/ߓZfrE\}\)tW?F$&A~~ F1*el);mHIU j.NoPn6^R94NvߩO˚nu= ڒ 6&Iӎ"NקcZ|融\6^rܽ֝t-BRB~Vduݫ,oGWRNѽᢷebC?ƉDң#c:j[_t\8Oqfy泰Դڸ6qV0"atnU4GHv32hwl<~ݪU{[3*oo jӉq=0GާA*t/Jn,BCDǑ,L?SNK7Sh4aU\ DuؠdMcdw q8o휝֗* ,L7]9i0zzn~F& €;Ӂ#Sʤ2[xܒ#x0QW{~:T!7JLh*o]؟݄y.T %m$(iATµx/̦4;%zoҩmR3sEOAs2b٧U#{yf;AYw_/oZY}ZTڴEpJ:pFi},Hf~WdaacfWl+pMA:Lomk+j!K-ujeT0 |o{̕{n|?F\.pZ=[G9uO+0qݎBύtyHz.p`~Q RX8䪍=Z>-x>&WNގa"{ :z-pm[8^YSIbҊY}y- u{/!KlNƢhಙ\j:l:b6vrcKC`@V,\&1{ RG!M\NV/a#;>!ϗb TN;E՝lYem,HQl}.=䬾f+f+qڤKg\T^n6sLCxI%D3l@12kONvö cYK3,,s1ɘj/͇[M#˘/yi^6ͻw}ο _C[uczS.1z#‚{bpY!Km7K>ZFRL/>KƝ V_yٷhIAvjNԹh/^o_JXt84ܳ|򽂙䁫\y'׺6ݽWWk9-$*KyfGt^O~X-#33g_tݒcq/coq')Jۛ)P[0jUH:Vo8؏էhgw~9[5eGL0*v夂MKm3=8 8ұ_2\1 ';UaW(Ī3Z!o46kIlL>]OR]~^+) EI?ԶH,ynNЏÈL*܉F^LGB{{)_kr>%w9RѲgvKٔ _mt[u5B1Dqm؞|NOA6֑[\BbQ<* 臡.{p֟KSf"%-}+2°|7#RwPR*NW~-/#a &#D)'h eYuTjwvپC+E'35Rꈯi1\C@̼.MK*/o*.]&֬RE6hqi^G[m ܁;Zҟ(%xb"dݘH9~@zoRXy uj|"%}K^NDbZCe֒x=\j5}8:QF6uܿڽ2 =G򘏻P J.'hq Sw.ޫWT]G]ҘMKp؄k@Y%<ՓP3DŽ\+R9M]Wak1w[[0 S{וn&JzpT+,ILii}t}p'G}vyEfO- +Eh7p%URg5+6|U5D&1C0?`c|p[ߏj{_/ZUnCvC4c.?Ó4$doKOZl=(o&6>J>ʉ0ȖF:]lZ%,}d|fmL)փtu>؏pJ,o1[ZuTudXWpْ~ܒFeXe`%樓 hwJeM7 r8(İΚJǠ5 ^]ӴK͝# u/9R^ng bOccSߏ^rk5c𡬯tu/1ƸohZǶf#x2_ѡ*O]*@_ '_-=s[M)WIw&A#F:FܹY6*|s=g#ls5㽁uwF=ey6:FԔLq<eVl6ջ8`"wlZo2 =?>oO+@bz=2H.c~ŋc(+X}6 sv'M} Z"g]>>B{Os6Hxfe#W~!^Y MwTIW^Z wYuwo{MfI;ѷgoΗS[~u3x1ci3,0]8/ 5w=O(7M3g?NPWQ(AZ5šA,['O~ɯB"wꕱ[|[} .lŸo$8*Þ|T17_fصV$v0LM |_da'|yѵ}ߔl؇Bbŝtkd#Aj䗷5|Pn/ N ct(8i&;:E?;$rQ;'WΌ#0[`Uw^9$O\݌@sz>s^d 2Q qֆ*Eܽ])+=^{4G` E7^ˤt֚u+wo$7 :7>އ)6rH .Ǣ=:[³cZl: o/7Z Gb%n&=|{} esXLg1lI$^V*n*x\)F]e|zT# Af[;&WϾܪ䞶GޣTưɥ&{/HG4`j_%) hXcdҘRzTY" h0gGo替қLTC YX{,+r_DaAt# @PiayaA~b3YRq_ڛ}˩Wp$п.<_Đo*n; ߭},eGd_im &KBfB&1@,kB&}U"J;!_ ;#X? V`UB1M)QL|I+dП_đ=cLرf?VuT#UM].#p0'#0[85Wz#\/`_)KB23&zt: @F7E,/"@fpSOC7P8I}zhSzvwk yW'ٶkryU'ڬ*=ϷSC SKaTu^oܱrQD<0vohzoO2:ۋx!4m k]ɸ{|U򞸜dkw̍(n -%:؅hp\aݍS*rΩ3]'CF=Hl SeKTݞȴ9ؚ W,aޣ筎~pt>}yC{h_g/ׯҵ{L<苲2ۙ,`8(qޖwopQf4:} sz~i$oojӇScZ7G(}ayѢDq;vpǖgYYn KfKOrwy n~p3/#]'ׁ9msߎCa= ap6Ҩ Iw}Eiuo`01qjD_=WH.ݴP]Rjka쎻$3.::+ӐǍ[-kDWV>i"YG҆HB"N CPYt:~5J2)5՘xu0˿zB,2ޛ²S[N@2q.KCn߷10> 9Ѳr/Y!`$/PrjX >?kIom)Y}B/328X.ll-a]9KKW{. UrQT7.N#MŽ lvٺAe9rjrk%?c"~ zaj"}0* v[O֐%7e3@.W1.㨮cN Bdh,.ʫ- Kgm*UcWr*>&=~M8zJ,nLt[[$ξ,P\#S:yQ[/F165Pxy}jltTkMMnmZIB{T'}|Ϛ(KڟeY kf4nSLl#3;*헤a͖x'iOW:.Q"6A?y6Q;PD"*~~[x_߾BgUӧ=-{*M˻nB4'gl=@Ke1zlGWqnz IJ&*nb[r6Ԉ8l)<՝Ǫh}lܞnZ\|phc2bܬhƮVOm[c3O"Yz2Ny3kk#l -w,vgUkKf``3[k_.:-φ=-m9_xh9G"fmWc8R˟##kD ѰVǔVѾ.O>nuVݎFz x>P>hAiE1ẆD,uًV\_ۗexVW7et$sYg*1{Um? f]vnrkb@es'1u65K)]RSa5l|f;@W\?0!ڐp'ەaw\wO!uOFiOkձ4S5smu܊HQh1}cY5zyE`oQaCbWL^o'|{dg뜩 xġ/|=D˞3,m[M=ͩ7Թ{G#vXuShf=h.e˯Khu9R\ NЍ ȫ멻8GT/^E#%NקFVlEA3Ѧ.*Y(8' ;77fE^πcj5Ƚe@Eos.:lJ8WinA3Z^kUoW?w[9v頙޽>\@s$^%Oח?l}aqQdSC^ ~ģ>3oZ#@(n'h?Gw; aPz=APK6H%KΛgu:=5jDs˫Xo^hGmf~ ڤj" fש~PFY߶q{qL&1C.+<2f.ݵ\ψe5͎_T[çjclF 8q;'gcT{n` sg؂?el,{ >򂿪?﷏Kc5<">]6PHw*؋PmB=ʛ#p{\̝ޟz7A9@g$eS{OʯX̖E.7 aJ\ jPAN:YDȊ8G+UMjDžS(AW[` 6e{ K}Q{h[XH=dn4?((恪OOyZS%-Ipq׷Ud4~qBgQ[nn+^n]in45j!o? s[ʴK'ڻׄ;Xڃz?,_ie4-GU?m&EG4ssI2b[""~UX 8? Z,q-u e,g/&`۬9뉐(OFbdaOa*ȧ+y59@cv7 yc4>^b)Kd'Wy_s 'Q=%3'/m\w*xWW ۈoUjJ3Z5kX?-0nV5%ոellxWSFXL&B-@P:BҢϾ|R ޕm:$uuO Zov[ ekuI}`[]F?]2ی9VTpq:TФ Qs*> sgjl]SA! ǎS  mE)~=1rlO 9.~֓MKԂcр!ݖ-eϩ|QUrF3ԩ%s{*P&%ҏwcuAS%SZ5n|_a{Qo8J{veu*KӶ%K-"G~hZh$?aiv=魱7բnB*6]+"cwXFNzn#GFHI(S 'ܘ>!݆6_WD&<[}֧ug,9d!e~^ c`]9QHna`v|4-0,cR|NhgЇԃYU^zeQ o}ϝS4XIa;gv g*86zʂJ=nAY+]/ nr# W\ba*_:1hm)$݅&y2qߥY/,nnWe&ooPv5_t`D1Zz`㠞lmIg+OƒgN8n{nWSalH^ks0*{maYo8(L5שFA(22X^uYZ+HxW9;XM|qkWJGR$۩M~; C51Ov00FLGJ9*s֟(nގ޿^x>vHͪ vw1.jj*Nҕʣ 6ḏI557wRp(i/x 8..["W\Ôb\hCV"?N+ڈE ]IEbIMeBCXWhakr[=x;6_tzO8|`3Yj@hEY2$ͪg,\ENPFhwTM:ʒ1r5h3U˫JRhn 6CqL2Dʟ;>/=Yc}%ofWҗPp/;%Sk#=pŜ|Q2~A:e5_Km,U%Ez>!/:|$Tz_4N"7LYf!n.o,"ӡgIJ4 J$TO-:!C8y{v|q@G[?wsmբk~k͉mWIDMŇM| sRZ?p!.G=#кdϧ9llz+۞YϢ]KOqs{oV_qMJn>O֠TCz0#iP'ߎt8Ri;6~oh@ONzBke,4PzOwU\ ܯ璣')>U Ñ#o~WGŮ NyY q8WZW &V-Ss%\J#W=2.#\P p Izm|eYZ.?,oRy1e6zl%0 Y雼zxUš>5UnkWBLKKP@} `;(;U-Sتno֋݊Y Nx<=52_{6c͑%Tj;n^4mjoH5 5f̣s.4p"g"<)~/ivrr7ߪ_ aw[:~1=4[ٲuJ8=idmXO6^*g:rh9O1aWKk\㺶mmCߒOQbXΎ^a6ٔzA6{l*ʯVp>u5w~RsԥM} Mc_IЬr0ʳ ?Y^˱jAox?6q4UA>ָҤgt014+CArx腗Ww55{7;a:;O'\n&y䲋gIrbmNM'j `:o:5N}{7T;ʫÉnPS Wԛ&lJ\K ?O]qm8wWnHX]/y*ڏc_z$jrobyOݭ#^T7Ҫwf XB$3\y9ٮ40,Y5#ÛQ![vSML[gd0}{]Br$hEekkNNVGߴM=ܱw7U}5hosJqUg&(V8P׺rzi`JHTvPa)JHէעW€YOͦ`h! /+q{u+_L}U Uf[¼9;Y`0-gaYEF+m}3Q֋ &'N O8!,Ž/h9!c8։| ]we~hҠsZoN{/Q\v~lǿWСT>7T:**qGD rw I2qh^Jtfډww!7 .Tx/ܶv(R/2#{i_gۮ J-H_B#=^g5DGs" 6(^m_i| +S&~llZ4za;|h 1dnoV~6Y5ymenO)j^=I`K^Ez&u[&9;r/,Ĝy|Żsm+:؅^e Fݛ_,Bs}{yiF~h1-zS\ N۶$؜EOOc:K;!-/J3ȂەւxxM*s`LT޾[}uU% aڃ\@> D$6Quu=/R[M?>Ӂch%a]ׄh%Iq&~3J4 &\Ƃqςί{U]̈́Pf[tOc^vGї"6r[M1W#k%ϓnf3хZ u2*^Wa_nS =ݍ?(-4 MDtӧ}?W լGqM]= 4#Q Ct {ot/<Z6?Cv* &LdWNxt>I*)ٸi -!p?-oq@ { /&D<hZ˯xS9ӽbX94MbݒGUrsE-1L}/Ňc]"R`4gXd`cVo~7ژB(j:D5 ;h֢WѺݐq4E lUł߾;6.S0X:7K%gig'źs8V< &"鯊[PZ/WB;7iy>d½j:nMf{|*zVFbua~ 68 =Q}A\ 򧝒P־䭗6!>k. kGgG!ݚ._]u#|60V2;N _BLGjTlI\Nz(E;|o# T\6$mq\2YQVu֙rIaX;SiUJ>2ЍdDg2V+2f4Rb!QxJN;r6aMMM= cl|ҁEAN`E(uRiĹ\ͺm;lfZ\s?uH Y{O8c /; 5*!s);]DjR6yYDy]W 1{8ȱYłCaY;@g$Y.LW9{Ey!(I u!?ĺ& /W3ݡtcP'*tv~`Pvd&6ggƣ쐯 *l|84(`ZRu[_2~ %;?* ϡ܍:үE@zh־Sd|x~K.qXZ{]]>IU7ŪӜ#sퟻQb7 v&N]וD8H% )Y]/6\f MPhq'kt-e` Gy0ɧLCo9Dݒ>^FolѠ V812e>s> #% fs> Voтz-Ep:xdڣMo%9wg-Vy hmm$ch,WJptG՗Ȏ$vC{؇rU+T5nE:!J~=Z_6m47{ᦛw}&bY!wj J%@` e:rAUH͙'Ȇzrfo} tnUa[_ntI;؁29v1Լ.H%̣;s=Ț%7*ǕjTo6VOU%*mYܧX׉F͆ XbˏNz"kWp4XlK-[[y<U-ckT%zB_*^ GAmn` >cj('VM|^SEUv(Q#yyPmZέG^=4}_>9| ^y޽3HT G KBv8Y)8 :Y g9uX&0wQDZC@-tN35gB}U NWux0X4e7aK&567]q/"݃S٣]{>Gstmpg"i^|9; gGI孇4U)+O+ީǦ_YD}#9~{Fܝ$UtVi0igYZ'@"+D&{/ Ë JMSZ,۩gQ<nzH#$j ތXƛ|=:U]"$Y%Wx}4bxH?a!JaPnjaO4<RkG'[jPڛ4MA6pqaa ^It҈G9Q65 e]R`Tmx[gէ g8{(|NXEck"PXf-F՚3A̡ԋ ] BF$6L;yZ_2ރWWu'/B:yY&kݭHw#ϥQax2 sY.뭻$$Am=]{zIJnvX({AKvlHMt.kcBVS=^ːRۣOKo5*,J˻ 0}=bCsݓ%gy"ssC$K6Yy%MRrZ>VFYng{q۫wKA6zbi v#mPKo2ܣ!ScUh\8eݐ\#&6}B4\& aǦR[{jYb+C}8 6͏ݡڌQ+]NwrrC榙06uេۋbn7slzٽ6Ep^w<Đɝ6dr[lC-ՐQ#wDu%ߤq3_7eҸ_՛iҸ_///rboo~Ĥq3ͯ sbGo~ؤq3{!$T PQ'TA:;]DXC]ܯ)(կ`ft6oN&d?QvT7ұI$**¬ԱZmqt06.^*wSrP1퐗l%jI5xg2+ݻk _y<=V3Re3-Cz]?IRKA>Q] i7+:eugn[$){78D+ؽǎ*pwLd1~Z~Vd]zj\xזެyYQ:Ɋ-r 9;p|wO\~'t3$??[K<<}7# :~4SRDQat3bȖJ7!YዒV_?P_ñwVI=:qC+a;^8__:S=eD(p?"5AŨ!Ց]>}uE;MۇȪBAl9+4>H_dOu}l99eRxZ@sX*kk fyᕎ&Vc 0&.@k#d~]>?_5Р59>jV+e9VJݬm!=Wv9W{l] e?"EyO-Kқ\bu&jCӚr{ѓf)iƁݬcWA3vGfk 3,h5oDS[s=B~ƜQ&Yw%u6d<֚ +(j4խ)[5(!Ib \"}oGf؎Z:^߼͵(N斵ESky/c0ɛ q5p}Y3Yaj]b9p@hs$燨94͔l،/ڭFU;CH'"as#4L 5Z"b6Rm:0vHu?tKȧ/':WfUI~9Hޝ9X1>azmytFxGY}$nS7o)k~u^֏$@(uJ$ vlB֡P=Ǘgr{; 8S0G qX%) I%/F GiW~1a=m"rc ȱq`:8WQ'{Sm۫]_S:Ť>a:g2Qoo4I({7pb[o~Ip~Bzg4 ZTOp~BzCLܐZo~4ɧZ8f~}B!?qy'3h}l/_Tpq^~nH88lg]]27e{}"N"KI];D [z]^͏lu;Ea t?g,*%/K 44C _9i3"Y`rRw>d c78ے_Y4F} [G{m!jZ\xgeEI_IbS}(G ;SlϽokmZ}l"hIA|u{}J(3l\j9#7Q,@MuĨrԗ3+ȯ-رGhQ9WPp)/Wؽ?-JKs䯜T.洂 x$yv¡Wk`W9{YO/}0{d,Ȥm{bcYL'Ɲj!IB5]x;U2~yj/wwZiS_]`Ne5kdqz(>Rgrz k$dqتFEJpEZWFn+GAntNM/zޝŕϐEB2p$ ^'.9}?,Q=&= 4#~GΚ=`S|Y,R>}= өwf"%W7HқWE}jܣ3}]/`b^JZ$bŪ.&`KwY.%Lbb9@b}1FF0Χ"t@261q _ځ+[jN %(h~5rjlR1j3 U}IVrc؝ƒVb`90(ȱ$&ts6ܒ~pĨߧQX}|zDAlRu͹g: [r^n;wy/@eIfkԄSixOZ,1B OS$x?I,vCE.!8y:ذuwI=ةsfĜ&E&gzr}c0r)k'AK1hS׃:&.a௒㳅cv՘2]$!]΅ؚcҨtGQCv(FtxACl2SYc\*ya0.9/LM͐ I5"4YOί)MNqY[j=Y`*Z5":R5Guؙ7pKknȋڴ!_%o Qξn%Z Gf_q5Q2#): &#2xtn@J{/n?G mh}m5zh^9BBΜRI򷻴2Ћ*{eiMX5A[oV_VYX8}'w_x ڛG5_[9PTW;h;K[0X&eλ~ѩyz{&Y0AWJBezzܿK,|?7p&%? E5~gۛ_gRp&+ZoIdʯzLp&c_6iL7K$F5Ũ)ƨ붴͎υ05>U^ؼ.կU+kIR~.j|h|TNi}H*w.)݇I*tu,rzt-쮍o44m|ɣ' )jJȏПvtlh<NSA\KUOb{y HcAm u$Y#n3[';CM5R)l}>]^Giwĵ{B?+ണ܋)L[52JcE%`"pk;GQؤyԞQc83Ԑx#]iLϯ{!TMy|r>R9d%Wvۃ4p+L5Zɤ$\|؜ l>NŒs TW<1~D>|IEM: Á.݌<ԛ6+@,c(^ c~Z:7O#[T$ K:n_7O(1&6ZRiN{zr-}m4GfY|LM0Tvsģ>@aDՖB b/IohJ1ꪎG͍vb}W<3&Պct} ;J) dP҄pnzNBRR]F"16?"s(jhԌnbRI9G^<\kZS4ڭ9uOkK(K.0r!˚e-.lG<'IKFc9l~C誊Z k ehyԛTׇI͉I~-UfshT F) E$6jԹUM'%G@gojY66:f)z#@-ύR/}Zj&;;ܜw8IBn$n#5{=>\z"d ن\P,D@xVQecNp3Sn᣺i_Ė5Ѝ$u_GB=t7z+RzUY g&w($+A;&6;#V 6j;qsh=\ rh,,=!:`EYiWgȞ/|(^@j ZKs2Lt/2Z8O9.g`  GJ/h-nb֖fU2[JV4BߨR&us~rDQv{,'2|yU:Kk-(K=-'Y{@AKR:7nb32̨ k9ܘMh1V>nl=;W <Ъm Kt{{@>;.ł3~DI^.y*"?Q ttryYЂ[?~5'e >|P3I(7|7ߊ I>GQ~?q3_O3 _og_oҸ_/&*N JP,CT/W03rMCGiw;&#clO:q9 gOOKMgҖPL/寜,&uO2eں? -2mSDPeZrʱjuMO:9[Fuކw-v8DJjueC#|]bb}nF&ŒjT/ :jʾ?ӧ-^;I^E9J81*9{;{>p ?]0&]wg]I!fV@d4g eWx쟯pT#8Z4jdO}׆+܏bʊ+hnWN_EbɘLv9>]͐]ڣ`k&,hi,F!xf<5d"]ѕy{mua0K>)OWԷ$Er<_^2 8,KL$+=CDYt,hJYXwS\Hi P51g|$)dV@}cqU8)B?TQ^].qzhsÄw]K%s_PSz+ZO#Ѕ6 e*^ij: U2"~޳@i*ɔSxHR~CUzI1j`~.ln_O7|aVI[eH,szWvdl(p 2nG#Rq-ItޓTזsbBIdsӐSэI^P,Erz|=^lt.(9#lig3尔x1 k _mw_?8FFRct$Uvw>.QMq Mʉ"+3-z$u))+.G v[/%:ݍJPs:Q39H?B~+9'{sN>ǩa%B4I.t;;%ƦЕAKV|P@3>j\I3>WiNE #5yeB9DA)z$`붤Z6aX'_$bV6U?57V O +OMun-F0D_}0uV#v`k0R8(ڊ/%vxB32jVhIӑ5.}<ߥ#sc8-=}"ۜnKk\ [5ZLG|Q`h$\E↨~}>fӨIKc+nwje@L$fe]ek[ ]JslINrl Fw qoflX\Q]ŨXAkxrYpW?7-_nܚT,E$|]as'05tip#9zޮ|*%炸̵"6ۀYX.pPH=4pEK;,O}g㢱]Xxz׾]:pZ1=ɴ=9m'=œ1B{ V/,9[{5=<(nv#dR8ZO& Oѿb\zbeUۑo,8o-v:>z`^WUA..d~}f^_x䰜 kpjTtB6 ` Kfi?ITBT녯M"t:<=umA.[%ɓjla'($gh{мcZ9YThx|<}a`c #Y^%I+7p&w8 ~FoLi{ _gRkm!Zv25@o 9jIcέsn?I2E9F=!; &U jZ _>XQǔ:tbznh^yt\zs-4:=/wVnݕM~#jGcLN- 7Q`~j0sMjtR*k>[̑Md&}rK[n`aL(Z9}yx8nFnسi kԆ\VYC%-qs(q3_.1Q}1C烻As_`p!2ಷ8:m" {[JZvl I͏"D,2F5Ic2Vˏ=g~X,C_QݨØƈ=]Rmb50 .[.̺1G_mG~I<&'2\Qd_{1Pk)D'*œ[D9C[ 1& #Ž-I!HR ov=j I0YZ*Gʹwyv\ _ٶFȯO9N^5<9Lkl$^WZy.:Ch<]nN{3SEkIfw',oYHV܏Mj6CJ `VKXD@}.I]6C͟n- jn\> 2Y#X)wmڹ_uS}mJ4nqpm;[#x@P)CW&$D!f Q3alҳN:Q`/㘌:D1"x{f|WjX'*ަ/Avi.|JMA)k:D/TY_z)a?OGF< *.vr }hb[e;7ڤ 1Y,, nɂdU&Zh]lNf&-v7*1 eQSڎlu9T9~7N,}y?ŠھOZ./U2چ| M#e " Nz o5%FLn='5t[h_\=؟F= [(gx>Ѳ`d7-@TZ K:Fb;2`w:?IH|/w99*j><u8~- LtF 魋:iSܙ7C)t^`$RTlRZJmU(VKC_bk֕f!;rwxT\}P4 ӝdj`Qmhpο3n@=}~3Zr*&-f@K| ks`&5}Lo&c2mXYkrHsfJ]u7\:ko4Y༬œ)N%ObƧXmNٯK?>"S"}-Ik2ÇlLcehq۩9;xgR :'*2h >0A`5*IS%ETUZ?j5> .Jdsimե^36Qg)l$ @4g[JhuU[ώtIY2)N:]_̤7ߏ IVGQL~?q3ۛQ1%)xֺƨ['1*iux>gNy9aD-s`?߭wnZ 0z`T!]U2C##±IYs[>-8=A&FL4<<bvif;\AۖrkOz#Ń%?҆5'5xם|~HR%*A=F%FEH S[.Ds2@!Jjš"p>۟] Π1N*=Ԭ Vf\Gr;S?-Q\&Qy] I.٨^.Z M ԉbT<_Ue;)4o&{+#\$ۘ0~?E}sMwITUX[Q-921댷g_ A5{痆1]fk2тbg3W iհCWe'l`kK?}?_QjlMq<OGu{;ap H84e~L)]Mh"FcDbZW?̒JJ2Yұ>;ja^6JvGj\sQɃFLJPQs!by:^. /&` 奁[dvwPy=j}GiÆخ^iEv/7#S>'q"5V5qWtp:[mbr3kb3FQ+3FpO]lUձpo7`  ""bC/H?0>UڵϬ&IH2R@-[$:7I߰j@/c(df49pP’Mkd /91Zq4Z`}b ع0FIvju 1ZˉiD!`h\y@׾fP9{st~-PTuˠn 4Eu HNkYl!'2Dž;l>_]6in١FLkɬZTprZn8Xg.տ(hމj ےv1(zQ^E;fT$ݹnN۞{hbȻGcN-&+*wLp))"MH^zOU27Zex̝֠t[Q<bGKR+So-.6vh7ܲ.aam (N6uv@sy%1*0 |,98]/#}<:'z㗹{rF)Z+ 6;3dps}K_KC:yCe4q6V4݈1T{Ma>|{{7ҹ/D{IYw |knV$T z%)pO NO0S_ԶX#FM~O |Ǭwx' H6'aw|)A /,zw2G"4u€.}x8~k,S>s#Ǡy+)楒Hl`h ڢ6>zS՟Z-j7<2< W[lmU'1Mrj)@O yu-{ |nީ3FjUK+Q%Rvrƾ3mE=]{g">p tX#d!KT2xM0kDb P/kh z6[G=L'HrTȁgU _(r2 K_xB93~~LIO"(|/f>95V& 5'|qna]<+#MA9|M!vƺ}֋dP Et)*rꎮHfٿK_K 솰 <JUZtK$U&RZNF{D@ 6N`w2ei"-a ɞqvPnLt;.4t銡'e Q9B2.*Dn쑳Z1UO}ӧT=?\`d(ɟD+~k{s[D~|ϲ<-LJǎF^c"έLS1Cm캛nM֏5)XO!ls< !:Je|-zi'KtEzoƉԙHհk|Ćܹ(e3*k7J޲@JvD"}w7a-f,܊ 緑{IPõzο}`W &W/d{mljNKOO 6Nխ gmv?uzn >z ¬(}o[Gv~VJOw`Jɟ<ԈxwrB8<]kQhud;v/к0YC[l6z=+쾯k.\nZ: %N-pbnbvn@Yp+3b(-3i,GpN^/T;5=jYY\ >^6|| eNwyy vT ?" #ĆH"&i+g]0jj·)#zԈyʝ{ [*,洗.ymD9ghoҸ]O?)GԑnOB(pwMoQ5&YLྜ𭹸|6nOIwjY 1PI^;Aq(Y~?:J")zi^Z{HeKl/VA40WvR+zWW'V/2d;2~l9Lw,ȵ6ޙw*qOB(gdz=Ҁ$*?r ͌PKwG>z"5^^@!Edݺ-[Aiq)߼Ze3u;48iNC Pm+ʲ4Q &Am~6õZN00_ϧxE|حQIXN\Ve±s<,'Q*w}3د6*\eۛDe|g#}% jO[y(qWƗ-(*ؒzv9rz_/L\:|Xa1um];'WW6[b-)̶<^=!.޶Iwʾn$&R5cY 3W[:'`3(;el%\Ͳܣr5ACs{o2SVKJt H$6[n8FBsqCv\GW 'o^yKIdp'>#%Px'kajWj\v7f=Y{ΕNpO`?TqԡHu&R_':3K! tGjMN,sN!t"9Z8ɾ?Bhf,6\UYl޳CF &^p'X/~O~;y%J^Ť}Z𰚬}*+\~ma}Fo5xۛއ@ȫ@*ې}鸓,+"S*w# ZvwRHv,wIo6wuzwcD=F[bf9sd4cK1rwE 17ݧ2AzviyڍeA77I] K_K J}6Ĥ/ <Шy.AG~LN➧\:;Y;E~U&﹭_F(mmbRЧT,=Xw_(ehM.u}❟Ƥ;MX}rgte:/ɯxɘ5ŋi ۻ'_7NxJ|ꤻ7)u2amUkY\8̢/}cCnPs;QԤB0[O3ϷxjQViWY(gng/R.o!z8= Av>QxKBy4 GҍQ/v>{6~?j̉[eEqy2Rh\"syk:]eq@ƴ-P>~7V4ݙ#aaYa:ZPfx^3%)T,7ۖ֟~I\]HZeL˨t9-I'c}vxy@i444\qvoj(xHͪhGΑ5*QD_mEΩJ45,Xc>Z ^n-M ͜4+A 7ZM kp3苇5n%8M w+( b]%ٍ %pS=gg׀e2Y'"jٿbިi,j\ AX=רّ.[~zۮg"i4W>Hpfy9~cHG\ *֐hg0,:-8:#|HC#r?Pj̠ai96GJ2&t! xa"qOg3W`;c wqD`DR;2?8JOL9- w2C2:=_{~Gcysd\SJشr9uܝqј% BѢt'g:F2^#BszG{ jbcsyꞺvIL\oܒ̾e{av>g]_T{V& M4qhib~2u&#~@_lCA|`1.7ļi KY\r+l2|;W;Wy?yEo~s䠷t+?n J= Ě p(䚘ȏĸ 0:I@90-_ݞWԹKz9z,Y@ݲNp;|k9j!iæ$?GU]?iI ,m0J3xODDË[u9mLJW[)/HzvVvZU X~E =UYEVZibL7U D*rn2Kj':ovS7צяʹW. ضhV;MFMnGv?3 ^H|$=M8YV@8P?z9HTߠ#}9Y>4]s=Mي9PQp_j5r75܉սt 0gy #ݎPLo%*{o:OĪM=Y{XlbC(KP(><2 _wX Ii}U͌15GSϭ[$0 %/Ơ[cDZ@-i;`/H=s^n?Gƽ:xHG{愾5߶+C֕ۖҖ7EQ;%-vtŠz%RnRj~8Mƶ1a½)AqRܻmq^~/F-]^\mT lU,U.Fuc(bM)i`B^Vɭ>:NI)&ժiW닗۰~9͝ {6z{\:u~S.WqM*@KN-RlC$ZTQPaJRDQICeQ+L_܆jbeke4mE]S p9&m$;@ ۶Lmc< mJxV0}~Rdݩl 14zn'cE1H,c:~_<dN @ 1+4wzuC4-s١}R<<I~981 E:dn ,+U})CbFU@iT~Hϛ? :ىT;W7V>r5 Mn\s,:4.t !(skGYґ9\s7j yβfʕf>F ˟hd4@YӟhkFoڴҧcKvz˳f{OiXzEK>Euɝ#"s~zL]sWFU"U3ՊG'zv%gMXdk_GKCLtoH((ZME%ۂszቹ͐=O1UNsF{ lƳ}g;{1P@s> jY?8h܃{]ܧ+lgмGwjf-{3͋(vhkw4;tޘfL`DQb"|a"4;@Ns;.|^8YPWȹ/;-/uʪoMZnj>iqs~bLMs':L6՘8VjmAL.foqm?t ^2Ue8y罪1^OFU|FG=÷5aŁ9.,-$B4ڻ(t{'j/fudžYLZY\Ù󅪡AQN JعVMJZO`K L=~E,A#N..J*ЈR~1LBuP֠~7_͏F%zBۨ-6-/On;m!,٢|q^XYD%gC-!v8Ze.پ࿔{KY<]*+ꊶAu UA%Aeqk|]{מJdFĺt{\Ԝ\2'!<ȰS|6 n,^- _~ә_LHM:eJ9;|q{TUa-ѩ䷠ҩoPwxiW޵ЮFֈ6 9킇e&KÏS(ggnC%l؉U7abü%ehŎ**UԍBWW>(jfN#nө+(nk˗ܫe@b82>؂/+u<礥dY$R &t21̲2D*;1~}tBon f/Ue]ʚe1>ZiՓwIHuO@$03pKC.]UMʖgT_9itAĪuUZOdj/t֏ԣ. #kb ;P ʬeKt.xRcl#q0|^7a{OyKj10 . d׽ zzX#P"K3\zbHUF VAdH|k_2XٺhU@B, XU77spO1S /Ψ]>^0ݥt_$(u0=ٮtB@I!/PaHwVp񸻪qY!WU84 U}c)? O2}㐫\HBc3G!SvDPe@E@PÎWԁc:Jőg3H8De.3>Y+8B>j{%^v'SÉo(% TaQmD*|.GmS'bl^0ssòIŔtGq%كiЩw@6LsV/qmiiUEsYH5F̜}Ġ|r)TӪ@ m)&%qF&(j#oV| i7ǭrO?E+iu ~~w2=1y=3/u;,xtpKwzفw3A\ Th)XAbXw9Vr5{pi]˺6;w VȪO.-'@IޕdzY"}r߽!uSLVEXٓ#;{~ k|Ko+ņkڤ|M"Z;_\]ezgպ_OS<ȭrQmW6:*>\F Zj۱bz"|ZʜkJyz'VkF q>tQ3TE4D:T|Z@&]= PTE03n=Gآxe|X;a }غ>ٚܐ=[낙TZ+Z5+Ƕ=R:(}{.| π~l̲UJgAC<$C:"ۄ2xrg4=F/HTq @F52U'ASY~W*');BfB"o23E/OZ }>ޯqG3dJU6wP.lT|גŬзiJ?~qaM_9n<*rehҭ`/7PHV"[EakUt<Mdfc3pi$sGwշNquJ0{+%sUuj@{EsYml=:$֌y(ڼ'oqmѸO}gT>4zX%΢CL N톗ۣ*(y'KPHs-V& ~Ly/,|k C,so"xP:as|^V}KCOs'}Ξ/xn5 U+qwTvN|˳鿀>zegLJ2g)~ i̤s[: gy!c 7CDrWI! }n|?tӭ;*쎲_ze*)&hAuWs{(  +5?|dοE_ow٢tWOPFY +1Oq4htTSkAޟӜ퉭3i4vg۞0T;2t>w\\I&g9H +q|52.ޛ!r#nOL^]izwEoDk*zOilt%ݬ~qHh籲7s朇_v JN(dZBF7PiWV@A9@I^'s|8G@Q-d@Jj';Xۍ㋮Jeߦ9Dn#Z(cKܟ-IQRނ$R睤;A$:k%(JIEhM rwHz%ڡ|}"5Z%_L4<~Đퟍ1zOer!_Pk@!k]D*NLɉTzIډ]ol"[A/˫I\ԛ.zXs؞`/^N~J,ĐCD礗$GP-D T#PVe Je:r@bC"mǕuw m~7g KeS,z[ܟ=.=(%i\bMU$}J$z:lNcPEb^Ĥrq+E }MĜ#wW 8jg . $1jz7`K FET MvӬ(pRD9:Ҏ½uĂtSZ Jvfg DJvpD. #iw f:z^YOƙk٢WKx%MpLwI4mc7^ػ~eP ~X3UtK]-Nho7;+5Gk!?*R7"jsXrXP)7HQ{$RGPe+KaXnl]+_sl)-j;ݗ^xpmh}6|]`z-^wOzF+(LAmK%R7c56㉮,פkMr+lVAC =aJƼX8W*쎑S'jOm% f/eqm2̈́h#iD8{pIjy,^WhPw7$b!lATȺ̞P҅kݡ. fJ(uwӄW=@9fT\4 Tl_CεV9ђCx[%} /^Ghd.=fG4oBZ})| ABmB)I͍Nxų!Ԭ,),/Mgxk4%5A備8dڲ$^Ky::s "BTԄ]Al.] )ڂczm;WR852Nu[;ܱh(#yf5!MԺF󒥣aQ}OmQ~ˀ3/<~]w_6B1grٍ ۸VWZ; QW@5F7wo܍L~ yzX{)c>`Gʳ{NP "4'fCtdіU^I=9NK\6~2`YnGyaڼW ۳=XNeU TUX{$''aFx}8][[Ej{qەU[S_[ǐ+aL-E2{ڏ[ę1Ҽmi1YoP_[C:#߯qʷ5ijZ~)3y52qiOq |TIuβa ɸCgb]o8jvK  ܇VG;mu<A4LPh7' FYƑ~,1D}ew-?tKU&k=}*}(b"(`b-jW52"Zɽ3f0lvתfwcg_q{ۧVR8tɑudQwy~۸L\^~2o,Ƚ[WPWIܭUqw\rԁ;YzXBWa۽bL(4&bu{t; ~ }:5ShCbfc: Y A}W~V_b:^noaqNh[eqx!&vj3o$-M]Iy|{3iJ{vķzuafkRc4dkqNmgsɥ&9vheAϟկ3֙N>9*[W֏X '4:=5}5{c16Lx/1nlCکbmw6=m E6)q!;n jhmriкQEs^|>qEzD!8wh=/_Ikwa+Efa3_Rt6TXRZH+ԍ/oԛPGwmU KRᶈ/tV~gMD7{)+Z&Z=ZF`;1qu}]"m5Yfu39t86ڝZa0Z56ժfr$V3ϖ^qfRl{I_7ETמ]Sq~]%ʻn<7Ȏ hey1unwB(#& j+Zζs{A_KURJc])ff`5+M8k_C0-vۅe᳓gCzFT#D-LkZv7kn [:-R)rKb cl S=j01=܄+Stqr)t%@u-5JgL49EٻQ7u%VWìt.!y+-YXNc”Ñ|dl3Gf6zٕ* ~) |5Aǀ-;}༑ؖ~229@Ps}tN-(5V@I~ banѓ3l~GEo:, ξOU@t6CJ5i](HT]hر^ŅzxT!Sb4Y z;vX"IvW3/O0{l7Ol1WF̡wiKijbl u;~b]X~`C =Po(Pm(\ e fI`G_?΄Rkp{FI3T@{d`;gP(Yl@]eŮPł/@w+?M`qjC} v](y~ۇp%1~}իG&`7k >vaiJȿb7pdaE wہ3ZաTiw(_o, P"&>[ft1m9oz>6~{Yy3JvNm'-5WHmπėPmbJY&>2U@4>o %}2w*ҏߡWjM~֨Tc8t:[TևɌ^I4Ƈ PlofLrth6fSgaL@ la_ (Pm0gF6g8%u,n{{5&IP;RWV7qyQ#Ml[_qnnx医8fIM29==b*Z4)c?n_a_BT9/C7^^}ߚ=ݬqki/Nxrvw.|V^<^as:dajCZNBSvjNFZ.._hO"4Tg;C*49IyU#R/]i/퉵{]]Ha:}Ʈ,fb:6$w6ZNLuZXM\ q)8FO=3T4 1<'pTJ܃~BZ}?\[Gv^r)1ވF|\>liޫJL^4bğV 21y+Ԓ!%Hl.OJgД S?%-NZE·׼:7c蠯>گW,hy Uoz ̗۩\GPdȔ$RbzñPR&9&52?bλ} % bPxbpg!J7\fLur2ƚɻuRelxm?';=«Z1Q|gD䆥۴*T9;.-.;Bu}j 3ʅ+uy @/=& .vTdQkh5uss./uLo<>puԟ-|I줓9&ĠaYc!Jk.%bnw||?H#5{\W߼?3zDܧCqD̦HE.gRnΙ3iV<܇*<%C(N # jrߋ*?=(TRW>\};%7r6~ N-Ͳohv~F}YscN7R!ot<0ۗU[p,0W:Ð :.ʷR8y쬿m'}ʥ1XÎ-={zWl~63w}^θxYlf[Hvy=lgGΖ>(U$m;Je1[kXs0U; [ r3$8 u8h|+a(k +5'SZ(l> 3D*釙 [l8nH{}鎻SƇ٦c,;zs LZl}='`g36j(-Pnz4䡢Yl ǧiM;Mz{nt_*?Jԃ>pnѮ['yfu&UnSf-[1;y5ۈhBQO$C7+5< I`sE2:TnJwSȍ$[~ m{sèn^ /,;Oe xn/t+vΞ~n4h$Ȓv}/]ӹ;[m\VOfw;~\|gAо4Ks/9ޥ\?U"">Tܞ0@ 6s[| =O8۷o1^qOGi+F +9ʂt+DxO6j4ݟKGQ m"9!\ng.jdw~PB5P]noLvo`w_PBRnE<8jl/3ǟښ9:X'`7*@j7װ ; w; qRM9$/XWuZT尦[A {/SD?6O>:J[g88?N xvUsUr\873w)`vFj{_%8dTσl~A"{_U;W`ԋY 'ƛގP='JO}y׻og3fNm@^C mV?JٿMYY)@.5oj@;Vg\(lݾU%Y[vUѱGawp~:.\k.]Sxػ-/wj>.Yt0sO6.M~>[q=8[?O ݍܮldpb ٍMkܵl(EB`O#Xgn 4@ګ=s~LolZח;y8!{?_]p endstream endobj 27 0 obj <>stream --U~Bk=y67ȵbet &h]El&9N:Or)Vɪ3lȻjzsX!yWK-Dv[9.׃TYLs9EEXڦvGF@$`̼+I/Aʿj]}L?z,Wk bYu @{,Gdy̩SYr/kaP6yAgɜo7O_̌kJi~Fzq9u'>Rk-Z"| _{ɇԜ`Yfmv }ΚyyKmTh&uwldm.ygXq5hd9MOgSZ*ua?p˟:g;̋PSէ x{}}, Xs j5^%OFg\^l{D4c]oA)[Xnm,3R5 m럼w _sa8LM);k8 .ܸ֠  yLݾ/|?k3#r"JTtǶpe 7L53󻞣kk?-6W_xGR"۵vG\lw)r/_ٿ62$V 'n |zdR9_WU)5<~u#iјd6Z;JI7/7*# U^< 1WEqzEq{'[B pjW o@!]~]p&wͿ]%5n[֙`s4w"̞ 5}eRˋ_J(h]7-#A|ZT|מâ8NolE;(tWYst;L^9U]^\RNi˄1iJc3ǬTYtt^{%OPq4]SIr75g7g7|/POTu 6йչ36U-,.d^_Ly)W3 %+QFɻIz!emN~+onZ3\*=nx\;*>~??ޘ\k.i\2CpEsq픻Y93Ea=ݞzj_1.ۻd!_Wva/rˁ~>TwT,銝 "]or@n$feҜO'Zلn%,x5JTްZ'81~6h&y|>ǝZyFb{gw-NJKYvݘw>t/Z=9lVGctN{R'j>7Yl/u}eZqb7Џ:+.rxWb (Iׅ+v:a-unܖiҭKM&MQ1q•H7~6w&ڦc٪fX2ls>ji0JX^xC55Z78>J P]f:L0f>x`jIsoZ܎t͠sa^νG?][JS,ʳ>R8KJ7AXwIݗ+8[H5* ܈ž̼9D[s㺶F9)*6A.5Aݷ?q\}1'C8s8:r״ᢛ[ ꭧ JaG_mvՊݩ_ko U<]ƍ ?)~i3זx'[c T?3^~Supnº !Y ƈ|xYGB7pfK1ymsxL [۔Nߘ\C}+eXcZ;\Xq9<`BƋ.[=Lx?|K7;KfV)5_Q!5imITxUX6-k3-6uv7l<̑f㻟8!WfWSn'9J4CH)z {FgpǛ@4<#CRr7*\~jcX.څiO2̙2ʮ&>F٫6/v/Diji'~|Ӆ MXkP0.@p!]  H@HV2 r U  {Ɇ q+.K̍mǎRcb3Q55~@Р::7<VH'zSW b8@2@q MS%L 2C_FZLmGg5j:Ary`CQVƖP,uuP+9՟Y TrP[X3XC]P&c|T˭p~l [D>;Bφؽyxvr.g˺@@ǹoS/,T䈎! kŊw)Ʒ H\u N),{*jW17V@`m\<3Tv4 6mP[FXvY[ԷrtohQ8L߂H2/v|\Z`nEO_.XEK௻C4 &\9z'|c"*RSG+ܔ~7K퓗}w\8z JGNr{iwO ϰ,z$.9KgbxAkVS[ew?azU=}yKlg).S{޸]]|> 9gq;۬GJHfIna s`Z9w'J)r4q6:GyXډ,Կ^P׻U^S.3mh5kEld?ң~柗߀R } "/ʾμ5{Hr&w{nڹ3.~zB$AV>L}eAsA$5˚\ ](4fWЕZ>Ugzh< ™ .b#@nn?Q9aG<ݛK{ng]tv^gBzB`v:XŶ x3C}t՚m13 Z*l[s*ڿL<iJ hk<鯇,[ӎOѵmdκq?ߣxk0#6$# o[j{QXnɞl*9ϹՄ ԂFmܟ-LG2=RM^b3gz g@F +TU18C~p/]ýs;8ba#g-:hLmdqU -Mr2fRrpzW7nţ=ŬJGy2`B? ϣD;rsvB7O.s#=]|3Nsqӥx1(-zO+a՘NPJoh32D)UM{snB ?ڳ=$ہ3eB=pr貖I lXS'76ߜŻZbH(魎+#3xKx"|e86WPO4ͬqq*  r\q[ξThf~#w=r{mH{XN/0'rNy1թQ/طc ?9aroa5ǦS_=}&zk{NGX@i¨D+xPcmq|tEn͵ _wg7;a3=lwͦ96I`whnw8Kc9 jj{ޙ2KV[ֱe//@$8+;u>1Z#.%L$usao]7cV6~fRt {?3޸gwvL;ϗŻαmOU2Yk[ :: 7ܷ|*S}G[1aiuƈBӦv;cVhMhyIl[1<1Q+Js,^̻v<]Wm+`~veIMbݜl&8`7>BBF}WˡQeM9 Z{+uSM{~j4f콟vşo.}:vi?C,ISIlmʡ Ք?ܤG|24:m\I UO9Ld?tkݒYaaڜ)vbWzOS(Z0rMbm]);%nmʇ'Ͷ*gX0ꄷŦv ,?C)ӥugmy4}=7ywk5n=JU&e`L Ya EMi&nYX^,j^Qu<3U_fFzb3:1R9e&f}("?$ (ayr8~N.h-z%.$۳mKij)l}¶|uFiYSG_Z->NuwZ[?Q *f"i]D=,}<ޥXAJXiL.mqɣ6߯9۲cW֎cKI玔 #({ 6L]Zh5&[e?k#T;ܹ i5uZFsl1I8͌h̏—D&Af҈9S=%,;,smZ-P"\NƃnL;Zծ`4+[>`4,. ]&W:LIz를1@߰:ch:JOOQSjMr飝p_0<%Ia*ʍjQF*[eQc}n`8ҭ`ͽh^ XkO1[<塵jdʙ2{̮A~懴f O$@v'u O?ɌO*)(%fTg-ͼ|475f.o0%CMm/2w"?/)ndْQ'{1M8!1rg (Cqd!2¾2O >Ö!^3- )az4|Ld\ofN #sW4N)/2RB @/d1LE&ނGAK  Tx\2@3Yb#D@&@' W0264\`$D2A@Cedx3Cj#J(?%2ꅆY:/z43\ P|'X @n1,sd-B|/oye YBllcm;Z.x ΊFDXoRH I6:4ۏ&lr3ebG2=!gngPgGgDOe/VmKǥa1׍-z%'T9xv3~P+Ex eifOgtӽWr3H~h98Z~7ICcdms<0_[>{5W^f_K؅3}>}H{H]Rfu6 뽬/4؞/7-ѱ}s7X9?$>zpU>j>//ToXw9loGν~[l̷}26a%FV lv 3n>?Oنjԩ ˖%J @<_oZr%I&7Zύ9;rp. AKWI*S4/8ojs^Vjn9 T]͍K5.\HNH.O^*^i1ԡ@Ӭ1sG=~"r_h@>~|$pWi=;8elW850V}Q8Y]g,բer1 ߚ[鼃y8u!3$hۿK)KbTۤ{u] {[IFX^-lݤY7<}Lf64bLsf%q۩G?PKVQ3Tn5bjMMLf /ۀ nMHCL++WoRbk[kQM1Uid :%&L_ ("*".@oΙTIQK[Yŵf1E0.1)כ jB/sWJ%rb1XPސ,꥘ Ud@GdOƗoYgIV)dED5/I8O묺h8gfN fДFͧ+z| &e`- ېgG'iARw=줥&LBҗAȤ*݋n{́'&>NPu}5;֭Т6`1*:6F8Q("]7QF=f#L1X, 8޲8  $GE+J89kuj9VXÈ0bU:q6=QYZThڢ{CYKBÁ>d{`^• Lvxc;Il"kƁt=ˍMuk,%ޓװ2_E^0Uk괭 ֆe}ط wwt /7/^Gi _ymþB8EĢ[RXms"/5T٘(FJt:ay*wcv-N׻Xkߌ[P%Ȳ]fwx{W0x~_ACZ.05x^ ]^ٽqypEJ9 BTi)9To-(}M6K-Tvr5̅jp?:tpzpE纛HWe1g+ /VV@J'^CeM},M|%ggݿc' v,jܛ(VH0:{:2?/[o+RCfjyG[A'wGV;PDžwNQ/C t|bͿn%7pLsQ IIӐdfwGז5N##7uдνi;xnVpRwj72^-z; r]f!I_{v1ϹQgpƵRhҒd%Um .7mO4'K鄗r c:0j* <0Up¼c'Vwc^+Ϯ``-d:·f|' uj[-yFdC-ke |s 0cnXk#z)Q#zX>2쪵[9߶T@_ڏjߘ$ A 6yn(v]Z9ĩӳD~nF?Ū[U˲r 4)6{rp鹟KeK+tXd3,4u%&RU/_Ns[5H4pde\l GwP\N҄;Dt%g`zG*p8kxGx7:di GvJ*w'* N]`5XI%UDWWfs/Xv7ZIޱ2.eDv1JM_[ąm 呗E*"uDN_\=_Ɉ7fyNK K6_lAI(.$t^e+Ȗ fPF܃bI~ rz&/)xzhS:E_YZ8%v*֏r{HB\)M.3.eg!>m<76}jnd9_-Fi2o!zPnU [?oOިCtb%= ^>YDJ ?xt7INRb.RKΛpn.w?Hn ]YTQnd @LڜޣJ*>lekn Q 6mUЊiK^[_xstS.n -w7;R办.ϡ\b~a摀*O_-:b篶 [/I8@Tl߸y6iVrk>?W͡]>D6Eϯ+t zA<~ ɏӁ1[|݃0䌆+ @:ghD59ע{z3B\B' (xy%[!؜79-g:Uʹ@MK[#/[VLZHL^H'Lh w u'7߫.Ih9<'_sS^+LzT9H}t&vW.C+sM{k+ڤXmi?3gg(4Ms*wQM訶!y&ZfLjvԳ9jFxdi;o}֢Y}5D؏bbUeG~[}>c;!b,yE_JsfzRFؚ{5$7;U\QڊK)Fg+WA 7'ޭ:J+Nm}se} ~vvN]Vviͯy˼O>3 X^;, Y5i5n]1֮`nEʝs-+}%}f@&3楝Y=vNknfa[$Qd0,n>xYYS<[~ Oo06YJʳb6GH߬*H`NF !Y=B* ç*R- #%@bdn[?5Yt'6sq5hxe$F8W|cPY =5u󸌛-c 06T/ DҗRi4lK` 1/.W牌ө|ܴ=iW$2+tJ}LG^.u@/ezWDt';{]ӺkG/IDW(ĽȻ:.k z̷ՍLg`em[4(>P9U斸hoX/lN>3qח룏B8`8ȶTX-rejvQ^;QN;?/cQ:g;o 1;]sgǥw1RU}ZJI,WQ-efB7yV&ur2c\ܱmб-1?\cF>`uus`S_؋vu~7Udsne=F_ ҏw洇䘀s3swc7Χ^mw.D}&957j^eZ xlR_1Fyo=*Tk9~ GY'7#Mn.Ai)>S5Pz=gkjvA 9GdF윆2Ņg+}m1K\+n H56ۯ\XJHn72I{?.!;ؓ*Q0(t(B2t^yyF#ĶNIuXq_N E@#Jrjy6\^^,`@¬ᕮv:lUvp_j9M9qtݸz;ZRĬIkyw4_vPhvSV#l~A}0,nJU.ʮsV2sJC>i⵲6e|{˸ѨQ cZcbbt'+:20pOMW$fҭŬi EZRLʥ"v*J/+ҟ }P*P)Mf}/pr#oiCv-#qsug!^Ջ:ASJ3p9YٝO4zbJ)sW.(]` /x) #O۳-="K~&fjq EI^J~Ja?hh?+`a1@V ٍT>Avp4} ddU8xK*oJ ȴcd:E~'|=? 0V}yy1 ?tZ`'@$ tbNbRYd#/d5zR6T2٬9~=.΁p?v+oר=Jv{*,Sx`ȓ%Ͳ}ܳ[٘.y/0gJu*ǔO>.I<{opy>]xf@,tz7w'ta%}65k 2K14Oc8k/Xå9Mwnbgp.+S lifr39b oQ\_WGwTܰK ='^iR?1v>zw,+]F;ȫ[TXki̮Vl.hAw`7i70“ڼ;0Io17/thnŞ; is%PvYp(6]@n-VJVЛ}Wm^͓X.ۈ>Zy}qC/Bh~#߾fq ;C̫NG8֊u0m?;ֳŭ-jC(Mzdc wmK,@fG+ˇǗDؔb{2CYlћmݳnzs-BOdlclF'ykY vۮK˞,#'&M9&F~$NĞdzL^6MWH$]Rȗ_k%#Ow]ND /$=ML5@=Z42Dx%ZcInJTUG\@97ljm =غ@ɨ8ZkJ>_'(V!\oHّXQLG'GKOi@^;vQ@E~e#U%^O|@eɩ;6ܲgfK4Y(Mה=挵W nQluw]JsˎW-)bT39 GR/$#}5pŵO쇹Y|S~!MLKvU_xn^"+삏~^υfw=ay|WXkZCQ ^(j_غ)߯Pzz m"OffSԛl/~տr)#_rM5Mjbvcjl&g/k6U{B֕)WFK< v:;Z^GO9pU8VST~y=ӥHNk)xl"B.ɖfKrv/$e9p>u%>8ogؠtZ|Ԯ[}sX$#&J&qnwp[ ?kF{ħ ,J'v4+VpZs?1p5THP(5Xwӿ̣Γe=%\ɧ{x页UW9 /*VNUn䠅 }ƺȭʝqw6lv)~v$=:7됴o;jvl3ݎvPh;}vPN&܊x*G;yc+=]ͱ~Le>y2G#eV a4WgwNY.o{2s&JΣ\>>"KV2k` fL^h+_3]3 w {I+cܐ;&$rګnrQ*} 2WXn9lm)ΓoL1RV>mTm][/@5[zoN8GfJ[yY4:jk+fNk&)IW/}b9qT7N.n3WCwGNov߆fBVlߝ#'Le\vh| +L6ȰԼo"tɽZZhRWfFUK*ݱjbo \ttߢjwde2ZodhV_nmߗYMZOg{T)U+UNS/sBYOӹxCO[v $؆O1dU}٨ce z~$!3UrrjKu:n<˒}i7dc!BS bZQx1 zCL/*I~wP(_coH7<;,$AKhA-Lpbo'i2g7B:YcDgľh}ڟRLVK@)/YЋ x* BoA4N!Hpj%h j'M`Dq\7V_E!<Po=cmHR> 3ZB clR\S} 2N|Ƴ2@TA_{;͠&lW*a:As5718{Ux~mq*81f~ĽytoVaֽ a7VI~nb5di#od d 2v2 tLW\\kZ@yJDm} Sgr3l?Zӿ_o]/[K@OMȯ\]z]r{^=Xl#J!0EAvAVDWu|yX-X<=ϰtwu{zfTGLo0You;ShGiV7:!?sjn$R尔JUzU J;oTE3<~5Y!.^BsAҤhG#Li`p'mw[nm'Gr$gb8a+* 'iCoG"&:Wآmٝxab/%檴sδ+&疫B6{M~Fb*f{.bsq9ADcf}}Sfx@wx؇1賥5}N"h[`يwzYu (zvnWVc/Oyg^⊗&-/r Q{NcM5/>UE_I"u S:@kȯ}뗂Itv^dm[_]jn<pi*>ATstjvs3z~E:}u' vK : 2_HrJLdKqaAϻ5A| A!.oR}'Yھk,\57t:rC+NjA8u>Vݾ3E_nBYF<=h&p[{ +Y nk:u-г2؄eM2 ]̸|V0&+s~+$}$դLq<ڤ7E60_"nYn5[4@KG'[j*|\wfurϊXWmؔ>J]J*KИϤq쇳,9ݜm.u]<)+8٭!Orny- $vv8֔b+R=;Hq'yv&= z^[5q5D{b9|q7q@ 8@jOd1jÐH,fK⑵;|-wѡ7ŇOW_3҈ IaZ Rj4Á{xNp2$]݈:FW0,Iy T7%`6~(+VXդ= w1c*}x6mnɍo}I,/ܰ:P)TeztnxZTEp,.hpiKR~Pptu헻ZYJ?xL*rOvzY׆-rlhqpW)I13Z~c7NgFy^&8?Px%oxN\fztw#+|c`z򾍯k*JfZ.5?]FA3sM*N3fύNjYo}}6O 75TO)mhݶVyUf~ƎW0h~ƺMc3zImݧ]_)W qJýc˜x)~`Vi!S`E81voBT%SypS9OF.9q9\A<牜4!cY֔x]dRHoFr)\z=h`hRͱ^(g+ha(dwNk ЉFcTR?-~_:z,R<濋VYwox]|=@WP?&]Oa${4n/MFy2|J-fT i}R@ёRTP==BWW{,gӯ:-UkLHTѾXeo`^p>vn<+23Q}]w;OS(`9uG 6 䊘wUx$\/=.[jfV]M(jGER![E{#[[|qOSqt*fPUkot. Q+wLR@GK"È(9)0:n6y򎻧x RMn.~XV!As QЍ1$i|y uwǼҭ{SΊ+'dzNmFr˭ Kc:dL?hqnNT>lDYﰛ4c&=m慍ohѸTMKuhl֡UBn%3]f XS=7sjG+ϕ>diP@9Us"Q暸81pzfߘ^e4`OLH*mݛn.uoڽ `*V\Hv O:lZЫ  n@ 9(VWOu{9ZoXJs-9*ElPPg^I_ƻ)Dt7vQ/^"$1>|NbV;Tʗz,kWƼ@*D`r}^"RX|:˨b q_ X9sL'惮Jm/B5b%;ҶhL븑{p0Pǯz1!W&<\|yUI<ԇ.x6S-y BW  ٫; SJafya ^ A?t閪< **= b z |޵sUs.ɝ.CO>ќ:ĕ = )m!U9/c;98ezV"<,AK. /p 6oua|n~P"v /4 )z l W@\6RT9)-" DX2x9D;-Z4-VAf﫟C*h.<UimuAMYS*@vtK)R3?Q`i←۠$7(AJ_B8Q I4⏥aggH1`G4N9d|B6S^%*rV"bND9:£Z4y81oo%⯤0Z?L?S4LR>skRv N9 `ccٚdVNz~xD(EނR-\Iy>.c e?.SM,O2N߇MMB2`>6m(γۆz7awQ`{^DJQͬ^?Z/=֨[c]pU?$@|$ZOiޓ\y)$Q 4WI{l{Loy`WO#/Z:VIsڡ;¥ۘyCu/mTiYr޹ri`4DOC4:1NP$$||&kC=Y{ ;8' ,A'^PbNuje32]',蜯W08Ir|qi#F,H~[Ƕ$?YZV6!^c1z.t Kxl{IgA>ؒwNxZ^|OpT;ɠlyjw49W5űpX rQs{ ?3قЯO`2KK@ѵi}ۅ |r!sg;O}syꋱ169qɦZ߾z8/Z:TsJܾԀK]|w}1#154mpO뽓Brt``i2i޻?z$ Ir8v.m{?=6 ,EޢNmvys8Avdsq8qMB(O;mOyF#YA^I4HTؒ+G^(^Bl|$g}Na5EHl f\!=õ533m){in9MDmhl𓻮*M=-,A8Ƣ>˥N͔.LNk:[ŏ:RχD658Mq8ƹŕ.#˽.ݛwi37hmERn O.1ZXVkxu72м{Zן.PQO ܼpܾZ*i[=ukԭ)}GֲǝumOSv :x^eg$/Vpɖ5=f5:T jqaθ!=G^&g<Ի3b3.3IzxVgHjӢ.ZA =Yv-?hzȹl7 bfA [9S09uآ\ulYFtG=/}h{tixrWǹM1@ELy+[٢i֒aj7X)H+9fj`gjݛWֲMd%Tںz,8k6v(kDs#?&b^¾0)Ѻs)R 5Fea7 /ƥWoN r`w21UX~ۭ튻m-+uJVV勻?k󍷛V75_;e89x'+$Ľvxu uΣZDxۭ7pzRQWrKwPa7\v7mmEm5Vm՟imUJhoUMKb6"LY|l(:׈ʣ*H x|rpI.FAQiF {wJ*q+GۭT[5w#lRm9zN4 tkC^ѵR:HҢ7 Y>xcn8="okhd{mt{[ܴCQ[_ziEbܹha&o #˚u^Ae]k-[͖[}6WZŜ8#>|B`Pˎ>>wF4*"XBYV[^oTZNksgZˍYWrڵBe ە?(rd[bR?Tlȳos1/eû!y.`mޛ0R?-SE fC0>;.s)Y+$U>-UTNCTdo> zxz]A %`MJTkhrgۨ:}<8lxrޛNBy@n}4GG,KBʿo{ɘ\Cܻ؍g/VVks٪w.d<+M sa]Nn2Ny-;87ӴZ `9ig3 R$\Z<ދshT92=X(=_{=2};wSNQOlU ocN*I"|9fN]Y_wAts}ul}ui`ᗇ]InuܑQ3ץRo<ִOu+ZK=gqoN3OvV$yp~r?nbVQuKv($W[=]5{!64IrzOe1sP>W섾-p;2t^ .=b"ĹeqP!$9િ=0y(oiw?W<6n,Դ޹ mc;*g}Oc?0+:iE;Kma%>yW6?*d;mrRk_KҮdKMD[Kʌag`K %TFŖ=w-4# w!ɷ$Au#!w[t{\,.=thn];Ͻvʹ]2_vHr *>{f+홖vRW[g3I#Hғv/ໞ3LS{%~FYWln+glCV᪻3{~p ]Mru)Cd_?d67C߮^:5`^[Gۊoo%^_}b-hFzfoZP^S6E)'[sy$퐕"0mjis1Gw|jȗE<:] Oc[mwH[dj9X_U jo ^- 6㲾eೞIi{;2t]G%8*^QlU-moPCP9]ު\u.0_C  J \f治ujhV\|*x;Jd 5v! %s#⋪4|RFgy3}ΡTEMMDflH @ܵgKfXf}}\o[q[̾P߭%7'M*` Mzy-E>0ESE؊%x= Sx<9+*|Yd^LwfśԩSLk|k+`E \h[Tk Iew)w=;8Stݖ!!喀*›#'ń4tiM/ $C2eP3VO`njClu ~JYc qj^VlYv( +ź^E]s,P@ަ(h$iC>@xs+Zc.1sz 0cZ<[e(\\ j\Gv`KO_2t6[RNPLK(W˹4e3jS"ypsRZ\ejX浙+LxyWt:6޴l ))D%CȆW叇SKrxk҆a۳PdoI]VP\)f/˂η,8ס=Z-7#7Rz9ce|% +(?Qrx F#)k1i>=/א=#[hG 2e56Ŭ̞!HMs^f݅2)[:6v##Xz|C9(4,+AG@s{AoN/値KR];4wLLL)u_[5;SE7!y#X8ٔrδ,1~|g o]1 ˣ tH%x:,[fZaw[)ofX>Lلˬ·-Ev'NsWߔ 3[dQ^&o$4nT^֒Q>H] ~#h~q}hp+L׀~`i3>$*fiu/x?z5jjl$c۶Vd8^6`6*hM /úފRSa(,9xSvg{PJ~e_zr^iۺxG*qiuZf[?숅U)Af#y,@(ƹ*۝9*!j} 1R6k~G)5t`:7r|S¹"sל&@ZW yrڣD|(!UzL+ҨK8(ݴ8f XrFUvR?}c#-8Ze-/ɟPD t(%`LqiͦY;^mЫXJktݣ'B2j]Rn /4@-48*(Vj<ɜL\:j-7ZWcy+43hNKr|5ڟ`g.nU!4K`݁+4'뗜~a)ֹ7 v  QBhh=o4 JQoDӓ ]1Ǒtr1/Z6 տzQYj;Y.!'6;L<>@/>2~6ApO%塵\5`^` `_pJ>ɳX1/>Pmg~:Drl|=؆x^uM7V/Yd  j~)ȳK3%QG1fQvZ3j{8ڛ8086[aǣ!1U"S|)D8v yLS -a;mV;?u /vDN'DЪI<=|q /D |q}q6 VROTލ 4q UPO4ԝ0IP|շb}T~ķ^xߛ/R?-u v& @3m6sDj}ꘋp9&{; FwnHؚxX2þ2hH7+؈4sKNr=EKrCJrUo5{A ORC;_&u^s^9zPrwCudO~)>0^Aj]Ic>դu]=W)5d l\HcIn)Iε7YxlB6>:>Oc'P|qڽv2w=X5mض?ߴnԫi$b[Ҩklo){0f}VJ̺Bm?X P;Lm݆䕏22hÎ=g;ؙhh[v1c%騼e񀨳-[_MzAW+3=XxsMAP֊өŹ]2 EUZ+mO3{XIJia<,m@8l4Yd^4;NZZqNYEvVX_0V^qRzkiH3\Xr| ĉB +sG3eΤ4u?&ȿ;ԏ -]Վ@OFxs0sJ̈́g rQ?o6.ps9 V_Ʒ:x|7봹B)"KSZ&qUUwCAn7_>1\f=Nc({C~7,fɄ?WPIU86b[0[' ŸӼKk}3> }\EDj0hd(1VdH[x-^i>,fAMUQL "IbM:7fc{=4[%s><ly+WMMpAyI>=y΁L7wIny%X6uh[uGzHIl} Mi4'duenyE?݀s:An<" '$[R,@:>G[ MFc?2nz]CCB6iX?lI|ц5iۦ@o',/k!dxM:H#m"rhTM0С9ԌCc1D#D軎 G$s2+)}A&[9'ZgZֿ$.+X$qtNdMr;J~H0Y 9Ý[ĩE^[zOºLoNJRc~vƫPڃ)`c+0=`n*yݥw!8sFQށٔ{*(So PzBWyAHpvc71>lR½ɐzn&z7ޤ?; N6G,LrQ fXmf<=So?1Y$UT5$ΟHp)s逦r>k{"vgZ6wLg1.VvmY#~.mPSNd̥ jaݡyfmm9ri5X֔׬Oz.$t_0hh@>[ew:Aј%+uy~GNb0v„oKs|hP!Z/>mo TRSjp2jmA|F/֮ʭI8<{i<`4f\vn6 "_#CѫVju-զZTpܛJ/}LOnq_݉h(Xi#6}ݎwZZ5Ji];5\&BznU@_JRO*TKV]{ U~Y_JyrlNIҰ:a/[["#0Wc''k5"yŢ(ǣRc+xfu^jU1R=g1ynJd ܕr+ZkrJ4+if <YaAo6.?(?Su~.ZSəT\ѵ< <]vjxXozDwo}S?GFدWY*CkV6?|s~1w-;].T{l DS 0  c008Xs`L`O)a7%XHd u4tWe6!u Bz>Nw\ms_Q/ u4y+is+)Yo>#Yȱx xJ/F~r^/enM" bJZdxk;8B/kn/5Po3 φ9@{@yPYoWkOK) "`BIJ1vrkD6w ,l(.J2z>e Ѥծ#a׾p~vt).sP/[D `[A Q!Uk  /DOBhA&/+((?!?MynSN/s;S6ԀIYc 457ow^p]/]^EGN"Hi~`Tz/^ξ6͇)T c?#J?rZl(bz䟉KV8K }H<5~?軥99ߕ{bĞ|]5ju&]/ޠOnwQ\|-s3b}-*a1vO^G-+:ƤQsrF`ͰbФ6OOYfך5[r=WLNFDhc=(#W|ʄIx/ą8}q{#{x';›= zol>ۃ~#{薻^}ZXxydg]SᷘEqf룭rugٖHphS=Z XUߒ!:=7sr=Eb_1uΗkk3\Ls4f?uW#Ci]^w[̈́(7USjCmwϵd5PY#f_ѹ|Ckgg[Ȭ[.sSE6` }XPP>V[SagO-[]lm|!T>Kr.K{YT yD_Ǹuۊ*KDQQiAE{Q=Nxp:g B&H# C֦~M%+@r4ılܢI%ss?R?`x|xl>5$C,yM9Nsv6v+3n;ވ)])nV?ssٳya3"[k*x34Ky5V`4 5*Deo`uK_I{=M.Sq7qư CY[jvꍼ!M&5bhzw%]f3fM|nS?sQq:/^e} m,;s3kؿZzY;bᑖG6ʕ Qt% =ӛ^ޭUGjLih+XVmQ|L5Rܩ={Aʠ{%l|u3ߍS0Qv!g~-{ ' nac޺+ݚ\sƷ ҫ&4 xZwn%jxU*w5Rպ kCW@ô1Y^<Y^NF2=dyMU2yFbi`QQSypeA+P-Y,U_f,FXzj]剫śUrNV[oh0:BnT4ӏ*.!. ),.ZM8[(d'F[Q+u^1GYy6EaSy3\E{oZT9.+|TS8L5G,4~ʓ%穧/e3S,.A,7Ej俾P5PHOVf]dSFņm RqzlmkigL`lXoJD&QV<ַЌVRV/ͭNC*MY=aBuWyN yԼyĝ.:3WX [#&/d< SW.vZگcemv. >Δ'+rkH[8$t 5kD`Ċ+KBk%bʭ3rrfw2Ιf2#q_K@ZՌNpmY q=TN&<16g^Z/vXYn;C]b `HԼz1bc47V=anSh?^%|{|KX&V;{ujoG:&ڗg%Vc;B$P5Ǔ谼 .Ot\ﴲ `h%Jߘ($!v FiVEzq>׹+(áT8a UiD+p7Xy9T)A.葉ż'VKG155X#:H+'XwDP"]~f:݃ZR0QyPyr2P" Heh[BwOkwĞfc(Б.;-o t'T76?צ>їKZVj@AS.AìYI )ʖS*[~fb^/.=ĵ/K)5䠌۹4n!w}Z.qpWߍ1V44hTKnP-Y7ZG'2?<+;#VTЋGQƞE> c65@P%'%f]z%f,Ya04r bMK;;Y&YZWo J=ݱc꽠,FEΆ־YS(w/z"a9gq[[іú*p&#9 @n ,%^_p'|T`+j,Aɡfn&4zo+j HV{x}QQfa1J<Ҙ9gЭ PMPshA=a'[b@C@#@b  \]m*v8}>p<7~MmMY/c^0@=hV88mNo|zd3m>5`#:jgl췗{`#`nL`s " `oHE&\}my'5V$&nzy;u:polV9)6VGy5Mfm<}W>_e<3؅L<\&DsP zᣦ>;J. 16ɢ}('? 3H 7#O_wA=ƀo0$ ! , $gkrV*jw>M%P 73i*3 K6*`6G>Mr/sSވcV==/'-uܮ{.y_wd u / F k%M={2)=ïjfe%};h)Q+}YǸ;mCJ ݫK".M~a:ݍn$mD8K Q3#ط31!}ǯk UfVُdx).I~y%o~35ǹSP¥f$DX3sYv;.e$Ytߞ6Z#@`4ϲ2SjuO'm,?9;ƄlS{wҝ GV"Oƞ ԁހpq+Wni2ӸQUj14SyƷ0f%zfF$0`~ \% ŗP.F4#@ViAm~'~0UX4 ]rnzW$Y=aPTӤծO|cA߈B3z j a8Ҹd^)aA\/BmK3Bz 仼꽴OՋW_tK_ǒ:n Y(lsn4HKa>ZGݑ>85AlOa@i_g ̺XN=?<)պwv}v3H½USno) /=sfdC gQ|G}V008PVh|ި+޻t/דrWnM;kn7ϦmsYEO9zoi<o- 3JJ,`jJ*yMG5f\<䯞֧lK1> { ֺY ;˜u`5heg=ɷ\g::Ia9pp#ztݢZ<ݜ ˪d q|GJBY)ybEŘxqz66a/&sQ<:x͵mZr]Tu͕p;t|$hgcضD4?gslPՒ\a5(Qfƀy.B2~u9Z}snJUJ#v~WQlV!$Џֵ-z.aIZ/K-qiQٰlE'f - |KMi@hROVol4U*/L\Z}P=h߱?\CoΪ괫~9ͣoVa:[)rc9Yui};:zKiaZjiX쫧7WIxuTGaxUx!pxd~j 5oawsb:AcSڿE/qrÇRGBVBg͸Gͫ;T-hGZb`ꙶh{d/ uO4ns}/[6$VsT [% /L.Νܨ:h茀o4ϻg訙Y9;j6[8VnE+ug0*AGNj Ox'$Z65 U;)9@5Rmr~.QwndT<Юdi=1t( EMICKsQ+be1zόƍ #nJg<-k G[r4IɊ@@2f ;,L|.]~\~{<ۘήliZU^-+86Fpd0'2VoOFn:fnDiuA.= M N ]úly/VDa˪Z~O~A?|go~p\+3es> vpqs!J1W1GiӱLгEI#"9"Z>#hZ ޮ/`&yԯ&U3+PtcߟЈm@h$4  W74F$A24Hi{R|+ecݐ׺0M>Kg s= C%ۇ(OV .gIe/WsKWUod_1+#߱GeX .peWr< dDi .*]Nc XC_[|K's[p CȦZbJ%E.#f)Y-:VnifD\:|Z,3ոa K׫*0^|p8 ȋGb҃$u$|k/L.-$$?{ Ϡ5wCX(JϦbRI[EE%TuΔ" >d$BrC 9gO \p/7w$ZEtoG&\MG%l3 .?ꄷ4pQlrz!;|UCw外ih2be݋Ė x@dĎg7@B 5ı4KUUxMZ|oDS){oe i(+cLYPsNuG qwMdHL!zQ Q#W͠ 8T |?%Ĝ! J.%E$j8}R(n >4tʾN>㋾#qoqIנ|`Gh\P`Qhaep]f=?!@109DLgHjvE[ lTdhycxekm\M({`B ֫3{ olf Ft>,` `kn U ٧u pjpΑ8\>,Kn,#*Їo.gLa1_*3|Gn]U_rpp౬SF B=oр`n )CF~)kd{i* $M@ 'wJ|='!WĀ8ۆʇ7^oH@΋_zճ_3{%OO"'v/W^ Q2QfjsW1Pwqn$c!bT٣pvi$s班35vOA?RUt~Q>{Ì.hؒ{my=<>tK2;D0!~ML%z~TPFt7f]zkmh]/H>肧AIIXqkǏcG9Ì0zfFdE7 im&d/lKuL:`tߍQ07X W6wH| u miő'lI"lyj3sԎ7??IwO"Co/i9.H(Y_%,A}ϧo_Μ$cmjCʫeD\s}͚w1FKCn=!'7s h8Xiъ釹 3Mo(6y:K4w%(8:6hܰqSл4Ay^v'q5ze. :wsɇ}>"C#Ԇ)L Y xO٥sop`=v8xOnәgGMݺމm+Әy'txڵzL.EʋR B·K>z C.ϾbŪ&ѻLx]Ko] @Nw|v4td6=.7Dn+ss]*ߜl/.W<$P/9svlFp69otJ}q{"~70RV:Ϊ)^Vd{_vqhOu .pj0oy͡E O܊(l V|ֵ]^S4׈pxLcBd/V.3hjdvow=i]esXunO7wG]_.B3|-f\"M7\8HYYDXtȉ}Zxmg̦ggZO?au|^ 0M?~m yjB]HҒ Sl "|M9U _6JG䐽y@ё *?st*t֌ 5IV'=rv.H-ڻu9[1\kr _IvAo}VQ9&OGX*"$M^ KWђXz;2GkfOҘDrAKJBeS퇜+j :D9feSk[D_e_ZMX #akߜb'7^+WZ 2axz_ߙEKV٢ӥ !bR_6d`NDs<=X&bbXL\?\~ xϥ| ޱ~oY-CZ/OZsSEtnhڮRd KRB|wVDx~;`a^?\7Ukwݎ]yMa6:~h ImlX_\OL-ӻa+0yII8 \\ *>4rĆ*4-XXXٺΚuJڵ jNkip|"ǖGWrDf3}hchB4af fT+D:s(uWi%i=k݉ю=kFC:HvSZ$%~ym>G+L^9F GrUN[u T+d>ڌ]HgH ԺWʦP(2Z)a_mv[T6Ç<Wϼ}G;;3Y܊b6В#V\U/~1A+T+GyȗkI;٪=?CE[JAm4^NYhv{HLYB!opku4űv!nl axHlFj]:j|*.]/]ș* A~=-L^]]9d\p{< sMhce[ˮɪSK=qk;c?WaIeoW@cա`(x㪕gCEu\/ɗ:wؼEGk֓qr=i`1CX0l,xl(X'҃ ~ `f0wZEkz4Y+`a׷ vi`ׅl $\OR+ڦWf8 ht "Cpb9!$~wHf _\Q%;`ZRG4s0y|cp\&'-b#M;?:t'& b?P"@9/ P3 PC?SΫ;o)@+NI0XtdH(a;D2\Fw Jp gudCnE$K*kslD3؆T-W-Wh?Mρ0x-A/&u=,{4k@2"`E?OC}PQu cAx}arXJ.o9?jm~yQ+G[kNO72^?J,_v"/zW=WvP{+MGA'M$CkS!7礤OjuzS'ϼmȶ}n DF_I5 >}>TJMRǶ R12tk ?u&4ou'uGFB~nֵ$R;_8'U)(jZ7UVn?SoxPoxdwF*{u@lb[Nw[[aY?6=IlHKZY/ew eiMG8)ȏ{1,wml[MKsZkozl).'h 7I\ϫ/4&s]`W 7ԯ_:Y,~z#I yTA=cJ dmO#^x =,N[ܖB X S3xʱ]9ӽUO]d$$J_Hӥ51t0)ң[p.mk^'Ww/zxeck;[73 (0 x7imC&*};X?{j>6 y}&,C@&QCdA7:{"Vbg=N˴-&x:Wx;Pl2uF}4-j,n~TQ{9aȌ\ps5 $X30Ai闸<*kty?)}ʭ%{7oF~48xYZz-l⻱?oQpTaxiCaGO 5_v`A?O[ﺮ{ 2`ǣxzҍ.HQb8ݾ28.?S8/FN܊`:j8OA+|QwR?)xZq귗ۊ&Nu߻ލyq=&d)Mrqxz쨀 o#f"F:/DK*C2CQSUk5ħh|lx}uA]d]aZ{qF6,=EUqNЩMu~ 2B,6ػ_h o1oxFs6{r$˘# ՝~<'\Mw7黳ߑo^Vp}ƴM+kz*um0585Ӻ1sY^RD*>=O˰1Od7~4MNjLZSYXFjYomF$ה lN{iTcjPoͽ^+D 5͞v? H\>z,g?᮰0F},J>p'ՓchuQEDi:?cp5s~f*,4Ӄ߹Q%~+kNi":l(=iT((T$ctI7n3oVMaWCw`ZDZhS[)WN/XDE׀sU_HG 1֜jDvݳ3T鍶Bjc 49e& Y>*}Yd5A-iR-G|(O`R%+yUM/s2t٢Պ5`S |̀M֑4j" ]c؎j~6c`/Ui-}CXWB7UY+jg"BO$,TEXH+v1K&\l7qv-::M0Bs!+Zq,.4Clp[ˢ eb/ <"彉 $ey{2K|3|u0Ug0<qeGݹk 6˫|]4)tϩ6Ckˀ4VFhJyE + \kooAG0;xo'=7 {e43JEï>K8{qn'YƊʵ]y6#*I&R;+ۉzMUWՄհc|KYi^%ߡ2V;VzwRԻ:Uv= A=QBX 3cɱ{~z7N_55^dlyVr[TmեrX?Nv 7ILtm>(_P6!~GlTT o)%HY(f,0s|y {7%Bb?۽*~-*WEYb!ODG֘[E.a9GV9QuSdhi0W2^f֢XiHz 5,^iϺt2mБNR+~)zZ_ }dU>e/ ܡ4۱Rn|aTi Q\F+EV٤''StzhD<{{ T@Yz lll $ "`ꇪqq-'ojP/57HAKvz5+p"3_,^U2ϘE:i71s /nU*rZ3X㞅"efv+2- :"UqC$#?N>F/t;0ӎkƫkN,~Uu}T<[*KV6һD^B%!pH)$3(A!X^!V!^|߂}Tj*gˎǵwU+%5?\(lozw.8=뺵EZ [ΆO M)*AH-g$bs#oɑ -| `LLEҀqxt)Y/+yZ+)45K?қ`~$fWFΐ~i8Slۀ CŻM ح RTs) `owRlkCA`3lj3 {b)g׺6.K1`3rYKG),Sx-))|!>ˀBxEad^ĕ¹b\Ȫv-;g x3/ȥS`3$ѾcdpF nAX|@ed I@(Y mxXX|[ f!^OqQT+.R)), FRbۭTuզ7o|*y[f-LC[ AS_+rs !|HblܠtxtE@z@z <> hݚ%jڮ2AuoL *%9wH/[z y%;ssxTo7ǁOi,*6U8Z}~ Jʎ-My,?־qS5.;I+%)!Tf dll>nб9JX}$]V#RTaWuGF{_*ew|f$WJ],#έ GϜ-LON 9cBrq51q$*"V>ޚp٩mƳN2xE d/<$;mOlvZb:fЌᤔQ*bc^GI9|ou7;T dӏз 7F\q c.>;rUVZGfWl%ݎՊtՒqmT='6d?kJk{S3UbpoS}0~ƽi~BˮkD;kr3XAJXQV)RKF6M-5?wyYg{2J\mKLXkkxp}{?- nnp}x_f~=Y]t-w~&jqf5)zֺԸuK>sfR5k&Bqmq}amm*5OrWQTʝBkڭC\ a,3RNK-7QMv.w][TgeN?[jNXNO#ݺ0F9nj&\WWtKek:APءenvK纤$tÎ<*Lž_> AN> J5Ju ˔E\sUv}z:r#ͧ(g}Eu5 UJT+El7.Inw&TC)ޮEyW2`85|熄^>6vdu,2H]F6pn;f2XSKÖN|p5l_Tɑ U,%òX3|1C<żpj iOwv-6 ڥ~4dz<vq涰̼ [/\Zj- bq Mz+cZoan.(Rr,L6|O˞uBhv"<|m2eGξtD1vle7nЮ)pAzu@ܪVFws|ok9̅)ƿX8u2=R*,򹶁Ç >rg5q7gviTӖaѾc7p%V> ދXޘ#|6.G'{h[1+b 3`: R ȵJ}P3[3ݟfgZ=n;v -d̰ DrQ ;U3siEI{>#yn7&l1=вN:m_ۡPG۱V99^U/֓ꔙ ﷞}P+RYhͫNilmIUO j[MV=b+x71'40kdڮ0hU8s՘CAPyU(*ɴD+ɌZ{e/0:(5Aϯ,)ыxdL\~ 7hWIFᄾ(V/qE۵{ثR՘[\RӤ6c'm~Z@6q[B(w~-p+4*ۼP G7hVti rRMLñPK7q"/}fX!6e~5M>g>O5n;\o,8K`Nby)2cȜ_'s>dc"[ًۧ :gXo{ճRIGSـdTD g#5GOZsL$2{8mG2X6AԄf#}^7Zdsg|]Mݥ: :`5e_O,O}ψ^qUEr31uē낫-{fNlUL42LT sNz>X݌Jb@f,#* ; 7),bxMBBDB"& ') ؊uV.N7=lt?q^7K|-YL ĘV=/QB ? Aȓ6>IhsvtS%<'~//ʁټm +-OhlL_~i+X!HUVP$ Q"u rQ冯/Ny `Q1w(\69IsCGіpPTk\"lGK|s߫wQ(^-ןJw7=3˅m23Z_#ҡ>}=4  X WIh;X׹dqي]V/{ t`5oM;99/n\Z!w:_2mcO ,E ׮A4u_nfiWb~fi@mۀ:.P`CZ PROIibs+zd9W_'[r:8šg_q { @ʬly!lB*X gRINq^VNqo<@σ>CFtbE/z=\cKifџBW^ zG|yrOe=d[<`%ؕ5`m 00O,SY XR>`< R,% tM>ݪ+͆_a3uG9'+KUK-+.P >o/okN?NH`(x쥱8G`pbWkj hh7O)f&) \w\y]Q@oC0sE?6@N_ ηL&GZx2~=aK?L ve-$w %i8y 4w42)-lFCBTr!sJK!@ LdAi uER3!(d  A1|%SnW4R}ī\l$q)d⽴fɼ'IM֡1 <,\H^TuhLqc_J[Rgo?RTrt[3 g(x%́5~QJ[UR\@؃u ]EvMRhNLaE'{xz9eȶz^,'ዴwUOYZ <R;&it%#~0=r#xI]~{>K`N![cv mL쬍a{k@_UR͕+M]|-[<#Z 5[wO}dI$_6O7Xz֔n!m|7Upv*Vyk[i[vim-{9o.,Ubz0Y{\]IUʤvz*Ssbpף_ym m▷*0ƽ0.wo6U _*SsOMJн7yѸX71Σ?j Ҟ<{=0QWNqUO+S7NvXD Wcr.[|\'k;c16K ɏ#&  c !P+}Fi>!Ѽκ?;%BwumWM\utlS__oX^Fq4ҥŀ"B:Myq+b.'V~tmzOYL.b 5~ޤڻroWK3ⓓJx%=~kTgNyXJ: \`ז\wufƄJGMQ@&vU04Oe+i>-z=4o̥>s4O H(֦A'_C6ĘꢒkU7B^|ny׭VŹmגb})sN1=@RKl% VhڂTTA:֥Z 7z>\;!GɡRҾLg>(+/5v|xљR[⽔{J*q3P%xhOEG׋[/Ы!jۋGKwߍ!XjO⯥])Bgr͹7vK&:,"5*펰 p([Q`yQAT>y]r=rWu`I7l,P}~Kڼ{9ּ\]^Jy1e^*w(nQ?] ]߁ ύu,"ζW朊w>$]]r6Bb=.K{uԸg*3t-7To_J$QCrKѰr?9c_;Tћ ъNSQ=+,$x,DDc:jnil>WDAۘﳵ" ^"Y'+^Sj3ä*E A!|^@Hw?.lN51)Fy._7 Hhu̷4蘃Celm~ {0sy|c| t t5 t8c{-h"׈iU4ɟ:WDwO',m!Z_ m>@FrP.(&X:{p0<7лԋzX6I]{4nw5ډոFCC J]As?9z.8ۧ6(Kؕ:Ӵ{~<-}oy!l9$ y$.Fu+Zym8Qk7f{k ~A?bH:+RbRDVnڰģ*:FB^"d3~x=8u1(\zX9BOq~Blfyr~W"ĄQPؤz!sޖꗨ?̜z<|ܳ"AB7HSzzCŒdGim1.X7K´o !_FȥX|P*< >qXYbv5vۧ#ӡw+t+֌K{=\Бz %]ڎn>v-~NXWra:(e"8=|0[&!/ կ> Sf<#*?tė};b 6N!vWmDׯ^V]zIa$鉅 3h/ə',1%+#W.[Ӕ:˾z#L3lgfZÁ@"t=7h1Jyr{1X135U#߽QS'hX]D/;'iʕcx;re0ͅ0b0高٧rC=4MG+ץ531S~h|rrMOa&OAGk';iU"̒5~enK'{0=#\Ɩx w5EgQxGP};+PmQ!-[AL&5L)p]pË[,96 *v對;\X?ZVf"kWwa_?˓2sN}z>?&Zȏt;;v#YY#)K8F yGnc[ +q#'#;Iak";JXn>*^ybcs?tRx"eVk~Uڷ: e2NldvWcs|l|Ku<(N8NCX'1Ju,+mSm|EE.ؽ\l G-FZKhh' 975_v4> z xiYqkҚTzaeaN\F9i!f&weGvR4&7euˇ`S}X^N W֑ܬ\[=V;im:K'Uj)3۝l#ug"Ǟ-9\T0:PP#FO?^kؠc C/4d e. ?(( ?ef>23`չ:n3k0X(y㍐<֘yA1X8BeЇӡS'B>߳I0 ct).0`I)a~0KqSju(%`$ (2;pa5oM)^og:/y{b)\7Y >gE &]5,fg) k*"l!I&f9H9hc} / *?έtsS> 0zٗ Uwǿ}B #2*;8{YImJ ds!vZ[?Vd H|?v)ϟ@ Xt=|<Ӏ7EnP,Gg&H=! nЬwWv7Ovs;}B.0Y > U…Ѐ '> cU8~ vS-]3`rdG9CВ؛p[(4kbȻA`fM~Xp9 >E, u!HB䒵rty"U6o#tH= ?X6PF¡ ٤mà*j([d {8m̟&Lf_O7l_ߨa/enuJf@ǿ#giQV~):+9]=V6cG@Uxcw<&7O+3zSnmA\;Va>%wÌ`>啴Jj걳LuMfl糞9~0I ѐ.q_"Ucdf "qk?mYׄGcnvXTZYE(t^v 04.l:KrzHs,v|,߾Kܲ) "=W{>]3pzSG{.ֺ`]?.?mWF!xF8w:7N#I V!SM﬋!r{WG&kي,ے^j677,*N+1X"ƍ'[ ČُU;7=(nW&r/UJٴy~wo%%*5׈nMOu9a-q}xfڵ[#=x7֡&&JI媷}TdɄJЊZ˷T|R ;$y蹷C- )KżC.U{?a@XZT!T4wwOJE-\ƥ3dMJ)96GY<0F7[Lk$^]^y~:.bS57ڦ>)<5Vh-WGU^}BStärWȴ-ƷaϋF3 ,cuOěӥK{Wg[Xzw:1s,hֵ'[VGw}jf?;}R$ cVÉ(8,Be,wZiZ{3D}wmC-MgmU9l^, koݲ :;e>Y%kOv4M:g|ޚUc,-94dm?m] {kǨe8Teb}~.܅a~?kKmgs h+ZnfB+eFz1[eCqnډ1mo^fE= SzC Zk]ڟUT6 /N@6:mn|J6V[\|8sRC;v7.\V9į%(j 7%tw]hkD{YyջQ^UNɢ(_)e;hّzu;OZU|O15i]- BV|C6#(k[>l0_bYۦc&vN@?UʜQWl}"|Yn|?-z]t77;nk3&~ p|YLG9ԖK]ԑl٩z4_1} Zyu (._O$+Md =Df"~) E4!f7D%8GUZsĭVM K̑ԢʑȅpIfk&44hڷЯG2v3W͵#_; ʒuqdO;bf> pr[6r}۸\}$p[]ղeeFd?s̫FX(fTjne:tnf%RVZēUaKFຢU.׾A3b-ޏK=n F\89۱;Nȱz12f0 2ڣeQP=eꓥ#ۡ~HwYNh42, 7mgJYeY,<10U _xWȑW6˼sL#6@NOtK#i:QP*MQSuMimbE<9&Krœ gK:Nء#ߛ9صWm'VR9TǹMò,`M&]]Z1uw%C=-Wռdȡ㤙-I$b Mf;<(|n;3ᄝM:jihw-=~{z=`- -;܆Xl噦,bӧzktW'^D̀˔o aW33>{s7ymp[7K,_߃۶Pb/:zX4Jh<:"8H u5/ME|5u_\OzZMa6H?`=yԣ除dt|>z rc"eg x0蓢H z]eуrxBf]-k]ck .ro4NOI⋗]!Uv搣W F&6ZM0ŶGZ2E l^Xnfn+?\do푅!\)uR;[.ڨ`6u/]1Jd!$?I`m'>Jz2~Jvve̎Ik›LNT[PT - MS*S@=EB +@T,fi慾V8Y=:n '@7,aų7Y2F v\^1v;%2?vᴏFCw,} Q>s `Z'xk><!J8(`՘Y):5$ X6V?KdBoΌ s}! ܸڎ6K;sM&H쎳<LoClv~ر;+ Ɵg5t*K]{NJ`b<Ȁt4aˀ{՟y.+&8[v&uat<\;໣w,( 'v,ac@ڛ)ng f!"LtS <{8т׮^N7!HBoG-KXo~-?kOx c'+RӀ U/`ȐJq~p@f>NLy2 b)C Vᘧir Ά?WOKə|&$?¯[//@Py>x4NoAfyv|w6 wW2?(k4(DB#[( w6fW|/ 3{ ,k~(y \`%1Rw$|q\Wضv\D sN(f1aœs:s}{y!}UCse{tp~|gC {r~]ta ;.M$] WR;"L|e~n?,6n2. c?+c|d5 OmZP_aLΓ{# endstream endobj 28 0 obj <>stream 57;)./eZ_j0Op~>>xa>VwQ8]AJ1vcaoFz3)=Ԟ8z ( HcF1dFWI#3Cav;s5Gdޒ xefBfGÅ0.w%z$8ҏƨ(LW=|lEcvvӠSWeo UM o4hn|,lѥ/ }=z(`y?_]O>ߺk~u];5cæڗbCeVlFKKa3rM™F2Oo  `쯾I}?/=tp{6g($G x?6^dχvl7@wrgW[EcMIhCI]aiڸY沑LMcwΔmq{-;[^]7*uY]G]VjUުoL=ag<E"Ȉuv~Ҿ+gBM#acTW7Ȳ~o:Uv٪욳N& {}LVOr^zX#-Xi)n6Lv^L㵭u3ҳn:2/k>Uz~׃ !.q˗>+%#A/l_| ֊R;,:jTe㤋h5 ϗnb0Յo?}ϲ4?8}c$9VR_:q/]P_Գ•Dʎqq,:`-x / 7-nH~P s\CsV\v87%;\d[i VV('oYj?jRia?EK~#R yyKh{\}t+_T(yi9O-&f6v>E5g+99wfߘYKR^m x'kǰ#6SOX;Kiu}Cr+|{[;ܓrFe ECY)t3?xƜ , vzzQVV5hz ][VFk?Xcof I^L=G&#m 7M{VY|nNC:јٻQͬ^mB'?iU{nh,MF=qZ(ĺ+TJQhȽ3(C&PEt;'s/X7^,|ѵB}Yvy R0t]2ғbe{Pt!ֶo{Uz$WU{G+yi*4pelHKH_B#&Wa,M$KrNs0z}B=O g9iɌ/cPl>T4c3l5(NU0)J6Y |^W?NbB/Q4UΑcaFOmt#mςwġB%tR~AN}rV3gojS 'Kyxr[лLFtf70%//ΗUm"uUUZ*PA).mLkh L~v7XΧfB3Ѹ+;a_ĒБhR$fެ!}G@_9_"ލi%u,cajXlHĭ9!E#az4Қ n*b6Ά܈wLl[fJgPeéR bjl'I_jIivzSNEufaaΥ+δ)Qbأo}*hEkO=7Qv(tTy\2n}oi[SnzJz^RBXiO'U*mX97Ӷ0Eg~I߶@wִB/@ C]LݟOrq=(Uې <Ʉ??~id6 G|u.,=y,)B&n4\l3Us3rqjwPgzV c@ 27r,`ҾYaP<&/2/' &WIigf]u esѯ܀ G -3k6 rڮ{ܾ<1QT&)e΢mFڋ=@C̈́FBca]˽UfA=K1f|Y1)Fs@V3$œdeNR7l`@fD%Hd~,fqkg1SY>/ 7x!ұ]#kxMȤTJee@fPnPm!NѺU@"u&P]KqUU߀*DVO&`!C86YY9թ1^%=D]gv wh ^L@=?'$Ͳn ֨xtt̏,}i-Ÿ < e}}&XPh8,DqbU9z&VQЯ ZC-c'S,N`2`Uҭ v̪!c XFvXlvXdv:`*+}75Z}}|lX&?9$q,a‰ l< @9xcK^hy8/0xc^PvI.:ւc(5Gp(Au?-00KWi?Q[%@(. DzMV&鳉zĢ:>)&szA5.͌X:4{Δ8l`v_QR}opNY{eWryfS$0S Q 䡾rŀQc5 k._.WCnN=h?@Uh~u ?+yYj5"Obf`٬1fܤ~v-TkG {4^22_ (VmS?@V_noo+y>I]̐=h8ٹ||(_a\W={0ߧ_w8G^A(,w%uvՠI')^poKbڡO+%%{bv>9 ةp#yWs.B`jdgϰKήw3m Ϧ}igm9=j٦qF2?I98UYR)Ÿ|iumd`?M¡ڡai0-I[M3Ad z\ juZudtk>%jNWΚWSԤRao$h0oO)PV [ǟs>m XK^H6niܬ1Αzl"s+LR 6Ya/.ò4Vf94߆Ne3(yPҡyŷoQ1YIC.Ehw Orz.+0%G9ҩ,-ݿKà)վiW3.ݣxS&oe/bPqhD!Lc8tKแ \g;4sǾ,z JjzNYՒ^} 6Jq,xT-j\} ޥnK~<5qrs Fۗ$ 3rEӉMzmU{Ќ"L΃9Ս\6sZD9@uy :=2G,\~\؎w.ue*q W!ZeЩrY5 eNF;u~[iY133z7a~n8SKԉƛ6ֺmJ)3WoH.mw]wsԁtL9ݳs..ZCnQӥeNKCȄc*6f2 \`U/INfvYmCpOZa I J+~ޡiSl/)NC^drw_揲wĴF@2=2:hu4 ]˗kUh[Ћ$fR^M9ZH.*GIV#=4ec3-]OL{Q{?KLzdNYYl̐^H8 S%ڭa_D!x- q5#Z*,rl]ekakV`k9x]ݩ O7l  jZn$DPP{oiI4gŤ:EJBlM [G@&"pUg6n.Z3[֪,i94#5}@JYjΆN_fGO6gbQpz+3-G8j/4B@ q냜P68Z(;.xUcJ˜;dʚ }IV6yzt6׼&slʕR˺uy;*pܰ׍,jRR:"t.᪍hx"#\x޸,7L Ȍ'} .2|M:DT?)Cc!s"sŎIfNL_brsDDOc 3 XK皠}k-Lֳ'Q\ٴKH@ΰBaN;y~{.4(mC!Erx7dWoS,#ҋȶ8>WT /§*ͽ *_تthب~Z uUgΙ[M;/O")},Wǯ*U63H1Mh5vqpr921u";yKT6 vb򎕽*Q|FAV(j@֨՞4EWmf]cUWzhSPXn0ztdA!!!h/F㖧cktf]ƨʫX!Be9di+ iR"CD؏l((dDXf') [OseN]Qe2vmONK$#; 9z ^/ gY, 7'hy(E8"l,($}DE6tOpJAY % )67n?Xw^7GƬEstԜos߯5Jr2('sלeF%ǺȎ.g2Dq6$Rl;INYe#*)R߸)XМ(LFĕZ<_e8LL-L1m3&ƚBbhl.7U/?eR">9Yܟt~44BNOCFECj(@Fr exLV#0KKXQR|s߂E`RsP51Vz6R v=Ff..Gq"8#9%L M~Nbg1-#8DR^K{8MM`bاi,Sܖ/Fl[r4}}uh1X.>OL 6x ИĘ!&f&r {5!Bϓ4৙m,)i%sӡ/'fGכ0|.9oc/8٭ :Jڒ Dby?#<"QV4r~9O4Gy ^ Y@6" zo}qWR$@iG)I1gq98=@G@&wiinpP1Q[sPd.6b1]^r5qxS H8 ZC. 2 BP1Hq^*c\R`@AE@! GMLlrFed-Q(_om* n֑,Yu&Jy@^DP,PfMT16ո1>vPvhkR_.@\x6k@r \hi%Mޠ^[)kwxVmOIϭx8Nt]99<?@]\@wmKVd\f4s~o{§XK!`Lz/t@szYQy ld{ԲcIܤM9锑ۜľ3a[;TGmU}JqVYM\n xSLp7lbF4e)ΒZ[fxk)Bw; V#S*tX4V<'~З) < |!$i"  F  dV<ߙ=Z b"jQ6*QgџTzפ9MߟK`z#zdx@y !3HwKih]ר'KdYwlJ~h?/bx:ޟ_j8"O1):B;ڻ5P Χe_/a< ~Bŋ@{V>+ϗ?<]krhn>},n!_{xrÿMĄZɛ1a 7ct`n?77,fxdp75:8vԃImØ56dmY^ɫ vNaqViܾYzrF1>f ܥ:>X8Lzzl:{:޻F2^3%x˻Z.0,V ϸQid]RĸITY,% M\jWĈ"iJ6и{|[3.fb- Xqڥ!5>n\ĉ\P0OWtmV\g,6_aRHLYnwx:_?n: ӽKN~f:!MۗP#ozF>n3reӂ_F@؟WO-]_B.nBgWZkr&{)/{Жz^Z$Wz`>hk;iB4vugϵEj>DRȪr>n8xfc (zt)~l.h!jC|Nqso@a=CP÷bF:fs]t+5[4U^ v94ߴ}\K=g_÷p)&TWh0i,HO15~'ӡ{~uI,It֑Щԫ_qaplZgДU҃PgemK)#} bűEh qel,stӱz7+*ޖES9ɭeшۣ)٪<*C}t߬úoYQ[;v+jLjUpz }?o*^tl8-g-WL { ~wX%aYQI,tjUM[&tuF'r]/E뢭#IWkWNb]9.nSY*\ffRJBmk|dL2r{Ɗ5a9iS}΄c̕QO՚ϱὰ1BhJ˳̞aW"_jiә yHmLWNϾO2BQx  O#5zfwŲ{4^ #Do-SR=P+.E"<$-&y㸌ws;u<1uvU_%or[<%u5 +1X F0CXǣ[+q;җcx1|Qk/tѠ39g_ NT#X{{G[-ss +Aj#;)65tcQUF/w/ΩH>Un|K3Q}3bw|9P}\wy\\IRBR"RLx_5yl*XI:X:3t3qOhrugآ쏟2RoFH^e*~Sj"Di)eVĸM˰u}3풎+ |D8=[mmgJìo.+l}7V K-ڏ21kXr=|Lˣq|ӝN~LLct갿UtB rAD#=*"94SYkR$;v&p7L8XS|=y\AAs^ZOr2HG.Rױ\9yf-~EH_@6?TEڛ='G4{f/&ɶlz6ϒ) sQGlkExI#3\ c+ub3Pp2v\>~/DQ)Nȯ)1e΅1D;M~pUqFw7n*{i};y:@,fdMJ+yU|/N!@Ibw()^&@nYcPyŕ,fu )="O4#cc􄄄/Νgۜ?"wf"V>Sm2khD,Zԥ7Kqts;&-@y=>m]gdWCeF6͜Fk$%Q~GN0z^~whX2y#3ˏ7`.#^x|Oq$V.M`%0y>^1#NQy$٣f{!$e AX0S༲F#NlSOKN!3 p.Fp[\ PUNqv#sXj]KcwJ5Lh ئ(/,3ٛȖ7fO77 ,<S>=]* 0 LjM!v9@HF2A#iV,e*c2#ʓEdI%e5>#=@Դ^+Fg, v T$mYTBȊmÀ@O 6 EA$ɤUV]QUq&?sU4rE%*M:#DTx!SBdX@ w8 ͿVd3)U膀:~&:)O@$":hj"5g Gy<3=͆@2wQ dpYAKM\Z.|~.ү}jUl0ra rSnaLSV t7CF\Ùp.4ܔZѥ~~\gBwc,3cοkp [;fÎfonm<}X3dPŤ|a`+vꌅ]g4 jxoCBv\ Y34ήQ/mu`^<4ќA˃ M SNjH{ҸIQ!څJW(‘ؠQ~l+,9u) v8|[[(Y}И-[eKl׌Rlatr`Aʙߊzx#+[zŏ;NF|,1ڇhǜ$;MpƐ#Ug[}-m yu+a7 VVhњٷjoNm‡0W~rӶO 67S2ի8Lؓ8h7qjO쩗G ?k+E[t+đhd7˅VJo{ujG1MVBɡnʲMuΚR#NQЭ\2F)3]4ai|Dظ gnQc+M{t;~Dq"1|Sf֫S7kܠ鲆Ro 9Цx $-bd= .lv66?LJŇ ce[@ȕ[N[e5,=so }_=-Ą5rY+JM<5rXbԨuۼ ͏*VlUbX6_/>"܇V{žAQ7`e]Ꜭ1V"W1`ќ/GSFGn>Cwb:dQx=Ez]A+b ,?]st>Ι-oZat,ˠb%Aϓ]j&! Nv&9G~Ut?z~!Ҋ,`igI!}Ll]jǖd?6kvXڣ}sC  \:;2b?( U\|| LKאyVS "~.@9$~`*ܑPVx ?{*6jπ(iGeNL?s@:@(qxBXD]Q!W$LSVȎ.~2޹|spRb-8U|}xr[cGE]>m]!_v ! H&Y`Ɨ HLAx>בBNj:2(%nRdgp(H-^뗪.iOFFltd}~dp "WYpy &-@L?YxjN|Rgɺ?:v:KDU$oN1x2JFm>#!&T++#ݶ|@a3blL j"y@3)WPŋe -Bu5pVj5?j+*fY)/(.sOhUNyJ${(//`Q3A`4A]D(@DfWzCPvi!@h)@kE vT]8*GZgfeԅbmGyI,RˋuVЉ D !y|ȑIJ*`v̱GfM \Gއ+ `&`-/% Fb'U|YѓeHI+\{I{bz {]+`>`B[߬ȝx vˢ8\=WdOJpmp/]8!]nc~z-}e3krNaXa%ZImo:%=OHuWG=kw1܀O@ F;zqHVgT"*esl4a|:FJп3yC}#p+!Os [- c . * N&@8w@bXBOIRUǬ< V.ԒQtQ L#;#{iYlҴR#I-ԸG$O 9 HXqzpto[9_#n⡂Y :YXS$~W?mgo&Z-/ t! LQ(pI-@\ARX} iɰ}..7o9"?ިoei G&ohЛ|9D޳|s6>mdldSeGi< jO.XheTAۇҞMyYeu+Ց'J&IӵKkbe ե0 =o%ZQ2+,P5~'oG.٨9eih"Ƕ>͘b!U Y4sn,!3QH-k+gؙl]zVJWm3{]f#N:Zwd=?b7>NmH;6:>kDb:I: 7;/hC;`1t7aY0kvY%b6wݭ^:kIvΔ@2e|mR6 7́2>0#e éMTIVqUnF 0,FZ# zm|?: (--OQobBxe<\m|TX:/l0G04kދ/WŘx8$RKZHRRpC[yPr? 2q,'9@G1ޮtv1@ף\ةۛkMjF$24T|-("<~hTNܺ,]RJY VX1Gsrl>Gl^kLp4 ~\+CGՖWF$AG!-.U.z|ƹҸ'Ji4P.E hux\/ThycYfgw,#v9/:|-)ĭ̹A/d=S(d;EK8mTFifwG 3ƍ,W=՗^ӊzFE vg)7_|ZxI|wKfzXzn#;Y=g|k9(,G_q{AvI]6\* `$ᴙGe;U-}6mԚvt!U|ddϷoE}2q+SM)! ŭfRfJ3j9lg]uf04!'ĥv=ٿr6,.X\X/.RB\8biYWQ[{fdsƸ;}roA:qSㇰO!l~^9${!&L&dHHrN%4PB7dj"%MRogAD Mg8gїs A3XvS.>A2]&ۅDOqX CXw ;!;;ܒ} C{qb-S]7.gwכ3榒cm ilH;朮L/gj UwEUcKpMiS? hN,#vDr<^+\㛵:^Yr-OED22#|>n.[|Gh&o R92"nV#MO*EJnJM]#gUw^'zl+Y>2c]Ĺˏ9c&8=fl͘S 01yиUeHQs@nml'J ^s%Wt p B\n1\5Ӹtp9\DVwD2uޡGG=ϑ_iθ|͔AFWԄƯ܄jd)~fdZ$GK+bvD;.B%#^quepȶqiױKbcdR ^,rFީ}O4αȘU D-,I#Y@%Sqnb!ゎ~=g=0dЪӄS H~шƟ(c;XKvQ,h$Gh.f1 1"2 |+"c#]ەh}a%_-! w@_V2%`9<&6b r Hӗ@#5%cbm uf5ƄR&:ؕ;XZ-Tjy+d/[DprB_5 `F!X]y l.W e(e}"h)').ூrT^еΤ|ʊ 5 ia!Ťng/Nk.do ] )xR+3/H@LB5 /2'rGrUoZыw5ζ:%'L ˤa])61l} [/36l?RK+c}X.kw؇u5ܞ6>.㖘= 6Od0禉܁5).M6 tdC,ṁ dQ=@KGᢗˉMn DD=DBzSH~Ov<#Yo娻XYr"rgcY`!,_ `- [@{@+CY@&  S$6Tu8;@3cATWڠ 3! Oe6K)戝:X9 5 jo9ݜAP6 a@xK*EHw(#yy]9_ \Qs~;ľ,^,ҕ4^%VR uFuiN]g@unC^H4IB?eS94:;-؇gw S M: (: *Y#.A~zr<]P`Y}aqob4ugȨr< e7dy0!`j4``0 DL2V ,;H4;A䇙oUY2IL꿾=v{ &H@OoT_%%F:?e^EY`/&@v  ~IN-%` XT,ۚKf˖k Amc0a Ev7<oBK ȑo2LNs[}*'WWC/b&a46~?3W x.xC- +XIQ sRhĖ8(o8E:tH'ԟ#:|W^,WR_oq>zs; < w5X@(/E 8ӋʏW)ș9FyW;*]tհC{uir_| ( xOH5^')\bS.G-!O EA㨜CD"*1i_sX]"*ɬߵHa #k)=ɵ2$CwouD­0m XFN$R!H?&v6a/W-3[ 3AF> A: n =×d#|>ݻA#7/^$oܰ Z+ydhPJlwAWyolR9qEY}J ՚ڒ0j ռGݧ=auQ%+uomPt譭$*뻒lm{}8z PߌI1\E>y;~|m"6`ʺt:c.F3g-IJjMj:<)'[}iEG>ԈohӅʲzKm&ai5K۩Yc5~`nxVzNӅ< 7S&_i^8a"컗@GQ3J3rvӢ䁌ֻ][*QEXԤ/V$F`3_dB_"/:=ja!KcP09zUUt ZE *n+τۺ<%SyUʩsOGz1iTe6[ DBjYaX.R'# 5N*n#5Utc5ө h;K۟]E<:Hl_m^X+016OiR U5]{RˇE8Z35:`â UoNFV "pJw4ȇY B@7J_TtѧIHEȊʇrʥqu*ɴ^[WqG~<=y̠Q}@kY(w"oK/ԫE54i8S<( BtAi\NMJi0+YQT]hvîHQ:y"Uryg?$9F'>9MLj!HDb0MHDLe dbi9_r,9wm铒a֛-)0f,o3ql|M'$=htv˩6;J]$|*-Ը#+<ѐ\=L׬Y~ɧ|YO@B(q8҈^22VGt ;ҌUOM'wodN`g籸L!!'^os cU3tWRHey95)'D&'Es9= ey٤b 6o BI4E>/٣(SvA\~U>S$ީqܵT',q+[Bo fn.tZ:'tڣmnT|㙒_%[W Aj)%@-Hɉu).&а-~/ֲH<ӷkxS. ha iSq94X % 'Z3m\grmfDh7ڻ\ND"wl,&0*5e#"ފ-T MSfMXBrULg68U AAu]9ʍͥE\ds&itg<;|,0Ju0sưZ4ZũsEGJgXY ݕvOwD燵۔OWweg73Ou`esݑy^o7Ƙ\ fNM˭L֠1N>P qZ#j0Xe,lRs{$1q) ~EON)M"Zy1/C3AC`)A;1Ρi1U=QKijNN*ʓ&[BJ2''C#tؖpMlgx8ռ7M.#$n8*s>c=b.7`;йhrNz~Q %UrmUzd=,F탋Y;G6~`S=x7qF!]\̫..hir3yej_^.R/#ҡ\6eޘA Z+Jn>*4U-*C!Ftc>~+Q\<.ک;V( K[^qw1r!IGҾ4Sxb^r{fgÔ) ]M* ɂ%]=41Q*<0cbsF Kc -. T*hV %"2}X1Ξr %FN>-i"yΒ}RXsMnvD TWH݁Ge.H(A\|zyب K ni'Ӛ3@fkE Á>IRyC ҵЄk^j2%ҵ; q ПYU xh'v d ``PQ"i)Rpy| JUtQBxCP#(t.GLW:bx\v]DR9 zZԐ=荚}BHB\]$g K]Ed|[]@Yj-!< T`p 7#+9*ʐko^PO}_j9a44qFd{>0q5Hy^|%1Cxsh s-afIExr6a& z xVbQjb~DN8}|ڰXY0.<(Y($B}|*C`\BAsC&vxNħd `px ~"F 2th\޲<`kK/{),*_˕ƶszH';:> x=VG^C2B#`ǯ* d+)]B< B B^HB~qSkx=.*V)}(oq_o(kE1?1x#,CU0rb<2]؀(>W  jR%,aXVۀr> tTQ_(,?"OVd#Y̿ry_R"mψth0Ón>RG 1&#H6 rtVoV#zAVo1iCҀ"aY.)vT<]䏒9dV_xZxrհЇ' `^O r"_r? ߀no7YN9P ªd(vB aq2qqX%&70Z 蒳Io?S}w@p!BDe'"5M@ˀ>[/ NOZo c, "%CT>;oW(h{u{ZMo?'RMc =lg>6; Y s 6ɬU|Tp  5oW8E}}*NNߨHdm+I;,_݌_MZ[ǯO>dp8gN Gs϶MDS+?IБ8UCs&ՙeW-$O { <M@@nkM2I,i Qu08~8(j+ MѿӡT# ?u&x||#!rvj)q@zY ~.n":Kv@^rB[Y 7Ys1߄ٳdS$F5#7rG$SS8d5#os˽QHa&"~˖<: VL>$SX+jW̔h}Q1N5_G_rZa/Wff#7l&2dfd\ d2LoH/HĐFadgr>K/sW=w?d\bѫFRڦ$Iu?ŚvJ2V1rٮv;AoF b (;ưvcr3hӀ"q"r[͝]p[Iv=(}n۵5y(d1@?J{Vs{e -w?lb?#IoѤ7hf>Hnɠ=ٞ-$èZ 7myUxިXL\M/t,[kʬ@&f(^"{'JNޮ@ժEūWȒ&VS t2h%!׿Hw ' wqcclafiqϲ>[CwoSZ0yEV KƒzcܔXi[f?9ڿ1;OOpw>>j0[LW=}:ƽs.^M7t}V ņۮ#9IxQkq+{}ieW[*{ƉZ-N:4H.Qr֛ét"7e1\/(|iW͕Qոɾv>0IN{[,0y嶩UTJ\ spQJnO?9KՅp` 5-e74i"i31;-r ZOĿT˧\C^&MܡTr7+HItB,%N6K&41G;ϟ=Cp=f#C۹=B ksMhN81; d'8i/<DTrpJh:hm6=nsUS]o^΋o/$,c(f&_ty~h' ^Ô^}v7$¤}So\jO8Vνgz[O[&:)=E_!-yݾu ZZtXϩo/q4OYh>m&ECJx|GQ詻żX= Fgx\v c{*~j|TzK؅9=(sYۮ6[$i5_YWk>܎WۖNl~n{%~՞ݜgWgX_ I堡Q[^e i`mll&ٶÕMp 2w x<=sO{q{e4V7vr6>ΰ71:+h }Mq?l-:[r/s;N}nͽZk}-Vs;ՕQ+uoBX;%hCg.q;`3 }JmDlt'4.RKb~OI_ki;GPI`[LձT ~07l3)?9 E[?ћEx+Kx+_;<~H٣  QvQ Ð_;7d#B~7! _;՛_7!k!Og6#ը[7zܤyTWs՗^%>>sP3pT o3 !maH"~N}9y˴d SrwÛe+6ħ%?f<9T'{TApFjlb"&N:<-n =OC,9w!|,Ć,]ZtsD:' E9S?.}6 VKLm1m(F ̎W ^4G!T9ACǼ &M GL!} OMGk}2 3lvT$S4Yi~OqTΥ 7Y U j<9ę ^qKܾq@q2yms'=);[ fg^iKk< yD3-[|?=n$ք%ٙ(!tz~k (=K{1 \nҼX:z.R]Q C~'sYԙn4˔!`zK#Uv׊ut5#|6F'(Ű msM6tY H3VaGfIwꦙyRѹhl؝ɻ?\ڦ PI RQn8@@iٷifxM3U{w E6ĂKK-CjĚq,o/yg*{ގ˛^QG hy60B=m[to5'qtIȷG]oU;U Qdtgz fV{~0?A뤕J^ TBuk93_ [z_n.]6v#:^-ݤp2kx ƀZΩPэԐgjҢ-$͟]l%g uNi΀lf ^ƣ?řV[G`=z)~P&')3K-ۯ/b-w(dqO#m y70Sűڛ Hjqr,UESSyy2T'#pZ χ;{m:--2NWH̔ZM4KloΗ0yܡi3ܸØ/u99yޜ2nue kytI=e%9EcΨؘx1D>̠Q?W.cJ=<Yl{;u:eڄgȸc鎶d-SPyiABBIU?]X(ts@"3! NP~HܦeYHwum8*eF#]M FYmj]5S|U̱QQ9\W{e F翆TЩ%t~il- /tY-[xroKuÍvǤ֑K-]'Zl&0I6I9`3?p+\_~Ň]1lTwEj7] ;ceu-[2Ӽ)4|)i9'۹ ϶vjQTg(TgT,h S׎~3J_:?p%kGOB)kG?/+a z/a '__cRu]|5HU\ʭjjӢٚPwE>% .aHSM]ҳxC0Fp5+ςc;g2gjO6 ֪WZgnՏ=`}v߂GU450oTgHc.֫7<Ep}ӨuL܌sw7=!S%f 0e+zW1^fK-VKi<o6Id͛E7m$#sBK]I?@8U T{)yjx8乇Y7T ϧ]:kMa#T/CH4VړZ<}|x%ނT;HUG U3MPvn\{U콋EEJ@Ns2?&=p"(f:.Ջ,h8}z£)or*Y޿4O?ʁ@4!%v{`skT*rv~}nb*{" $Ki~f l봮%E|'ˌLb>xJ[2̈́Ef/"%y#VBDK؇>5늟ȳ!$\ŜBCoG3*)j_(%)TI0O\졦Xɿ&;Xa3~gܞxʛ Rbwo#P?|xcqX;ŨCUv'_SPx%, α4[W[XxZ_bo$N [8 >e- V7ra Ɲm߇Ӭmv(RlR3۹zt\\OOH)0k$s B8srM(#Cnv2avC)µv;c~ Jy=ؔw; }\8MWs7wK[Y5ou֨QHa$Y%wwΑAo%*d1{I"~tãCǡYWI!T|ջJSQbI nloIvBQA$\9Z7a~bbcDnGhb{wSq֖AV2N;/-ӎ̇jHP"WoIWw&DI:b~{D@ucNpTaI{I_o&)>#9aYcS2igTnIpp9q`ܥ%wRXKn(M}}>~25,&Z]}һbt: n~Cl¦`Dto[Z@&_p?]y4ad3,Lc0j#sX@[CPX˲Ʒ*ye[/3up"ps*R|(-u~%Xo{Fuؼ?ZK*g JxCܻ2n92=yʝa#}"3J``? oQ _kW )\?ep# M࿭w(>vcTϫ-5#/J@OZ޸]?+} 3WOz g7|_q7&%7Di!=UqC[ɋ<N\[wlܳix{j|}^w%ayp})ٖ.R2DRBڸK@!^*T :d~9?^o i slKobYJYES@CCw^.,rD(p4 ZjCfݮ-]^٬ؖ= 1RjE7.bF>V[-9;,bRqܙ:Pvձ+i B*@#s/NF~&$cow7ww9Bi62L\l<$Kd"/ʴK[D@c>i4*_6-rנtP2U*d$2QpM(fgaFyxdѡ`ڷхzpo%?xC껟&A{ZF5ydTfޱIf][Ηޛ iYߨGTձiOiwT 4g.YJjB)|KkIybso9w=+}4C4\落΄O/Hڟ`fCmc7Zz;5Lh55?kU')AN6ݬKvF`Qw蛔=Ga nYwGb򷓯wTV9-N W::ˊˡE2Pb*Ͷ90W˒-UϾJ@\0;s0X_8K%M5ԃ5xBǭ}P k򢌻T*ơ{C}l5s~2U%v?o.(ިDpI R:ݩ{3sEHF 1!5ocU*gH|$\-}4[,{z1P ֧~7%&'F@:YT}> ;p:GGfSkXN(r\@BZ $i0+t0z$K $QQhw3ukY]WJh^<|H\Ug*5 M0hx}_kޯ'w!stДN;P"{s;WA'ڬIV4*۞^xز6sSϪsBʱgo ;Dл} )*s:.ILF N*U2znÔnlx V*qQe3-)cnIV!m_n=ޮ퍡?\-xޝv6w;|V:UDi넟j[&DŽ,A!{PB95?zAzPlux{v(iS]QiIz"!MQ|6`N`uP:iA~/嵹Jzm%2iF+cj xyxs U }b;!FOmI~IxA=vqVhw?{w'{Z_~̰cy*2{7X G9xנT4W^|6whj'ͳE9-r;aKuXVq9Z<Vcv^%FR zlC1k4/fV:o{FjP̆^zՔ{+Kl3K؋|t&p}KRvZ #c>d^~YYyyZ`]5Hj[s\uZr}@,S+deQ4vS;apuӇ_-Ώ/Qw?࿭ggLok/P&?PJT^@An]B$bT-nMN_) G "i~A(]w(]uSKT# pLyN]G{ ʵ& yKܼrY%SWSp~wD2<}i ?[|AeܪQm^䣽/TlhAMDt#RH8Ӟr]Z+/ؑ}yU)~ɻ_Oꏓ&tP L*~7bzY͟>tBҾ-}μ=`vǞKӹU?NBzy2ye¢\%-(K?PK$ؼs]h=6:2(͏3&{-Ȝ b-Qzqg;%3qu_\R &I=ZOAY˃>A,_kIQհR:+F K۷lYe'Jm(՛lෑGE ON UQCܟIe~ծxR P3 8uq,Kavi5U=屪F$| }Dძ/f4tf8װ@]?Pu_̆sA,^ ݫ$!L) %mlj}ӓs69#j;έa-lԣf-_t!cNP8to4cn%:{Ekj ]eڑJ&q+9jap#-3 5Q];aiʽQ`yEx[y7)T"k眥+R۬JtZ,`=gv?2PSr砗hsQC9`_!m&*E5Jo2N'}RAʹLIT8-j秭ܕ]I54MCJ J'4yƯ lԱl) 8* $Q.p:wlw7ИIԏr-~:?)'L̃]1,,盇~{PFd1 PNz6% krJq0+AsO_E$t+au"tr9K99o/\  'Q})|@}|ۭXH?&k{aݩFjNIJ[T3z<mY8Mϩk<^-벚``r^}e=~,Tq-Vzȹ@_zwJz)rYFR_!YG`wg}}Ƕkq7rb:sk-k3g;6g5dp-g oڜփ\O%)&S2;GMP[o3=$F!}@H-ogֳx͔ 9$tz}Vu5lyԠf+Z+tM(WKJ@f#6lr)2?+.bTmS{*Z*yٵF47RB(i~%ck[ȋ~W\̪Lcb BaX|QKڬ{ WPg-Sik}'w /=8fl`:| 8E%{ߓK"i.rR̝a)e28YIxM%cHZwp #r%jړF 2N8-AG^D(t-uYbn{VnZqN9rQXu b['N(=n{fV;";"U"K9mR.u>:vU_xE(z* ϩaׯkdSɱz?Wū.{Üq_@[j|~$vպ {h @. 8Z0LQ҇LerI)s0`fUOh%򮞸'5]6r"'|u=cU6D$] lFW|&z*`]+q9Gm'USl⊐h*oCrgb,OJ'$PD j' fjKf0 =pzoHVovAoFݞgh/SXCq J$IX6r&hJMB?9~$fhdÈ!%?L@H{ <UD߇\/ ,Yp_VM"[NGu7k3'2l(5O~r2v"}d2WI=OK{A4&MൊlI3̒c~h]BK4]zK*}c,NY*$1HOa17RwIx$)M'N*3ߦ u :e2ry(z5a)nյ7%L9pw 赟">?vAߜ;%NͨFUOi?)]JDPShM4z!aۅ#zqcpo#}08c7;2Kߜt1ޝ&ia ? $1]xI- SyT FhZ^7YP:8xI niK26̡-F:1grny:;h~战4ݗ􌌵)֘YӦ9'N:J/ιK#}f$OЅ7wPvb,p(Evv[M񷵙].]IctF^%=1;JD]a(]D:/;ˈU<H}.H(*MwjI?2aZfJ =jުCq4JP)gÅ\ fE` 3;h@Hf^G*YȚ#n6gY9k~ L ϣsCp3} ֵsHփ{~W{\{3{vQ4 ̟Jv*4t+ ̌Ш<95Nǡ,/靥m}NS4_1`NBfKj_g[ˊҩ%IfXR*Xi(c+rfgMCROdvhS[Pme*3 r8QiFeww"{eƶxYj]TX+[<$2nCN,ʎd ge>=k"J'oo*;\5ȃ@,w8eCsiSisOTyŏyϔI*8 ęzB=Eap}U]I O|Hś_lnfΩ|٧̂u>k'|UsQiFor"eMa|p?I LD:6M5@ Nբe^+Lh8Znf᱒tFs5즭l.C?m}l&L;hr*Q'?&dZGBDU\TQ4 =w1燣3LSfwux_:iXNs𔮻RY#cO_Hj8s_jTm7Bj@HU7yِQ+qjo&scSF͢:lU óY\QHG|}u@W)Fz z kqdr08'*lZLJ\I{6̲(~>ɍ=jnJ;dwײgI'.0AӤY&"5r 3G*9]Q ♔}Ǎ`@o5fm+B K xT.됓^:j1w\WqЎyK&R',QŧT@! @W>e{JTe ^*]gBfPxQ ΡCtטܜWisi_iHKR$&+yP o(E}Z(E5[ D?^A=( wb~-uWc!BUFVf2hviK^) }U"p">{oMPMTVBToD:6\~Ľ,cnj*b2vTI53PIpPj ޮYNr0N2~(W%@xYjUT lT#A2p!ٕK]9iEU:vP;iYh58d{}3!vy2I* Ф(4<ؐ_JmǒZQ@ejջz'Wjp7ښ3ޒ~7'U47i,lg]%~x3_g!۲Mqo٢ar:,+/b.u{'q$}i[}S{*QuyGU7ċrMJ liWM*A&󩂣Auri c޺Om|$.mABVؕ s%l~;Uͽ8M>5rdw;Mr01g%jrQrýwUN&dpXlpoڨ{ʬ/JXȐ/Z5Zch梛7ĴV6q7PI'Fz3,ڋ" ~?7ACo_=dըK/y 9o>/f<?[2ʛgXyG8^* VYKI:F܁VTz(hmk7ݖ[Hi5. Kqn.SLXc z5]t^% .9F.Tj.E,Dx7d eC  oV{Je_+fq6=|YbJ)lecݍoAmĵ[(*CkWg 5=Bs]imgQ3 kXoJ"J93tQOrBUc#Wg&p7FJX'cuckϼiJS%AvªNCo3xnmtkf_x5Bzrc)[Ykݾ7\@_.u4[x߅} S[=H_ ̟J$k@l3)y:%2žDgX&Ɏǩ4pYR1M s3-sͽ^큤6HdC̤nïPC(:3~.aڇY7\o\nrhbvF߹ɍp*pCE46=0^.a]lȓ@ 1eM!6d '.GiAk\Roͷ"~U0ҚLE%lJct1*KxNQ[(^9jZmpY穿roλiw.ݺg/+8)9ʮ@hEd~b3 ߚ\xw?._EgoQw-8cӧ-QisRXJ[SrTnwwޏ51Y.:ap:wݝgWFqEqUtTZsPBOC.45'@NZTotijO{q2DH{Yꅉ_s2xprpϵ(E+\N\HCpՓ5rzz)gl[;  \y&d`(Qy6+ b'h76)*k޵vNn;aĐv86^ 65"uHݻ|Ǿnꦣzl>!ȲsJ+*#}4*3tK6b3%ev+*mC$¦s'᳀|mo|iQ?c h׉ʙ(k:%*/NTCxlKԕwp}&eG~ Jً^4=/ѽ;(f"_g$ONl ĨZN(4̅y4Z}Nl|Մ\T8+\eR>?Nru @\nrя*DGS)Y6LTE΂gL>#O,HrߦxylM=KA9I:_%Ol9( 87 P7#$ֽhPT-&U jpk]Ԙ*=,$,Y41iiUqnbks{kn}48'2Ğ9KWg$nG|c@Z_ϣjעJO6Z}FUTGZ 8Kb+F)zwpLOe7Zڒs)dIE)|}4F0Q䓢: jG/}4)UGTk/z DcݹY,Z 9(cq5=n8>nm< C"tD#DVŐ&rE?.$*Kz<vLTmM'[q8{9wBӲh羸?KgG"7\u3Gyɬ((qX!tAazc0aI$*۳RQeHM¨ **\ k^dђUymչjRshb>^nB-ڕ:P.nлU=Cըf9vJd&4"QzF؈*;yG.ѓuA}yMЪ5Ao(3Dwi2Ҭή5i%I"0Ol+J~n@{X(]J^ *~_J?qo lĚ}W}ӡh›*$YI㹵f&MNFo9mW Ȱ˄ӠW.\A/x[Eh Uoo.I^jSǬ;=#qu6+b-jԪ4\(y0_+* sXfS~ [)<;%o!5o+k'x\'[ӄ 㶢Ҍt,Hb_iU) Z 믆o)]Or` ?)3'֫.sp/X_WU}G~ҵߚJL48mRIܐ~-^9dmtn>ٷaOcVmiqez NM]&zU}eCO / MJN_x(\[+{l/F,m*ZPoj̭1+ 1h⻽ö wS :B{V36.=X[ w]9NovNӀ$F*qN}mՉ2/W^9W = },flj±}IX޻~m쟀Ļӓq%yQ7]_'@ Z mw@^%@]]@k@ 0b @= T{X w6"ߴhF~a^}f}כ㚡gp|xs^Qk.".?_~Ġ)%Pؽtk.ñ "7{;UW)1վr .됈Kȡޙݠ#ϻ0fqS.wle`S@ o^=z,~#6<}&@o%(}\twe2fSޏʄBuϿsS^2"q9.hP}2,(ɗ{5yM5=2]iKsao.R̠\K')Ƨ;{FJvtq٧ss&^!bw:st> ǟf(5'J2iP(^zX2~E>6T?gRY-6M<29\ognfƳYKVMg1ӳXwT7 $~%nJ\@ uS4IL/߰\Yvazծ)i#YG7zh-gց1idej`H,HxUaeo m4Mpx~];SQG`0MXҫS|VӨW[2 &ں7'15ۣvoAHY:4az+}-̱u@o/Vfޮ4^_iI2V:~Sg&{YzbJoDvLi\~#>(,R`A[x:$S}WJM$zoYgt;~D~V.ʓU:dNI ]Sg: <5!n?P,RALjPZ$_;@1m ќGks}k%?{okyL|Mn=&,_?S{⻡\KŬsAd+:R,Wp 9/;n?y[2e%lNs`Smqm qYi0m:p8QO.ɶn5̽oa!ӌ(rr@|dka7KÂZu]ދzܮ8>g,koMo@t"Y1yoOg>n3H,Az!uYnw>䁀:]<| SPLݜ-&C~;~ϸ4Zmks5Pfy^/21p4k~q@2iЪ {㬫_i6JiYBFS7KUHx{y cXsV[֧}k -y:E_V⡾Τ4%Ts&`aIvv'l]cgiu5` "U9=9;ϓc[<2ǻUe_7m"hZoݞUևN<WypɮK(.QX:2Z٧zìviG8ƅQhc/!\Le 6qq]leZ?}4 h/5ja =l-f약[D*3Md'ا S Z 3R6iouЛ.ЯB1 lg̾Sqt>|hi6Z ;n,ԂQHvqcF#R)@wW޵З|r|F4:j$_h*]΍548VX]ل>1e <@GsP,@2vjl)֮l5[18xS29>Xj $.ǿ_)BZ(AV[+'&9` BF?<(6z~{,IQ|{Y{w’ aTgiFcb'1CFǰ}v^}k1xIBu-}` 6$w>zkogῢb!4v»++o*oʭѥ0k4yśnnEZ}:Exmg-UzRzVaM8ئXCbP, z XrS承gGߵJKQ5#_AӘþwcq5z\* /OѠT} K&w 7OԻ-{MeEoq̽3]3 ·$TjL0zG1Z0o2S$l/ώ03Xs[$v\Q]@46iQ5h @GL輱hPr[y)*ω>^[ כOf"OV[ 0αX"b1|6.5 :-'RlIԙL-kWϱ"TI Yv΀l>Hr\@1w**]\UiJOWgO\NtnhkٜYXڍpmcpn u.9J %@9T^ ZopJj? ;6Jʀ'#@c3Yewc<,({_.HJʫnZf'Ͽ4g:dao۝A1aۣ[F}P7ezRch-c23Cy/* ۍE%[T3ɧwua^gz6]u󨏯P4p5)A`ĬCL7>Y!̾ >7g`ؘoH+> g~`^Pcr Ցp_KCy+ː(~ ' )$UGsrpZjo/_g{6ƭ)OTKb3d=nx3uz2@;ޓ {qP113m}/ZZQsxeVp#mhT)䢏v};M)_U+)e~ǻZ>?:R?sX&9^AAl>;w<_iA>?_M>3raѓ}[oF,lO'k8K2:uiDx<5˼iy' {@/FMC?1&s\4ǮO{׸>>DJ==xFveFB3⇃Q;,Qmp;*_isW][~AI۠[8sT`wJe칪1Dfb_tU?ev#wW>}zTsϾ\ZFOsKo5eoʟ _:>|]m\9')zf7,'fkwAmf.;o0i5u2>=,^ܕ/F}UywՋZ5]5Vf|FrO$_| 6| ;geh@Wy3vK-[_A[LfgZ 1i!ɀ}X)Vo.*Nkz[ʙwҕ.*]u@}3@taEIlnf.B]|^}.2]`ue&?tyzΦi~іekBmO~3|.l|@}FkE<4,ss+GsSHWXF|Q?SR_׻:30t3}8K\xiANzlS -b4ә"}O$߯I^bP\(sOw8L^E=9V1 ($v@"P=.o=$!N) hҳ%WIbb8 ζ!nRSx&+ƍ*jIש8PNIMkj;P<'{@އ 뤛ke ^$IZn 2>N|(r)J\#7jI=7+F_*!/Z=2u/'̷2&(b:/gûp[OJ-o\ٯou6M/v;dkbN*Y2Y(ƩBҩiպB|XtXgYFgR//g~uZyd*^di]UzV2C6_Sv_-թUƕ/F"tAy :E#=m'Ϩ!vhF,,<3&;ZYv:]"1SrWƕr4L/ӛ驗NN椵b飔NN:%:E=CК]j Mdjכ`4}bW$Y1<ιn뽃U4:?ɝCzXGުTf0.*P/֮&jR[PH̸ QgП ڮrҴ:8^'oO3rezu!ujWiizf8LnnZnWq}}$ˇ9SJפY|+ Ӡ@~-B9Tϖa}G-*].!wJMQo^g4ͦ|SyMT3,baHqk8o4PY M~DZ *|3a^u^ 23z]u-\)QȓءD;"ad{ß㯘U7k 5JaTOsJFr^_jzF%L%_.:fT=Db#/gG-jɗ;<5v4ÿW*{Mow_YV0yhYS}9ȭ{, @*Pz5>@n ! y| " w 3-}X '0+ 1|@o;}˨0./0c`u&=?R Ph'AO֓hE %P% Pz77 KA,9]?[k{K9Ohny.%X z]) #@yQL:+폾P[b2@ƘŲS(Hfm{PtR@}@Nu7!]cf廀323UlX0g$"l[*˴RPoXh)$ ^~>zEIi^+$;B7YMIhTԴVaF}X\ìzu_"rlX'm s `*>l=FiBa= F @ X1Ivtg;n[P9*x 8]Z/P[Ԛ^\P/ ~7y0Pb&@l%k ^Q<@jZ|oћv{q~nS7zvu~֯ڃ:k}a1{H;?r`]~`l}xz놞逰O7Nk,vOst`n^|y%E/S}SÿPꉂR#z/&3fAP͘y3tS|Mr qyRL⠇? N ֘OGޒo1n׽wē۟H!ҡ%s2Ooޕfs[ߚ WjXX*M"^Rտmi˿Em1Q' ?]AK有= Gdg3>*'Ҏ\RlF.;~Ǟ<}f>|o:i 7V  '>8w`:|Fr:Eiup+K\jӭ ;GELm'jGdׇwcKvo0i n J a@دy8!|P9R9>s]QaN|nNZ>9I_5L]98iNʈzF ^;F9NꦛcGka!Ft!wX3 Q*!΋Es{;Pz{G']p<^[?~ vP2bVNRݪ/v/h[-)6{~bD;Nw !o6iv${ųZ9a8/𘿞+I88:_ذB=ا:fk׌eQ3b5u?0-W1W~ݜ~_k]FrT} nMgVJA8ՎRhE&ؕ6K.^~,[7hִvxnlWyȭ0T9{wV!5ji;̿^}.`}SK)/`ݮJ"W\s{͑zeJ]=7Z3.Jci]bɗ4SsR|h4&"<.M˪l >0"L |\州 ]֡յ.x5x1͑7Uo<Ӛ?WaU)ݹWJw,U&>V\zTD8D9dl#;L97v\*=ک턇f$mﺰK5{8.޿y }<~kKq~J5\j\U.ɉ%'~Q|ԧdv4L*C1+$;!Gt{ =GNK0ݴÊP`A!l߶<NݡXv!4/H懘e*o Sw>G<(f+e>5F<6:OMF{Ebazln7G&ӱ0X_m+Df:^z.(}IrnI"ºѨM,`=aY/58~Y3B+7RԎ4|N?m+c?SVRf6=d(J2^Qy8x#E7S3r Ϟ{gQ :NMj'n.9[`I-_eۥ+r;4[;v.E226N>d)6JŽ<ڠi^՘$KﶼL<&Z Z$)TfTҰ,'ef]6+իe ɷ+ HxVs8GiKŴqugUȩ]@)̃cdsD˼+7n5X:F?>꺨̚Cn?Ti7b4:\O3C{)!oVڱ\WFn\$`O)8mN5(εgPvz(y; .ւ9U'WUK}+yNSߴW+B?MmΗ ݥ{g4J>H[t (KOTkԑ^K AS怤Jty=?OV᱗qê1[T^lkYwR zU}]-&7n3̒ͩOH!j__'h^B&TyH R-̨ƥkVᓉ_4K?pX!!r8fݙIfgIS1/0m &Xv,Σ*z؅WL\Hŧ3O+Ku]^&yN޵+5fԤ"( '/gY1'U{<6%߀*Fr7 ʿRghk_ruoP1P'p?&$2@ r/qUX#HzW-uBX#Kl#a 1BdaAvrӊ>+LޅaZuWQBaU".@] 1UH\-R~ Pl9u*V|+ {l9P&6.фJg&>MYїW[^a'B+(u Uyzx;}n{E5@d!݃-x5{ c-ȡdfb >&z f~f?GuDl#}ap]=+m`M W+?<,]EVYLz]a P^m+!}/iXN&%ӏ5`dcy{ ,cOH4 w%8̇i^ e%+sI%I }]F/uCWF3{ye\o;a0q>󾸫%^]D[bز(4 YXYł{蠿f yY4 ;z+;(WXyyu_⋩r^Y5+ή$K}捏OvY>*6Yo%;,La-*6x:Sq;ϓJU:Pj0Q9`^Ȗխ7޻VpJs*fv_-h%ˤ/Kؤݙ, 3/9ZnLiKdhrRX;)#mO X:{pI%]WަҞҷ;ەԿY9EP_;6rJFVՁe7gt5ngOX=T$93;O>cRrzxhkMrȓA%bSrGy-e2W"Y=t7NlvܼlҁZ.ܼپL?ITt޽Գ*#B2+s2[s"zʫ\ iݯrXe>lz h6h6-r&${^GC xNܲ~m}&t/Y^7?Oov5[gbK$w_"{څLTFwݎ*zkwlFV]FSqʡ-7yr\O%mJcא>ǐZ !,49\/|7$1zXe6_  bHAlepև?af ![4UHOj@mikiߥޝ,K'0D\5Sϕrh\Rq1})ye X]OQg}P=w'$ExN 1Jf1ic +1n1jz\,nn& V~9#$vmϯY_p}oM_@+O; :_IF+ |NSm}oδ֧U]4=gDSDڐ<@z>9~ϟ2=+hKqm?Mר,:,Z0[,ӳ#pMhY{LolŪN:J}|ƞ59los )ѺwΤuXfVm`U vLj^G);D7)zxF7ImM@]\`˽,ǥoo e^x5Q+DwaeOZ4+ '63CWkN:5op|ڽmvɂd飦eW+#v-+$>uK<8i+}UHd<p[b JvX?a>{3pG.yғ7oB%FvMZdZ=Rⲯ:ʾBU[Zkˢ,;::xƹ?7¦dk߿~kX;Rɬ$5 j`\l4"}AXO3,|_<'~zOtgI _ɷ}jo <4T(={mܽ XYrZ4;Y?d_iۜb \p[c [EZuyTMוQ>͡s a4Oe{͝s,Jƕy$f΍a/S|k W^I}$M/Kk^Ʋ5qJvֵz˶8`3tkNdU'6?qowde,* r_G탆?EgcdTZ6)Jtw}}-sGo\*k7q׆9}ZLB54l}QB'J|G&LnXM6`ezB蕻?6K:ԧ%/ػG4SVe,=ifakUmĽNU(&A}*FN+/ڹ4C tdrġ3W*kbʸEل[fQ"ܶ,(㾔ro~2h^ k1"zr:|]ZޖE J_45=% fJ[A|۶iHP|]lIҳ-ԁin͗]7KsuXh%f .R%dzfGjl(r~F\%%<*fǝ(=XXn/yܸd_ZnVUWk/ NVnJ\ʰadq_:r]4.cS"oAv!"2wsbuʎ+tpo8Մvhn4o)w!>~{w7ң)ze{ٔSa Sj_[9p3/[U|5ˤ6eލ4_KjSӧsbJ#My"sd>Mq::?HLKc캓0ԣwQ&Oւs9w,#,ZL/|S6tkу[ϏT֒})(Q,dKJƑ0\9EHSNO0'3<`1t&9ja^QO1uyV`` ,'>;(@_4@@/z4CH;jO: #ԫ7+{md7+5f+S~Tw A3GI vw8| Ɔ*PthXzAMU^bO$%8JWt0-=-Zf|̿?xPeaBy-^;uldo/KV6)u`b`LM>BEpQZ ΕDe`"օ,VJCnid#꬗ͤ|XW c3A`}k+Q!` 0gN:!^??HތnNSmfV@ĻeDzYz&eHTn!~{K|^/\3XlP*;xf<| \1OQiy_}ҟsd1^dT[1|hPԟR|kk !}ހ6@;11`eY|[_D{؀XlU4@1~PmRqŒNy%G_yR\TOv} a3]ݗjxGo'%A-JSܞJ&T\bT$t+/$$y>Ro7 / #6nYby'6hbv^HᕺȹtSG}gZ$VsA4,?3\Ȃt(v7zvq͕pw:^^:=0v=wBYW;9l߷Dw>mCf7L/.W*ub 6!0-ú kPNA:'H4imɹM`;lL'ׁP>23.7vp+V0kˊ_#B3U%ڏcv<ܶPꋓA~p9 B!;1dOJ(ys#lO͏{}zK`]Q:ܰ;nzܺ%t?=ogY~R:"nNg,8U߯ц3^ ר%'~rQW8 ~8g wܭֱ=đp]>5deVzhG9z4ycfц 8⡖%6#AITӄIzwaj .Wq#2ؒw<Ȼ>]6]V0GkdNΟf気mYXdb6J78Q-\Q.=~=)`@HsKT>g?¾5] t<2˺ Qocl^u}k{2DK%Z N>|x̰5 \xc'!ew˻lƩ:WE/ t7[ =i!TȍڬH_5IT[ؑGui-ڬ],uYMݛ!z{{ 䮗!_ʤv\A'%M)tHaڔ)VV>Ί=מyV0u {sM2o[_%Ug+QCCVҽQ|΍1#ELK;վv)!4mJw,k嗒:itvl_ׅaTLZMIVFԢW1gQy8s~2a\95YNḽx7NfTc}9voigXhPq ZZW7+6*X_ɘ̺3'::34]9w{ļmYu˸|-C*޷Vͅqa Ŝ7R+.* }z*/ƻuz9LJٯsCdd2{GiZ <{ 35Yx7~Zu"B\ YЏEt~lxP, 8uR3\㐙OF`Pcѷ}Mm g[ϵknCMAݷs\ڸ+ʕWi%*U/d>_\?Y&f0[o{ gCNa0<׎NPb#ɟLO8+[LZ貔^̊z95Y47Y!y:>fWSjYS:g);}H|6H 9 qk <[_6v\0 `U֌.@- hH|h@ Vd=dYd4 @MxȄALd8MZe1ѥ¿~c  TRQ6hVL<|$Ex3(u4U䣼!\ _a ?}@"h O"V1_FF]sv:pOslg "ފ*2@O>@SF'f_' PPCR 罳3[BTϿ >Z[V@xWnOӱp+NbTj[* 0@(fW`D&[a v @*<1E4o[2,=$|.Kr:%(5Iۀ- /v oi i`_pvlMJ`YnM)v93C CeZWv_MEגNټ_ÿ endstream endobj 29 0 obj <>stream pSJ[ӃL͓Fb_1_LCf-֖-+!lNBL_yOk}Fs&}:t<-u'I}E'4{?/<)~cH%SȞi]-ˀDx'۫8_i:9<{,eW,,]Cv[1rBrXtaO˶_y/n$Əkﴨ*{'bwhXuꓝgyu{9LлpзMy]恻`MɹZڃ#h~cAm)r/vUrr[5@1HU.Hw>U5b}_뾵]|>Qt`4ȒXK7lj} ummpgp_~Np7s1^A ۄM5cCյ^.ԫȞp2./dzA3.oz}JHsn۽"{XV\-Ԭtqz:."V|5(D56~\{ hݿOC=b[+Ǚlh:,ڧ=7o+6~>{5WY++%-q1߻n3ߜ q9L^g7\o!Psc2:pOlpq>NXLvzyu(~[z/M$ɽC'+-rzvXe<3x3r*g3a2#~$W5w˫,V/#&I+wp{fC]QڻǬGXa/v?o1{71ju~;ioGr{ [v0nM?˿ hQRUaR&Wr/p7;.ݭ{t+*yR%vƤ䴝ls&k3F蝣aP/xt2@.~3+uHj R `8j-[5 m{޾X2pF59YXvvv4lJ+9cL Wc60F]毽~[A{Y)b[>Sk/u. B+4Yb;%<9t1>^!hIcdvQi'WE:FTSh s[`A|ݬOytĚ4͢ }C\sUx,yXU@*Y/"S]*AsLG8/]ee7]6-x=7piq-m1se2|0)N{X=Ǵ ӹAӿӣ' JkqQ]E,Cھn W\~4 Ӟ3~k8=4^1 W],t_S;CjwU;T~kʖyoh^G H }-8$;W/Zڠפcݬ B(S'6h,9#ckOwss+֢8Q?F!Bԗ&\Z̏ d/1 qf zö+,Mi9f6SFV5q 2=⩃V %;Z˵{5s8d,XbkL}.g&DRμ6xVrRS)\gtӈlk֬_Yz{PvYKMeR?/>2tڥnD{ļz4NM Ów%5 9&b?c5hXփN~Nld39~V I:bQFJt+~3o攧]_aRvBbVBĻۖ}X0}*-0d/ q x.-4.ǹZu˚a`zmk\ogqU3ede~5J'KxAU4>)_؀_^5wa/=Y› Zg#Ѣ)ĝAiKU y6 {Zu(֧JLe)mD1(,88KT\>pNP*ms/K."KL/{ ~}9s"rZ9(z2VRΛ͙4V˞*.VnZ[|[O`/"iB7YvC!.?.+9r"Y%n zs}>2Y]b# OSj#iS]\^[I-pQQ0}|ዒ RgLPINK@NݤtPiOISYś3nɯe Fտ0N ^c"yF Zڭ29?WR],r>.7vXYn3\KͣR R4x)|cRQ*S0%Av(Fx[@F@z?&{Kdt+N!ZeNtJU ٧݃H# Tǘ) `R]qZOuMKH|/ !3) bRBxB\_^XV@ŐDjsRRu[IzY_u7NJy!qk_;oU'v53V q^ToJp';v`߭)@7~oZ,;إg ~HsqHnb> A6?!;` D73_|jcbv&gHb5PꘆR<2z@ר PJ"O\u D i Cw8= 1%&K,vL.yv:ΰ-ll6 ~^Ă] ps%Ʀ$!f/hY) zc&7w9MO3G5aTֿ;6 .< :?Gk+`TeW?\s襖b)oe/Clw=ScԾ@_h~"(2\d*@M@T_& `p#ЫO q?v<&ϵ{o8^z0qyO0tz 47V(A_y.nnuQ>\bKxOf64HǩU{]Iz,nQ43u!_ yx`SݽRi~>|(dAE;yԛ];#nv Pj4ח,TR^EvއHҳ1U?6; ܅ޚ\'ayMQns= TɼO'ʍAf21;}T X?z r(;LҫJ{u~puRvŋ1sR3xo'ypjttwG]<vZ&vY޲QD '}NR[VeaFM Թ3=ı|X6s=Yl~)YP)z.>~w'X'@f8 A@goB\|oJV .y_[0׽6;bt3 N'{<艳*p6B%!f|r$5)z/c_}FzH edC4VaTw$ Xauy@2wW^ܥȕʢ; tX9ksy{Vz]$5X}rxN$V{(?ZRJnowsp C|+5Wj1}k~Q%h, mM)1_>_>p ? |n׻1Mz$;6lg֪8X2A6 ;ܹ|[P^XY#ttޝeL9X :F<ϼJ )! 6Cr5X%yTY$]})+5pbo2&kD~TB^dʝ8u_,tLU??16T 5I0NU39&HN lZPqDѦI{DQnG'V;+ϻ?cY19w`^\k<3]q*Sz{/6mI9nFnQS5HI K;Y'#&f;o{_nuގfϣ+5W*.GlcΘ3VzGs~m]{Uu_ͷ̔)ݙA8hni 6d#fkyѺa^[+fw--$ [b0ߟCf?m1\-X]z6/9;';_t׫Ljoc*ֺ֒Xk J^=F)ӶV^2CU7M1^4ͼz`xnݿxw[99uҙD:(ANZnL_ &!FVQyrC^䶌$$_Ƭ)wrK"/YQoJ\Ca+_{ڷA fڮ˴9φٙ!2Y¨=7tc>QpٶW3Ћ Xe\2ǪHSG0U0VRr& *jt,K%B_)7+ڸy pݎˣg| N:-]Զ̔|;cc [hΛ ܅P3BmӮM& vLyՎ\3R W]/Ӽv}l/͂7nmyWկf{mb좐jHFg`aޑvhYq_GYm(%P^Ѣ^ߖ3ݖ*5.#*UWʵ saþFEboάG{/dMZ5 #Zs#2SC{^Ni>m +o[ d?ҺVƗj%+!],6e/`ݮHm:-#;Qi ZǜωUOE5,fm{2ᘫOxJ)pVѝrs?ޗV糄]TIY$Ƹ}V{f6_Xm$ofup(S?= }ي;tZjYt^}] [eZ2Je[̓R8B9|\oJ2/W9[VCg*yy&3Q 6w!q\ Kd;K}49GŻ܆*i?De1^6ɾ[ME:w|;/*?}чebOVnɘ^ =wʝRqZ~5dtTOJʔ[~^a`1Y!ua^ǢTFF1fB3'pY*fre2u}r?JcCc?n4Ő!NۂJS~S>>0w(^ɷX,3l<>_6BSǟuM(_׵!kTkTtc˝π͎彖qszJRk>sȐM֏a):} 2³i$>p|ʼnioTo br{,l:Nfřp4[Ҧm¥ȈeHa6 Kxx+EŀX!> Aăb(Vé5Jb G pX~gߌY?4㏪M ?8ğF)!Lif}V.TG'IWӮ \*4К $Ki9~JCn*?gP*n5kJ/by9D C55ׇ0g'a@70?lO.JxZ-E_K@+ lua pc I!k#BXc::biFXNyoQrO/r(ЅRW(Kl+XT"x%odD;g`y{93 !-CH>M4H+DDboj6_i'Gn{\/C'2LQ?f3Q]Ұz.:y { '@ 2@lC}, lٲޞ;U#L +?jS|3dmQ튃p'!oս' v5({  `aX?LX%^\~y[e(HN˺2>;iwhO*{i6nnW5\4;{` lIL|̿Kʼn pV>AQ D0~M۷TNOEb{g VC.w+uo+MܰEc~uJeo9ؠh(sV2xy7<[ꇯ;+o/MuDMbJq@ɁL'0nwӨ*plB1_=WqlɺJ08;gyA[ y9inq W]_Uz8TfmtN;c<˓No vӋֶ|MzϠzG>zJ' ^ k-f;>ڻvk:6#Gךj 0kQV ,Dɶ0>R/HPI @ O,͋~(} \;:x<!ӥcv~U,lFu]G1fZ{5ˏFˏm±.8א434˜#q-mNH~= ()ǾsCBƨpmWRJ/PzfV5z6c}sZ;(Zw?> *`߃҉"҈tbbߠZkO}#nČf̑IZ a7 BPf%7A{atX(NP4y7zڮ!k%8!.޼J8TK򷱑Br ElM[5_ ^;;?uZ(Wˋ>n.o 5G"҈97A;ogV$\Xo6Aά\(P*'P~t=iZ܎@z\zi#w2x6 &x/n6p5Ve hY1s[*#rRPjg_nDn^Guq9=躻9.k7~@xMn^e~R",!]Q:nwo!Sq7θzTSzn@:(>OEG\_ATͶﶦC Ύޔ*?z9Cb\Ͻ ɲЇNƋ-<գM3!9_-ӬYRWD̨)쉭@ $Pڷ9h ڱ|Q`__kYmÕtݶTN˟[3էBs_=^𔼧]\k K9G+NyW\nt2Wt4b{W+vsC۱<|.\ ;S >V'&Ϧ-!h3IH8ɯ!)|@.OTqߥ-} mV\64+. V?P}>zr[oo=xyH8nq6JAjve@5 dPG/wlK4cJ.KV=C+h̞:0̪窡vcZ],PEϺQSp|\v:L1#Qm4[0؝8r=Gws(~U&}gVN Yq֏aaP;&ڨQZl `Z!~ &|Otav'ˍP2-o;u|q*vxSYaD~Է7)i1+8UNY^.l9zuπ7 <\m Ep6]a1f4EƁ4g䕃㐹/,xyҫ4mHXc䬥i1 {#*#5bu[b|MOǦ{zHűeb^'uϔcos^h` iy 'krt; -:sv+{I (r֛6jn31`"?lU`|F=^ dzDړMa1F$b0,P3Ȏn\Nlh}HJ+'m5\mO;O5k} V8=k+ĩP=?|Uܲfm~&B(,dI$ >c&Ҍf#hL@i..^+#At5I7T|_yvlE [{fsX(s/94wH/S|/i1?[SߎKI+-lgq|VU7zVj6<UBtTzlQU;JBY\, YB f mڟ[Tt+RSU|t@[@A=Z|S1l:vxlV/~c3 yBrrFY>*/_wEQѳ:FP<T^Oa)sA.( BQ)NCHYxTH*SLKbf> 5x\GiBm Id_O|ߐԛ{~K%`+ÔOl:Eq8SN(~A櫝}miϚ.4(,U0R)[_\wܽq,XM*r`,HO+E.?+ ~@辷O0xen,iTHw%Hʽ΢zK$?6,y^IVCgJSIPDGG3ŊSRCv E*-lN6s2EC)Y_8xD;sV^մsiWJ[Txcklm<S\[VMل YZ\?8a?`6FOY\=[m@XjWp_s޻W\G8G'|qAK`˗OM4]4 SndV lq8_4} S< Dž#6.|b_-kDMD(f@R}d= %=†X`5^KȻapԪQ\CsTi5]/q~J+|işunA@Ͳ!\|a^m`K:S2w޸7~.۲S|m[Һ9C[GW}5X%/!xo)hͼ)Xe%Ο0. s4D<[TAzX"]ٖK n5w~&2//d[_{ե@/[\j,9ޚ8X1u8[,/h^E HRv4C}+{W695`z/iO x#gg%1%wttgD]{k]֮VPxb_\^u 8Ԙv*Fdqv˖!ݛ3˭[ FOzi1Z5^z{nko%Ђzu M,.˦TYNһ} 4k7Ih@]lo3vAJ˅ߦ9҉|_WOC%G,%8ë{V7wj_Ԫ;dpV7'w2d1O"c5;QeGژ^J zTUY:P.WCCր'qYO?x|ip;ݸ Gu[uWi˯io]pxؕ0g߮n-BsTT:,ZV>Wt_o3!e &S_~S) I?u`z8fs_*SuT6vM.dž!aBzQ3.Ney*Is`j&!xOGA?6mҦ^Js}aׄFK#e9;ѮӜo@7b>KޏFE-D9kBVpf(LfSG(m>d'!gS #tL2OIo_d)lKaS6hn[C"k&kBș3ӍwIu84YCzɞh Ժ>ǂ{8Hr..Ǣr·+Vp|.uY0wtOϸWFK^?wz:> kg4_.&:e[;2Wyv ?ؠm ஐ\wCg9~ʞZ=g|WE,up y>ZAv0j7Q_G>~ 3/Jpg6‹eިl 3ҁ5մ|.BIrY<Wfq=5J#,Fw;?E:hD4e*hPH'|%-&{ǎX,rTZMΆCBw 9RA\n r{@Nae}rGanvz育= `!=&~*@*#5٭?/ʏp7g'S>;+3XXh{ˆ5d+{+dDx)bDT`m?9~f/b1;:CRWcBSVYޡ*Ss&%T!Z!Z玐 -k(y5{P{KzZ9pINe3a*ԗFNsŗ+ r+I{vٴ,lR.6=.{`GTO76>xb;_Kca3H:H;!xן<~r5`[;qIJDJjXi0wlQ71ݗt]h0UJ8]R?Aշֽp]GMa/>{-N"lOAᜟEڥkp%*jaf+MZ·16JEjkp5p3O>'4'dDj4VaYyC م-\ X!DʏN@AL_(u6YOt9&"$ҀfӮ2YvZwF;FDOvͤi@CZ}`y_ڹglCXV{#OvLQs1OD:5VmQ할 y\s3Bw_i_ELfـdQõ^vg im֪] QܖCEʔJfOJ;]P֎d9QŒcddʜ.' ;`8A_hx;[58oTn_'ILҠJ}(&Ͷgq żdk^\ ڋaI 䗅}?^+ۛ)ٕ?Y}988qvQUo664Urb^j Zцv2O@\.-W,f<'}5?(\(!QT5#t.]r=?_}]3_ ͐ƒ'CN?pK]|0Bf͠]FhD^ˋwHM(D7US ޽2@ >AzD"Զ) Kd3]eUN'p^+Snv oR,Tx<9,EùqYe'nu ){ ?dǕj9Vu9 1$:(Q$_mQH#kf}3zɅ)_:+#-f"2[K)tJ^iF qUJyd՟@>]-vQ,Q:(<(EClb)-]S(bSnZqNqfQv6)-%I_:H:Ldrܧ68=߂(Vg(ziw?tlLK; OSi'"]Ha)v "O^/6V$I1I|_[;EUKC4gُC}+/N_hE,;&K.9Hy7l>.G1ߍRBʪIHb)(%Vx}vx3o?~Ƈk' /?!Ke(c 4m>4^:}Djt'Q]woߦ//L)*{3E["J]Q25F~ *k|B?;Fs=VrE#zboӧߟ10Vԋ4HJݮ7;\%z\V`(JbijMdckOp?ynz >ιy?ӯxKGq.Cq|3TS'WTP.?/ [>o!fU8_,m⼬lx>J~|'x*qy;Gbd>fp{YvIh_ٗuˎrm B ~ÖX7S{^|ЍJVy wz7'/HN/!"S>G-_b3/\*e>M(,ZeaZƹޣZ/\39lNqzAyY:fc2Me\7K>?bFj0Yo|i77?ζv>V fcЯ,X#:tCZ4ܘ`RW,rp|KY{/?IXAl {CzXwf涚JUp= {C|uM0Ӟcl8_ yb-&*$3JtKܠIY=>ƪ"Cxmi2 ?cK\WA؝,Ẁۢ_MصZt(τ>蹸k,bG}bǍtI@elb %=t?R8" >|6|bMA~9i>ZA>#krdm旸 O>[!m*t#cRGG=\t!Ԩn.l"em 5V6-Q/SćBLPfz3s2_dbnIMPn3Iyfl2ֿ P,^1r\4]wx6) ԪEwu%uD-CY^QvygCx IN8MǯN,g3>sj]r.4F/7 t/G8R0 .i}Y{EV/%)d.51 ?mڝԮɢWqgҖUXڟ+4o3_\1a{}ʗ n!ܺH޳ |(v[Lqmjt;7===驃wh%xֻ}2,Ze9t f:q<>M`Eȏ2&>ƉsP.^n4Uǧ[q1=go%qKX]ФֿuFq5KbT;dux Z# IE]TFePuPrрKAi1?۟FUuw cEw/EnvDI, Q4/`',;S$/d*p}0s}`ý PC#XV97{F۝Ӯkgsa͈:4D~|a[C0R ]9Gt[7&}v wE>흞Q:Dspl&Æp2rS)zY?briaO幞 tY$OrA{n6-%23ڬ{V٦7&ڏn jatݴ7̨ Ozc=UZ ?TyjםQ_IbۍmdRTw*}c ڴ߉J}Om}>[LZ抯m~QӹQbrE3G=׍v-LFPY,lz4V\{Q9_zzmXg,14ؚ䰢ԆFV$gɬG-Al}fSLJAԌ<6\ \A2J/a՞'rxgDɬJ)8QB79V3bV.DqCkX8%8W2#{_ED>dpz^~!a=i,l7=vtþ?d{C\;˔%ۧ%e2 mzC}g(BV;^?w/a#wETqav\.ө?\oAqi=6a}W;Rߟ' NlvK^{Cij% z_  _kˆ8ȬB4=cƵh:ڤp nyzYs-2 u;/Y&DʥMwc;O oY ?X\rv /wkd 8w|JT>l!ͬ-y,9yO,C;~ن}򥻐JEi;7PX⾚ qQ>=܍JsݚUKnjpX< r;Px]p []2OJNtkiIhyd.*e9ĮdӰhjqlz!6Jܻ+Vqo5eT8nnRk-ƣ. :KYkޅ@]lC߳R (UUE۔.w d*M Ա00XA#f2 7;sS;}g:L@+(+iQPK RgFQ(K.ҫW1Wi]e+HyԹbsֽ0SRl5Fޡs:n[JO:쪢v,Ԥ+u7 ^<;'_f;fn`Ub:, ;B4-gH#T3<sn™_'){{tzZ+kyE#p%}]L?Gཛpb8O*ew,RQi)[a4{M:63VvHK ZyG$C{扣t{f붨i_a u<^2(t MQ⑵&X}cԤo0:E>MIdc"ȁڼuj'gsp ro+eDIۼbWNGx-QUBZpU_y! ·?"+,1V7?2iy]$t.&Pl<"D%F'+BVᘬ)ɗzSKZ<']{@%Yg쾘N,<")q\5Ɯo+~ؓ m2eˇ:zm0r+:Y,tnQ)j$dckĩ Upmc miN;;gp\*(Æ]xl֞e mBrxd_I1ы=w0h|̓[a,g:]`{)XHH0_?r{$Cx_X$_젿Bg-9rm_KYڵF}h,Z;%I{Nc5ٚu2we;=b6"e_OEU΂KBcXiG|x0.*S"Ah%^z覌 nNր2o:yƫȃii!. AyGX9lwShPlZ/pR=Hmc}[r|- ٭X]ȿ|wy@<,N{sAS_tpgFݾvmeKp7dDoZ{f֨ 4K|Ga?ܪ0[!n֗.Zlw&RA*[p9{9[ҝVdg J _Ӗu4@44Z;Pي؇oM1>ϡ0g_lR'{=*4ˉw̔C|'D|EiGe{ok﷒.u6qh+0,+=_"DѸӎ"0b(~eEȼCO>FQ~7TevN?WH 1HnNZiqcd!un#̀z%1 !SLBcɉ+r(bd)F8-]aڔޭx}f Xa"z8Tx3Fܮs%2nЋv1.WA1C ]L:۫sQ9o1:>Vo}S NAmo6nni"z߆=?Eüq(rt^JǰGr碬ҏ6FSkwF4lrny5/_CWC3stOSt::S:ѧqy%zc{1zv}G qǛoxpښVMݷ *_ou=k [gOӴ3[v;`ү⮫bf.EN7PR{^Φϩɵ%3uO1xKAxoGw^Ըu`15ewq95v(f2zX{=|%0Nn0; _3XM27oe)C#}B3ڿP/Oxd%hOᏭ g!nWa^F9{gaCTnusT YnףAzTxūJ/yiYɠp-lyml#ӛX'vN()hf c5Zjw7sO2w8[%ONf 7^w%չ+VK] ZjnnRfcӀ~sS|'O'8q";mQeV4,$̝^`4^џ%PF >vHqjW bu\T+us`д0dxon3櫔7ns^sR7dmXGA՝}\dMޒ{.ٔzDD+t^HħBM0)?0Z 842j2WO{Ñgi`,AMlsݥ@y#E@uG OE^T-;k q ?x8{?-yכ^p֐)-w[jQ;DEgv#Eak`8=,z$=m7< E\-8B;c:YvYص<{eҜq~e">AR7dZ{C+Y؀.\O3ye6e=5$mG6Zj:$*=\i&+L@|q{"CgX[2fEƭ*YCr`ذս3Vm-8& sN[*ۦ&4ڒ=KYM=y={ǖM m|̊  B4^$/ o2j1BZ*)x+;ۑ3&S1ֽ.B}.yIVF|;[H2`§t%97EDj́yPLA0G wbg\؟M6YK^j P' sWӜo/ӯ1GD0*QI'\'AfNޛ/"*8,:%arдe:(֪x/VVfcκTm6(dsUW :6ec :ki]cL?:R]W ϢgmCt:T'n:D㦍ԏ V?X"]r,j#]SYٽ*\tqRt諱2( ql=ڃH4>%<+*K2XeZ m&!&P\/u=uC'9``wxnU]E`?%v^(:jg0OiyظI6Q#!ӕ2 cߨ ==jNnwnC>0HUী045k@( UH&UHNʴUs, \YLӇ6BRGN'u.tɭ]|qiAuJ=/3f=mUFnm'5nJZJDoyy]fPV䔧U[r\Z__%JcJ.:xbAx* @H j휋j"ww4 n+X5`+16jT{^orܝK.[QFb ,,TC4,L~% T\.9*Xr /1K=l/LƵ/]rmbj jIjBǃEӡZ3~u9V߫RstBdfB/6H|#' *qNzF8UFSIW+ɭ3 nԡJN{0Q!(u*j!mᶎϲL<ѝ|ebZ [)]mp+@68Ov1Fʹ# `QCq*> pп<կ~BWftoI:HZ:=04 V9-3c7ϘNVfZ 27qV#/b@HvC 8Hd;@L 2x@3Fqo%BP2L?BW WSV^9MH" e5!ۀ]@zJ=?2ڀtjj'.τ @=@C3g:aȎ7_"m=vkj2tU5!QW$E::ch}f c@qTd1.g@hhJţg0X7YB,U0'̙E&TM b*BS$Y( rI։w\ `+/?}._}ZK/ XB_׊,yq$;(bjOyCf߫\`)Onj^fhEV"kb >ٝ8Qė1(#l)e*WphĿ&q y+b_?շZ쏾ѺFLe?뇤Dԙ(X6roYڳc܆-_lGGxNi=*>5fX5Cܷ_%6r.su<`6O~tz Sf[ ݗ=n7O<#iaWi>,$}"?uTtB :33ٛצiA:5CZv;jZzU5-|n}ϑiS@ ۝*_6X^K\vNCI'3eErARB z;gǙU1Ⱥfʣ.-{N)V]MNP@ `5n9T ]tiMN^.zNWXF>]٦b7)[HOB'zF>\yu:Z.2}W9Tw;%eZK&2 u#mbe4GcL)25xȥҔ rNe&^؈аVI%D#0U`d!]r pyufNj)2 ܷes00Im+PM (r oFM.;DuJƾA5Zlm-vwMZ&ٙmr?j;ؙ̓[.Fl'5!瘧%9΂ց\;TsUE/dr>#Zj7xߤS|sLB:g[DB-ݜ VJu\V>왭2Xdقcm%ͨ\SVܴJoUKGdXnm["~'%B7|2ZM0{Л/t7m5;5grbڃxtx]aڜX2 - 7[m{I.M>?ၰ< 4>e"<3jܩX= *Ubdr @ z/ԥ9ڒe~fWj$'a0;k3dL[pO]EQ HiaCxtV@!2 Nbˤ1x,א4'f)EO%5~5˴#~&pс7w>ӺNZG9vSNWْm0ЧxD#iP&=)F bwcEo AP4AEsL|ÂRt072Օ&5C lbN[7C.*ZR'd ÃyZ AÇ@F>5~<&>e\YXuI}H|oh.{Xݷ'(;Q4.89:e9imQ8cH*c&“{ 30dl!Ebgt+ sFhy<Ѳ;KecPm>>_,.y4gbXno۸_2Mx"^yL*WWxTo9kZ'^4  ϐ5zzµƚFq9"Nz$pСpw8(oFPb|H9KZ@#9vʖ~1 l|uo!IN>q66)lQ2#ZO:ԬPGOr |W)&6E}1^ FnUZ:ɕwcr/\9M nT̙TT[ 곓a8i6՟D|^n02J?Y0K~-ǚW5&(%eڪS(UѥYi.EYɖj[-m^KI;f@If_b\#  ꄄjqv؉u?!y7Wqa 5KCn#QilyMFv|^K]h܋ǁ*ZԾR%hVhTr|p.~TA'R!7 g<yp^_s ڸܞte0)[;.{&hڸ1|;E*:uʍz>F[1}?61FAt6]djy39qe2 ]f7I:#-_$Ygnq&IY #у#F jpxs8߭TlHX=2,>b1|ȥ+QIsP'e^\WO+@h* P:{1.@Y s=hPN}'dé4^ʏy;7i_ lXK=N~ש3)YNQ *8JgqɠYqibV&o2+xXJƞ`UoeH NtexZEp|Wi?tO:4`12WJ`-{=rR&bܟӔC1^^'-{wF<c& @  -EdӉS;B_,Ը}*^I*W ]:ԮT7d޶! @t}@ ½H8XWT2E@4ZPDy){(1-YNTiߥ2QyEd׳ qx-~u*ww]@62~_zyu4-U@=0Y 8 u#9tVɤ`Id6}!cAWN ?RP&~YF6F.;wKj[C{г\z Xi,>.0|EkF#BƟQĥkEİ |o%~+ eU7 ]v#@m"fxӊ =+'6H9Ca40B#~$eLm 11 ?J]vϧxSAba/e}8W Ӯ_Oup05xP G1m{:\lVWld/R9GF<{h|[3sBZtEڕSw?#aZ,Yto 8L[}r.\{[h= ~g`!+pA=yX Gd޷ٙ?ڞMB: zD*-7cʲvۮlnQqqxb ?G/wϝڽgmka+ޫns^y(?}p=].vΎJ5J~T"ze"zҵ%J+EjZ{.ƌ2H2*' cUaw6+nmmZʏʃo#ܦ>$ :Av_bŕ %łVT▞r{Z?m,Ǐ^e d=,MyԬrF\V~`2XgqZ^z:u }sqa]<맕j2]2j:\3a\yYؼ#5ܣv7OJgMWjd|΄z ~c0͢[w2>zZ( 2Gh9t SN*Άՠ{fi G[*FҌ,tN}y72M|V5m$[Ej*s_$d9uzMB T{\esHE pص3SUfOr"Ut;dڃ:jnk7W"T\I^aS^. 3i wI <ߥr/|q#Vuvwk鰱Fn~C2Y܍F0t&0pf6G7&)# 2Nwx>ٱe4R8Z^$V<38H]0&iv"atO+UyqY̳n3tvW>tKlSQw/T8Ni'i}*}̺<4یꊊ߳qi"G j>vI>*|zVͰ+E(]e31Yy!ӵmԥ*'Nz*FJb֙ }(/6՘wWr[p}F-Z!'gӪwHs1w~fcFdeTA/;w\RmoH–6&Z4->M˵2q9΋=6_WLTsQ#lUtsh aTz[#_. _Azb̞z\X]_i/Wٮ&ݩ>FΙ,eG$X16m]m-}0u}4, h7`pkZVQl^ܱꕑ}KvՈo쿘><# *U5aRxV 0>U blW k N#覠AWt>z0,kPȣhXTI&%\s!Z+rgޗs={ڕ[^^wݽRwoOVӥH}6UY>t` i( -,Brg2gFEWL7VYFr\_6|(i&,S\q?`Z.Nr,_;md$]@F}鸻/Fƭ߹Ϣ#2KɆ9WBH$OtT[uԆ\<*1خ= 8WoL% VOrYVvh2}#LEs$f,Cy1A 9{ wܔ]LN]NEu| j&+pr=A7e_)Jp3e$b-HC#(ϱ&5K&v2L雬 New'ppcp>nݢ>Yv?=$"PKC]gTEIű8wdk>]Lʠ+>꠾,CwZ0Rb`T6PlG;wW|+pڋSl=,p48]aRXkܵuт=*آ,svZ[隄r86ޥ4o6 ! l Q%r8pg@2 ׍ 2(1 ]70w8Mڜ:榹S'SH=JoZ=rSq"Q}Kw/qpU`P@V2WKwBL1L)]L/~`%~25ހL416`c׏"FM#w+1/e * "/7"fSiy7 #uW;$_}׫F"GgwMw[v;J?Lm﹨LO-X!C-s_H#|?*m_ҬƢ]l~ty3碴?VMQ@̼[}֯fɹb~upyZ3sONto ɣcvT}qX1P7kh=ze?I xVpybz}['AmX->{%(n\"ɋݙPNiz=@Z5y}+Os_V+6R* p#C>XP[kA^Ni VX/{6Ou fh5y/+o>#w8\J.uzr+$4ޡ{[,n=8W~J:̰_xmXh5 _BFM\C᝷VVjfn'*kVC8ۀX'[RYL|%;u *; 8q?W"NͺIukk@7bbc Ҡ7Z`;Y#;t0+k"0F_\9;dVsWܽymrdH؝ś4yyrϤCH\Y_}qJ}{r[gϡӻǢ&=Gx`~k?UBt'0;ۄQtNlFM2}Yߎ־[F j\S(۱X/ avoϕn&[}2LôhĽeLv//xU tM=vw y;gTg{6S̖]ŔEw3ui]'zG?OVV~/HRb x@UL/S0Б8U&᩶6_BW ?::NLvܟ}K^}1Ն[5W/<3J \HK(Y˂Ӑv2[4n ؚOw6Zf)aGilLwGq{ZqS*H}J'6Iu*_ӱZs 7 v]=ʬthOѽQ%7Qw;AN#cVUNޒVpneӎ9f_c31W}6rZr޽*ɟ|4EZ;6v1JF?̧ RƦ1杰i"Z9Ww!2v/g$d̈́46S0fM*0JIheUFKw4D9'ns~<:Ս.qiȭ&[u6p6~8>u_Fh~ZExpটb#B 1G`$ߥ;8&O]`tQ2ΥPq%@i?-{]w~4>۰\-v"&3뿙cu3G=dB}2^t߷nɻYU yZ{XEȫ1GCϧ8Y1KH0S&xʼ7j<+nCT\e;=9SÜDdX[`D=lNEuJΕ>up{!Nzפ8MJsHQ2"4Ax /<~? (^,G6s:#:}.#Zq-Ӯ=sG(ɤx gN<ۄ#C}!?۟ޠAT\nqpR,Ad(Ө@5W/LWZXk5"M~v-LGu#$(ܟ=tu7_L>h.},XcD,ZmSI gڥ򠣤M5ʞ;c Rh$':]#m-Fщ@ 3M_hB$EQ ^9w\r˫C[KGDb ݝ@c}so Lt=tMW Xy;)Qw󷮉e<.)1OoJ0s)';s[l_v"fXb(e祙^n,$/&Ia߅ad$4NSqf&%TY1s؝ gYj͘l~2A:;!Ax=`&0l7EcYb_.f%if ET>` ?VLbП ##%[bq>@SS BhɠJwPGO.:+'NȀ}/~p`Sn.7xXpf 8x{{$!jӰzr/y[8DQ=&@kΉoeO?O>'G~'doL?/AFX{S)\^#5qd5u%+)o/W|ЃrP=sSy:dz_$"oϥ ukkz]g<ɧ?WπW-t-ւݑjrâ_hR}`A's#r-J'q*~OVt Ge}¯?an";#?!n\aŭOE ?5_Hv{~O!oX-^j>wxT3sF۹mޚϚ?yg/C/ .-:`Ο{fgnF3̳+RIL|/ En;8u՟*_sR\&By7fF=t$\-&s㰛`ed?116$:!a?vCZŁ֮fiO)d|g{k\Z~z٧x͠x̵q~Q̜̄aL/x8}CN+>a AȜ;s/wMl D jݠeR Ìz>]~!C f U< .@'{xe;2ْ;DuӾ NKIS'fpf,u\{qǒj,!dkA"ap#A|q~73н(zj ?(iiRBᡈׯWݥ<"[vX#=1W:[ cMͱEnGbmn+ 2Kp]#hXIτ\ ;{py6,OI\Ax[w+iۥЩmT7.~= ^I* 21-y2W6Ph5~X]uh kqyҩTKXay(e\*~ OYgܨ'~ bQkط׵ۧzӥջ]Gw3əY[lP/Db릭䒦\#k!yC kN8l֗b6> zٷE%klr)^bwGuwsV ԰fڨѶnuD^Nx5v6VJi^n77f$΋p%i5()"dvL"z!7_ȦwGTEVseʑņeϚtS>T?Qw(UrT'(TǶWZZ<t_Z&޳6>thކ)ϟ /m\HdI`ŏ"LUn5{=Bhux >ֳO+yH! * .jgg @| _@ C <P;cdVY,QciLY7l0]%aD&ڒ[V$& trd@@Ƴ"]bgdY;@VS w8}[sk&`Koӟꨆo߳rN KYk+_q'+6P*A6@6PeZfC8րFnw@[嚾U=ķvˠ'i}MHas3fL\b ?3bbr_wڔ\@o,ЯD0 W r?>C `h =?'D~o 76)|[,oX{ZUl}>z$y}B%9 6m.Ԧ"n6ޟAv[zZeP _m./A/wg)9ұ\WB|%wVB}?gG8v;*[xXw ,tݟ{+-x$;yw 7T=Zz$NQYSu݄X;5)oVz?ɶgbadŭڟq[YfjꟐYU\ ]T}o"`hu(\71/nPvǼ!'uWDjSd&eXW{`]zL0Dl&?1#(KR<;6e[u}ɬ"( 3V-YS1r'OL-5Q}9y^;=+CFJit~S$?sDoanX[ѮTz3 ѹEoL:G[J q(T)Uj4vN{z=_eT6/ѻig̋ř:R˪v}I;!^tұj/\D_bNfg }w5PV7 *~ƿΆX 9OZy8}V)gVrbU biښhgps;tB(p+fϼuS^1._Ld>Q"!9 :8Kfw{jc9!|5rbYTw5)n6g{N ̵]&ŽuFos˭hWLGHQ~JE[_I]ޟۨhx\`&^~\8--=$2 .4H/cڲ[^sbuWU4~34|g{9}ze=w<$ BRv0 }\4T>ABH|{!6K_禵#:ϵ@Ewv\U/i^xE鎻UIRc [K[?s rslQ FqslѮx!S[Zd(9VδpT=5J䋼>-),u&./ZSUȗ/RC(?LهHK@~P'8'nBs:aUY'E@cZqcȂg³yIJSN Xv9Sbm:!-}Nu ΖRޕ|7_" /hhpvr9|e_|lum&=?Y,6:J)⥖Vuf51|nݩEݟ/sY].@]0Z[5Hc:ip0ǧ6Njrirϟ HV16빚ǤpD; ٮR iywn 4-%w{KhA;#F&aN DE*1Ok1p&aݧDUL77aq&;wə_&^rmV&"߈Jѩ=-ja~'u 6~:De9 +~!hCIϗ`1-N4g MFA+̎l$Y.OKڧp"az$41$rA볁ѧ)# ʧ  UD_'OΕ V81<=,;d% *AmI_ӄ1vB%4:Yh@,hH!) b[4z\*L:@VV;*]*S*tUX6GgH2۝̑i59|.g8F#4 wfM@Ϣ6Ze+I1=\NP㒢tS"R Dfb4PUz@}P'~[tvOWǴGW.ڏ6+sg @iYlVY#jlE0J/ v'ȷ'`) jL:L @za#H=`zE0}Lq&\AhCm}ThҢK&({sY}lIXty-׀5?6W`#N;9pp8Og~J>iGʀcO F$ я K۽Wۍ'b\;\n=axG`?qУ<$Y`A`:)'_ĩ og:O?e/@zνMdx_J'{P U"lvPLswwb߯:mF5<Ԭ 2?b8??k/]'.O`k<QW*Na {E` (xȽ?lۿ!?I_|8)Y {;>ďOi{XCۜ9ݰ]/9Jɷ?!u w ;_O9Q.ǿvGC#AyTtX7,: WrR.[j^ό{>Y̍) BϠ9g}—?Avf:τG#OGOa! #V<řxsó<Og7GmZ}k 1lȫY˳w ,:06;Ϸ;t?o/sৡ?]βD#9v uT'/n,V Xtgk ~|&DfPZKllѶUGF&g ύM'^b^So?4ߠnB뭆NggZʗY?gN6)xe;zh)InYypAz5}}Y/1 4꾻.:) 6U@'6 v_cO^E?yu0\ѥ)Ҟ+$:aLvYb|}:k ?]d܂;e`SJB| .vynMMo^-wߟ"nyssiuUx'sNTwjIN9AnBb؎xsixleo(5gdd08^PK]C֏j8!vv*N:p+Cr37aq>ҳg qֶrGl=/5?hr,#57GF5dɷ2Blkcϫ1UB ]&TWcsy:E]~.BeԽS54煾2i cumJui(x:4n5d^!զ*Ppؽ-ƞ sW:Sm(Nv#֙Н>|in~ka?ٸŃ5ڛ7y8r uKA$k5{x]I_C/,N)bFaX_ՠ8 \fua﬏CPhZuw}w_ֺJg`COÚڼuijZd8[o$e )gV8]]⣉l [ӡfJMrh/vzX4O7taX~>o@DY_@x/ظn0*e.ћSOJ%镜HKٵ1(%`TOxD3[uxe|Ò%i;F"utN+ˢ#uj`ya6yTX ?qrן[\(쮳ޛ\, qIX}-ےqj}=Q꺼OyA%ڵ&)ڛJ{i  ݱ-@98 r\fpMv q&0"G?VVs(nѾɷ9"ڲwՠ^QRM>Yljn;w_l葂u;D}\ZUM:ie1/3PggЇ Äȉs]FUYӡJZ*B)t숱hV_,S~<:8W|C]]ETØrKGD]eT`xQJf|~tWN?L"Key.9?ZkNURE, vF˧ͣp D_pC .7K>(sh!Dun*ui=Jz6}R˴85QbPO@~Tg߶('`Hꍗ8{cr/ϴ`<(:ےԦ |%,q udϼۄa)hEܑnԭ;-ߺQ*OG>Nvuxsa/hZ"!Ϯn2ݸKuZTc G%{t!]E 55KX"2˃;$ٝȗ[wQ̗NDnKUmq+^?hAT叢ZF|2fGv?\i+I6-!5Ie:9n-1\"/-|qgq,oL/<y?w8蘹\g_# Yi>,r圐@i0>Jrv{W3[o(q[zH u2F."7 T:FRv.9[ШsPPKvM"< R9we;> K /}d0ȬdSvچj~>]vN,zztSN!:z!f[B'V[zKH˿Lf)N[3eVcwGuF_ .`SeC=hdme4X ,:X g QmW`W,+j"j/__B8jGM{ۈO*>ŏ>z|dDn{r@8a7LIyr[4Ot?D SlTlS]2ExӁ>}"=LOqRYTn8?HR6a!_ACUmRrQl  f@/6 ^Q -=$:\J`VNȼ$d٫Zx "sAUmOpb䜣(YLs/R5\g}9,K1>lX>6c& / 7.yx1ݹe\GeQ#3SJ;͠˩ d C怑/{83> bxɲXN[x$t'`r0k-GTy#16g.koyԨ&讙x?-mWNU2t 3 /m41_k`k =؃C_`>`O`nE)q `nk d#Rsao+STc8s !HG2F]_p-k+hx}^ sM*qB Ԍe={~,JuwS{R^xZgy`7YJW /߻=Z ^{.ogR@{KQ+2ML^ $Qb?1>I;ǁ y6/vH&觉 zy0I[dωn\ÀA$y"C2Y>;A;dG@h(8 YugXSW܂kR$Ƨk08[)Ae%mljx<9 MTY3CkhڮQ@G c tPoQUhmf[W)uRk tMH_q+|K|0~wzo`4 LST`&IԱ 40-oZqYOO$!ɾmz*ۗy?"X/$+Co> ޳6 oוB ;*s%a$ 5!?PݿLRD~jO]}[?I >!,vZYR~dJgaOahi?j^QSy{)wHlF'3N\3_~ׇ6G>rGwQpa|+SrGm.Kvlsr_ӺVlbPX6$Xe#Fzгԙ/Q;_VV-<ꆇ~ݲИAu'S ;Z_jinn:b#cR93^Irn=(j|O.2:>ܘWƺMVCz S<7{PSƭs둭jIQzI:$ͪ*[v"_}N 7E"wmm b7h۸:~C{DzdFgjNӭAɰaivUG9ti RE>A3NC7gIJK.l\٣Qמf kk_GW(]#uտԆŻ:.d'|yUz(ej0Ja -&S-{jX?qr(wynav; QC$7ќ'e~37=KoTaX^fV<ZUm>noP֯=UD;CC67)}9=_{~i/zfh\*WuHysJsѨz]U$θ{xGK(mUX?G #($94= yEhVvyߝ}#E̽:Le+XpV귧Gj>ȖZ^eղu-زx#}F3tR[=jN3kḅ^gLкZe }JN9c _Řr^_::EXK\ZtTNUxBb{$x>*^16y63֛zd`wgk%n_nv KNKɔQlvӅ:0rt[ InsmĭOPG o0LaIj: ;h5ɢmcj,>ł^]mׯ[qժQFқLZK>I)QҖrgBnlKm}+#o s#5,?Cl&k3+RsUF 6پiרJmǒ]5I+HU+fHW;{PW~|Ѭf5r1^YAhf+bd)ZFhfotYISzj0ʕ6C[BmP <+MǕ{>aJ 1/tY1Sx*L-Yqı!dkw: ]fB,Rygu̳$?U =$B~*V2'N,q˭bN|jEv8˙_-7>{8/taUU~%Lt= {Cf67de΄e.ҷк pyא9\|S͈. PUBLxȤAv?Wް %Iv]ϾO?B2*qʊfcrDߵ~֣QzY1O%em#t]LK)vxeغ0bV].b&\bcGa稳zstY sCUV蹴v`1$|5~RΓY&]0\hF`b/.+^h)lRXw=P(N 1OHc$p* v!FScm 4cZ41x<'\VMU 5 dri*D\/˞m V-ّtuhQ}|!M9]`J~Xd-ӏ՝#4[gnMhﲣl݄#O_.sE m!@́B`wMXWQf.g. rVoqN#XkX۶[OBHM2̕B8wjowIܔ\I`u\BԎPV-ت@{/Yq3wQYSoVB w3]NjC9hDTr"|/5Y u7;S@y<B3|byI,8$dO>#QZzK*6C7mk@U&XFeUW{0[E-$ᬤfr(HJrRe۱DZvԌW,K4t"W d H!) T) H'_cZK.f/I*F?UU&>!9I *061%IB-Kg5`-f̃x쟷?w?' p;m*qw)2"S($3"  (­}Nr&e$kZY#\UNa\58a?'e%Q }O)tڛ0$u9J񔈭o0q LSe OEM\I$WO c)lzaKV~{pCP.ݳ;'W]Jo=fx+H5 Mj҃'dg&I_,ސd; G>!-\~)g1O9М8޼{I!"~޲ s 7& |DM_K| W0 p*݉ۜZ37R^ZШt)eOFgwކރ5;ڏVux?[rB۝st}{Ӊm[|lwSƛd&ٮmҟ:jnoov.|1Y# 6 jD >q6#v x0:8W@>~G*̢Hk{h9)A&)aKᚸe[ Hu?$ޏK j|s^`ms>AHϗ?Ec_;Ʉ)ئ/Ua|x;PDf~[̸,g~bK\烚Z[| T\ nW {"z֛Lo\wbJgVOrUWnmzx[p,T6n⤡=3mhkC}A Hꚕ*>St˫ʁ[kTtӥ1'ܼ;~yn<[v|.GFPsZВYJN'[(_-mF".8/#XT.t>YT#RB~[T/LIMķT`٧2at6s ŨysXk4MG3TnƤMІ 5ᭁi+ad#]JfZ0SQ;7sel¹li$mqSuoٹ (S֘%st1ʝc`?BGňceԯs疘 R)iA6\ݜmئ5R[HfXY()zl{&0K1]U- h]/1OlW#G/qem*-ne QRzpʏīivi+so땟.k1s׌j?3ݰ!J*ʒ+c _&O)[_"Wj5Ѫm:X_`NkHeF_Lєzt2a=@32Uh>1U1 dfd962<WxPy>\dTU/ټLտ 0 2Ӝ(™+#`6ɓ"ŕ.Mݻm N9)Kt!v[}{._r_,XKwIwgXi%9wr3sI|&>.ud.?۫h[Uo Kez8E: N}JB6r"hyZ,H_f~s~cfk ?l(%5”[+0=))XXNSO TH{K,2ð>3h$\6>7sx,<^ɭ7dţI,zi/U1BOi5+hT X93g3Spt$^, yo-rQQl@tX @A, "KDro99" )@z@x)F3_ 7 2 |_.5@m fPKĆ(clv&sB/_RMFO%kwخHkΤۂɇ*,b:+|#+,b¡7` 9ݝ&L3 ޱU,j,`:0Ֆ |8L~CA{0uQ,p_ {zJ۪a{QD5OS>E?9tf_V2M`s.`1` pp8\b9'\'\:=֢g2 ˽oND$t[sRf?.ي"ֱvΥXʏ[I¡0ߒ2ț:}~ _jjaVaŃ_@h 6N1Y&/Q1-~r?wX;}q7Pj_UL׀BpeԊjշdtD1UW0*?̤p3znX'7yA?HJ8aɗ&00 ~M =`00UNo8X_bM\I~CŝXXN?-W|:L:7~+?XW@n>߇/HeƢv-^/K)bw s,,I.PZ]s C?\-o8-ˠ4gۜi/+\{˧ٖoǛG=ڂE=T\EMWRvu.:Oty0ČJ} )6k(!VPNg9<󌻇*6m~ۅ\X\݄[>\SRO׋N{̠̍"4^Yt4b.dz(l(nؿq]/"UzYٟrۣCZ:f V:U ʼXW|*ZWɾLϏRE&@xy`> 0*p?W ~7KyVF['$Ώ,ώ1 3̪:۪W(˫R/mkyĞ|pkJ zmf-BAf48?6-Q~XT7yhx&CNӛbU?۬/ILN=[~$n*2ZւCRmӊ 2-蠾ѷ5?Oyߥr`sp ˣ|VDy7$s΄iLUژ=J0KNVFߓd]RSfWD_iTh#YVGӄd8*w碘HOVkkӪ{E,Jp;U}j^_ OUzWsa^/}Fx\+cD+-߄80V)A9a4NH\^nrvu-Rw3rS Y.qKȥe4e5Se61 =0]ޒo_,{jU3Ϛ6x!YbJ6pyHܖDDƚ>gѠʋ+\m!d?|xm5n-e^>#%\ aZ.nO32B8kD)1U&x ձ:JZ̓Q.3"҄;Ӻ$E{k΋)ǫ1j;IєЮa"4ۿ<<|<~Q\S*][ 9p/L;h0b J`ήN=AZj@U gMƧ)9OԀpƄ2>Ye+Q>n¡{X%'t; hx8~q4dw|\3ęL:H;t شr|V)VnrLsKNTçՔR +(`].F<7IW薙TwNE#bZ^ϾUu+H}()vWͿ}0$UP~ 8tG6d̑ U&FGI+^/,,Ud-HTy AW1Z2_8mN@.&#MQUJ '='E awIi oww&6GS8r4|'lY:԰"t1򙟣ekpB7-ek"dnCX+,ln_ys.m3jK$\6VkUtO /&1-aNF'E[*n~>J.#kSDž5QnZF0gl>,#Ajvn>#O߬k>s=jZ%&E޿fgɼZ-}dn'IB(#;e +~'ZrnX<"b/ +* 6ӷ!ׄ-<԰SOͭ_IUSЎAv\H 鮦rCV b6W{~yKdI{ԓ Ҏ>o|X`zwS;"VU+>*B.' zySM^7tf{) Vw he^hU$DO<+i^>b˩gk,E[t4Ii wV15!R`faR,L,t"%@α 1Y `x?LhxY.j*)"AA*U`LQ<Ljс5s(wv^ZЀ"S)x~?z%O\,5!p-t^ px4z{Y=`0^L 彅bHצy`4V߇/d3'p (o DN[` ~yH!q}!u1rT#u,' @D@ !o'w[>43;#2g L 2@$]bq!QaBӽA! F0D29J5@a R H_۟q@l{@LrH"txrGFC[(i.4+@gu@OR@)`0Lz@?V,CE5T&1 ,6٩e&!иf m.>AX ـA/_w5?u2LXc:l-=9?Zx,"94xv5;t~ ~$|չ׺>4RJ"D`xʥM$:hx&MXk9~QKha@Xj"qA@sA>z߶jg;9`[ސUWLXZL:)IEmljf/fw[sH*@.t= HH!%y' wm3Ɲv- E9v#8gß蟭?5^|?"&&lnd5&ѹ[>v5#*U@!P^(x* ( l7cvt%4shڒ/ H$&o~[@:wAC`0,1:' ! oXolڛ[2:z8Sߙ4ʨw1eUt~Y:Փ%'v$'Pқd>3`7ٵݻ5ax*|ПS$~?y feHк1J2$]sŹy|IS›T W4Ϟf; CSWj}j~IΨc'}lVYYH_ endstream endobj 30 0 obj <>stream s-{m-onl(œVHD4'>zƣmA  =aWR`w[EM!ߞf?$ 5Ik]}O3شf?OYf6ۻ ~>8fvQXUȞֹ)rg9V_v@ F 7mO*[?ݸo`CbMښ~ȁrѳ>"2S{ 5ERmj9 [j o5$_FGh[ 8VX[F?tWI炠Axś j\XbIlvDpf(ЗF ΃bh]kФU=jXeM+lP REl4C GX psĥ:IEXg#/JYectlINWEkJoS>fOWy<,<*m+a{7,V|.t2TSGY-~E;DGMJQ&1Q:=~a{URӭXyR&˥-| $kV9 :(ʏnΏ5L `j%7)XG޼2ZxήC..{Dةg0>[L5ƚZQ|,.i1?#DzD$2 xBe:>˔] WsndY+GYesXZ|?0ׄ7&ud [t7VR>nj%`0s8:y5尴_ay ?auH$^M?5-WK;wyK02,LȠƔ / 4Cu_:~[2ڪs@kԊeUb|0QˊI(tKb-u*"\B-Y ۡ' ͳKSpF"ixR=M"ֳճA35V6>ܦUwGyٴpH9\!X5Où)IwԤΥlKz_$GSL_Lp֍ڛnWp."ZϹ/sk־}Gi+qVWPqLV}tR2=뇾w(M> 9Cy*W^SgYa]72R=L%a\Km]u|w?>f`szр]BQOYeiԲ\^#zE-T;-N#<>;ɵY#(5׵xeRJ.$m"/LH)R!<ߏ%we{t=1Ԍvi@\uIayI[+7gxܛ#ή2òlɔ>]6ul6TS r+adۺn&z)%z&!ewv9|.9zɹ/ⶑ@\-Q"*oR^_ބnpǮ:;SίK O?JRt d4) d{Fes|CĚ3iTw#lrjG&p'_jerd2ʪXѥc5mo~vf , ƽ~ⲅeڎ]{ԩ ? ))82ٱ6i'9:FW<8.Q>[/҂ŃEKr3nܗm:XlH/U;NbFNwT3jL)-d8ĝ5s ;4#{&;4sP/,("^xo$iX(axr}\<@Ӏr:@%g(}thTvW ?ȜwӬ|dt=Ծt}f*ܧeK,;.MexSQƿ0$l%h@r"s ( 'ruP!({ Ir!qwJO2+(ӁYg70@7 >,hL̜ղl7pqo#^.qN2!ڗ[ܗ/m%tCx^VV*τȞyɸ䟀`b-0d@+iX}(-`0]00!3D0?P:-wM3̍zwT~y|El)|ӍPU> \!/Lx|lPCO?R(/~>~-vWhN/v06ӺAIi äv&&>9etH{#6"KBtIH(k p'߉ى9Q:V>N.RN4Ԓ2(W،oq"c@@vk 2' 77䱟Dvrl~ K t2F\-Փol&d^9$qOPM }d_xq#&~(eYkkMQ7nh*#W%@nwLjx]7fT[ Uϓ /2EoL?4^dF"WuOӿ_"p+01} m{FzLêgA@?hOuwϤҋ*Nxybh͡Q @u ~GD$X/NWo-cpxRLhmAC|N|hs"&PM1z]L⋒tmՋ{p ^wP"GQv';ѕcrK~ʾ4t#cK*I@ ?.و!/":߸cAٶsh.s$2%C׽ZRuY sJש+ңJ)\.Z$}gfS½l<u-8M73Ηb>ϾB=WMlT/AC6#A^|ֽV]T{.hqR 4w]:3lVXVA:fKj/J񹪹R$ 8 Tet1LV x20ߣT;i`QЎ"[X*%Oo;v~S \Uע{{*Q;+FydbfETR6s%CF$5GV^sβ:ywׄ7[L2_} 'z o!ϧc96P2"o +>eS[%nzr\Ē2J&y%Օr"#[~N '{u/M]إlFSqXdm(1fӳܲ[.CKprk 賮t{J6Z*zb[6,oglMgD%sOOZjbq%b)XZܼӲt7o̴|pEfFJӓf0ҾCR{'mzs;}]syP6l<嘜 m7^ gX#9[y?)-qؘ؄>niY=jizebZ]b5X* bkJ)7X+}9D\@X|ڶkw;rK+/Ș7fL]H;~1lvC߿'}4eL@Iˁy;cԻT6YA0!{Kj WōowQIp"%tLrŶEF7b x&X៓~Op-Bޣe{J]JtfEgD!C?~-E]痾LJR)兾Gn.rdIOf/X*g\퉌U~r{3)x8,dFsXtr5>0Pa G;2'1kTvs5k'V?*1-}8[|Tʍ\q[4:;_I~'AZǓh WQgyLyFDx63IrϽ.2\%W9Sd6gzWI"m5nTȪԡCЅJrZN~ճc lϤGDnՍݕvy庽}#vfåhZXBn׮GډO;7LB.mp{X6dྵبV7JPrPpS3\'kGj9^"[c%_-7wN<ќ€h.1f|4pl%V=Ty0e~N+Ǥ|Nɇt@j# nAAXtn3EU a17iT1J?ȜNߊw͕}Zp46aqW#]͑7ZT8<#:p<'t{$UNU&q)x;(`@0pxbdVu/J7msmeeTQҤYPnL;a( fOkn65c3MǴX/cltz!# ۜH%Ɵ.S{Mb) &<   @qr(J&b>~䕘9x򢶒MR>h[jm`cptBkhW}A[-q<)ć#>&`j0qH-;NܠE@ Ă$Y+eϟmt0I%,c`"BrN?Lsiɔǜ J)^wVD#1>K]'0whI.}+YgM6 @nis=Rrkz]g[es}}y$KH1j|7ُ]U lK^Ts OX.$<@Ll)sTT (,PPvREH fM(N}qZ("zsS[=ւ"endPx;?)'dV{fdt¬XzIG%V0x ܥ}@][@}/@}YJNͩy(ykhl_$>"l+"ܘ=SGB|p RF_ndi3vvC5T>z N>m r^h=aZ  %r4}ͤMq興+1nk￲^,/~s|i~ \3YkV d Q+k`/UHb%`'qcN]jPۻx!Svnڏ 5(OE^//b7.+??_nG(p9 -`07|א7Ao,ʾES %X{po=y{R}!F]6fjWw۔v\U)lV%bdD'i ; Hx-LkFnRϜ7+<qk.p>~rnQh.(2ZtfܽiT$R[ qYo{Gůܹgf,3:}{P.Sy!,AOc3'47 ie_DH.FyrA" K}>E|'_1(A^2̝y.*ߣ53\gf"WݞM7 =29_ 6jۻ~mz~y몽h1aJ<[4[Un9X326Hި@Plj(eJ.=y Nv]:]Pm8jeK_<66g׳^U.\ead}Vn#S0.rV)1QO 5hCW~/0!l&E)ZzWw <3)8WM5v"8eSP˗tyg>8pCgf+@؟|өУk( Q? BJLgCo²*Vbt KJ6r vv5/~o^2qqw6nĥGK JN*{.ΓIyH%%1_K*,͗w O$5nP#gOAmꔐݴ-\A' `lzVO37=YYgda!\M?ٰĽqhƫJ).$/AQF))\Oaixaq>) 88yuC91uu#{ӕLdvxqrq-iSkÁsKggv+ʹaGB7qٰt{ǥ@bf~6JqFf-l*Ez]2{__bu)~Er@ (KŠ-~%(e 9̌>nJzR4m7f=r/.G;\'JcDC,{e9fmTL|<@,Uta%Xj?ge}pw-^9woưF}wUO*we7ˁ(yUꝷRAUdovj>Ez}]OJRPRo%E1PruѨ7N-fF>xfb>qla [IO 3Ov4Ԉ{.mW*ohAyR\Ёŷ,&-5QR؞!cJtk\EԥRO6k/> ?dX~0Xy>x ն2k8PcbjWcW V)KyZ9B٥?hJ+IQ]W݊sun~-tSBr{7^c08dɮGl&,A>QVNԒVPC멛|Q ow}b-K\R>2#b.DC.{zk??T#o8!7IUp.8^U6)jL؏:HmBeյi> }ס8Rnd:@K$^a맖gbd<.k<M2:z iR!?|LGNn:>bɥJ ;?.lO>Y2nb*, Si{hV<QR>'cN ij#.jKzBy(Ɯ"Y}1>NQ'PYzyue'^BxcSq\ax1',C+0Wq0Αw¾ԡFT]Jt&ɖ~Ot &Ox8T9P7q[ʂߦ1mq=d|ZLs 3b.KShy}z7JRU̓RP8 V#H-ADg(uxBxcP_ʮ6w4΂e&YLn?.cLph\Za 63.UCJ&d+8֓ڒP;7'}'AcjXRX:jEAz*+rSҏe-2/97cv)w̆a5x<Cɻetސ-c E+|mRl<_X`6HB?ANt;XA&PS|eNO/呩O` ݩPN}zt;<*?v>qǽTcjL ]` ݀y=1(͎MtFu@tc @7 ju "!eRaE mX ݱsA]OfVwהV}Xwx?6IUG`WS(5 )H T (gL" $\K~q@l |'S$ ɂE.sbSW|>mLE]apzeH1G)~C;~6}l8O/^<@. beC\K. IU k2 Z|3ֽ8ubQgr{C[HKYLhRI'z3ҟuÚ2Gw(_nUPv_@UYJ݀D:QueܝTGa(in5e21j c\6w=ܙ~_5}:lcF0=òX ;@3#F@iPG'%(!S]<3Z&5O໹lHGWqX)i`|)HWEj7\Qפk ]\?;r(bK\-|Ȓ\LAYɑrqLW0 0x>&piŵ;+ ܩ"ei+ C/k C xXXVڄ*XVp {-,ᾒmOVJm( jr+|fqIM>5in]ҌYSDxȢퟚz D)?:{ˀ $|`IOOxupp8enrlL'x/-oޚ'xapB+"G d>*OMvV_EB1\l@Ye@oar@S@ȌG@o4w7ܹ?)UUS NqE 6[o<_m?eE 7OD\3!Xos*G.smKin@PuI@b&e z.o謕 i dvȳûSxZ# {QM(s(f #e:`yj;֣tVE1P;Pw(s(&m6 O>tʄ|.#i߸7QďE]?Lz¬"]p (0Rpa`~z]mΥ8-?%ni^IDj΁>@aM{Qt/bE1[Uy b ZpoC{ReT :DQk"5OP]$r?qdFV"~/?5 p4{]*3K/k/JKzll=8 ~g8!ScтpTv~O/} $^5'}fer+(5.x+7`̽s"_ob2`Qj9^/[}'"yQF y~)F)d3Fh:t /KcP;MO9pwUy&q{tI,Le0;7$~UQuO@mP[>^x|BCEyǥś8˓I$Iw~$Nji9Q_ /~͗i;J7qn$~ cZuMa{U2O'j Em6=p.2w)jP.`u>&Ԋoߨ I>(V:=d=z޹X{%"<2T\FM+MMGy#, ȋO[R2E! s'Bh0=0{^;P7(}tTk2HMjhOuNu%k V=T^LMr0KM6ۗƅgXJm8"~]g(y7c~V߶tw QL엗gѼ]|*~i9~Kէy5* Ua_J+r!T@c)(&)t'] pdTV>To?RdKpíT̒:[hyli~ )W8tuLxVр5T |-^,&sG#f]Ofܜ<c'( C+d:(X_m(f?`rP1'q"/Bi d,Ru)II@<@|b@̈syLmq!ԥ[z+qCGCPPE(q|T !-uo(V5Pk ((*a<8{eY+ҧŐ̑Waz GJ>1 x受{Qo`.jM[+/7Е Ϣ4oZ!u:ĘÇA$R1 CGO GAJPZ¯_X/"f"͆rqNJNnWXvXt9K78IQ=3a9pYbB~9leQo~{Q½PxC3NR+=p$-'EN˯Gfi}H9 *a]+O<\rp/\i|뜜ڥ{~dWf{ u]VNrN3<(W Eߺqۻ~;;~n1v궔.N,gQD5:c?б{ݸo7?ڸ'ntw7Hc]{S1%IGL>j_OGRRSZ:ƗFfziᕪv8ʟwܙ2bˬwRItڹ1\E}}ԝqmӲݼX͕7)lJ]G\F?Ս87>ވZ3it43QۋlC[/^1[{PlϭˡPHw\:5ۇF]W +N~&gQJNXm?5:ra/?5:˽Ooa#9C7 [j֧Wh]Rg<8FQSu@[4cWƩ|24w pu%jǩCaAnn[!&֕i݅ 03[hݨwrk 19ƑVr=rL)ʗT!8gdh}-i=#۞ިxoheVwSZ=>6d-!{߰6dxː  l8/ Ph ($i?d7m:8[Lb,pGFg7Ch3@1WE[X*DDSMPX#({ui/R ؝g pSSe"caUo׬+QfuSwqM !$\È6{#~k? yU^؎ Y]#Ya=+6@ٯKj@{׸{'sG>Z`M۫ޭ \k!-{l"|f'1nd-&Zޜ_~Iv;ed@]gr8&曋YF-5SnZg5W᜛09ķ6> plǐw=Au~jOɸ^/ 93{qmd@/擛,ҵ<562iJʮd6 j QU&/P@4/dRע O;MB7ꎰk_'ɳsg؛LfI/]{`䬭z>S{y9ܠf~ݘsa3*(}۶8~2Lw8N[sѴ7F+0ߗ5n{+tov:DJ&12_jLNclyI!%:C>) 38 N~ (Ѻ|qԕoOefD!)^b-Qj2)NʲÞ[|T:aE-Oد38@='.s>UNbf]#ʪ=cqD55jqFG Kdj׏6_K!nb{zI3xhL2 yuPv>g6`|]\Ʃ`̀7<~~_RmVLiV1Iפq3q{\ɝOw=c.wtݡh.% MwLAlw C/qWb!J*T#%|g=q p;h܍jŦDɢ:R0 =Nd:=:@M2qTԱJ_{~1)EN*ʵir'Xl|[ /TL(YjdE5> "֯ q;xPaAʮǵ\<3vzj(5+5Is6s! 䴣O IiLyq  `rR-WpMmzkaq=nAYs /V{N`wT#I1ˏ6_廨4'z3~Ƥ![IdeCήט6|_1>j0*{|2)l7{G;jfln9JŪ: jQ~,ӲRmӜVUvڣ5$){ s}󯑯Tz'SRbWPI2>n~^uJ{:gʁm̅A}Q!d٤`=}Ҟ_o l}W@~wФ 9-f.(mdw2ex;n=&we1SFVR\EQgv#rՠD{nU|*v7ŏ w6Tn6%4*Х!{)Ak0Wh^\Wew9UJ3uù%r}N4c -SO+q-9XW)r=o 3PGXN¹4"ܾq[MfVl)ƪbUQle6K2{Tx7 4B57Q26b7?L v;I(ŦhY%Ò`vHf-I@FD&i??_#~wm!hnT)*)@(Y7HLUJ KŴހ4(Mf #\8 }H=rQڿKJXm!FɳumSnY^Z8S1U ﰓ S':ʽ_u] B[^Ǘ˃)Po( Z0F0VIw/ 9_.ZdkWeݵ—!inmE9_}UUp~o+hX%ҙnXҾ{I*(9S|45dnK^իrEiJj(PS'2F;h;D97%s^h+gwR#“a?249g `9 F]R_^•EO1sVNE[}YZ_!BruYle l? @7]8P d”bV|Y!oYbma^~弳Y00~4LppQֈ! >PEsCO5CzYm81jT/+s6+h3_vV)~-=5c̰7z|S\Iv-~0J;ҌЭ _IMUS&cSN 5Ȼ HޗHx\\g Gun{AghV䏉AkVq_\MT49ؠ!qE M2;?# !솆s)bBJѹ`ݍkZf f_*vtq5lv%v+ );GRH$$@}wTgЪ}R=C_2Ŷ}.DBħ2eX=&& F{|UKaɾ>ws_ 5$?E:6,NޞG'Z:n4R&UDYz(?c DFs~ kXE*lxC C?/lnS|߽|p9de1K:UI6,e5<9`GpyT nH"5_i$4 =w.7qvՍAX儺8^DNn |1XK WBu}ԭLE>y,>S?ȍ&" ֵU]G4=52^E6 GqR)O85C-זzz aN} oPj-uw]ujVBfD̬^ToF1\ViwV$eLI'}I$<*_}1;b8${E=8u]}o9'߼Y@jOVH|Ϛ΁Pbw*I0A0FsAUFD菨+tWhnPH묘CKIF[b)#0rp.dR7 > KHGlJv;㭗Z @<2 MipYP]wpgG EA~ީ7NR猳t*ׇ+vJ/cϲ4dx48C,8~ICz_7gOsoͯ1)l7{Gsih}\daFl&_؆G)z S)[>)~+#Tmccg"3~!C%-a|G9At`pl[PIl:w Mgr-?wqj+o]Sٚh·IF?na}Sj(QyTq+g7+N@X; +##0#kޫgLti( l y*wW3ލږ. JWY˙GhYҝ:x?fY B}p't)_(}WQH3󗖺C_YK Ex  cc}<֕5Nv7 l_g~,_PѨh` num`45zx0uOފC3y(v0C ܣ}V'xkw֟pσ49INA!B)32q ;;M2;s[A^ʞ7iGҡZD̬#GhGBrchҳpz'S6黪1w)9Alޘ+&'3B6L;>O{yљU$!+-%o|E͹uC޷ՓI](Â#-}|<.6;lԳulq6dFk؊"B˖\ ͭI8X~^”j'*SzSU%CX0.޴7 !Z\YK5IB^@~)ӧaY_GHá&ja] ;|S"(&~y帙Ik%+ %e,{..T[$flB]Ml)}@TO j\>EPB^ m8ZWio7,O)Z2Y 9 m,gA\֐9j /U+T܅s)[uL,v]Ee[/32dMU48CkϗQ:7(pя.Bk[1!hpRV=bWr9U^>5^G|HQS_hOǯўc sdJVAVy] ?WT: QyN ^^ڜ_;U N335SE[/d@|MBfv)K5x%a3CeCinT>NG:p1p:1گ+87qKpq8v1 =2\1K+lOXc;JkexPUg$H0AQs1pڏVkn`.|i;0(}-2 J=-k.q|fXJs3d-"D>,-E$.cyT@/P-ʠz=0.DNO eT7բcţº=X+Nh#7cg͎qkQ ^8ꙋw \OneOlV>_Rcb*B4nzj9t6p — "b=#InbaJ{~^ʄA>S0Gz9W{ҟ5 y-4~uclr ka鏦xSݓ}@|4O[%GLpskk{oKT~Ǣ9⛕^pQȴf/dT9{  ]tj<۩p;ؖz3 hKv+f-OM^_$A1 sbGC?%DAIa 7,u"a$\N_Uj:Q&rnۻ%-~\:0?+xH&=OyC?smaY>,{>/|'!F'lQ? y7{VbIa3+ABTQ+jQK2Dr;ޚÇAҘ^5s)1Yf|*vƑaq3Qw v  @jAș&u=(M\D1͟|G+~ߚȟJ{P7~,j0G=O[f[BDbI8v&Y5:  8$.HG@E2*p(w_O[nEttM[8] <=% U@Fڅz60֫O+bB~/'tV s<,}5p6!*@ke;ޢqotnJ3sϔA7:;[O\xe"p |9+)&ú>1oW Gr ΂s~ܾ VH>ύ-a1x$\ <xgBKyfҩ=u,l ןRo_κ* iኙjoZxl0e xaRdӏ lZM|Aͧ7,؋peK"}(>.evP< n ҒKKM]B4951Āx4 (?DgFФr6c8"6\а3LKuЃs9u)t$GQfdj͌. ,)U<']=3r$Z ymC壉#޳Gg ǣINXPv #nYa@9ϡUi[{xʾvpށNk:Ű1:*$jQhQ"=Iwd-jS7I @b #;!/'a 9ufw˴[uڨ,.wK*jc-? ½5}$/IZy2;WoE,_JmWc~VwMmsP΋ 5AT_ :еx(z%ո F76a&7]n{Xzc*2y(prۗNlعWL&2ۣbVRijIȄjoEm`#6sF6A*; ݿX3JY=-QB#(6g| KPGYvMP"Kc,&18/cļNhw6^Kbc.,K$ R&VUpzu[>2I>/a1yy}K5Gpm&C EJ鐭Adf6O 7'Wr/zfǗ/aiD/C L!Y45#_9b*[!ESZͺBb&4ȟ au![.Ǯt+QXZGl?[)ڃ-mv0mVߕ0+%T%p/R]!ڛgqG( ]1$? 5C-Ci?nkޙeVNƛ:I7I5' kz1,-YOty!NavRZ,a,WNV[/lb;l&"bⴑqnsXgJ\GnZ;.FmR;<5 mWuyVYf^9i2Ȥh<huـb{Rƣ̱^`9{bJ>y[:nT6y&(pIW9d}Yߕ?ΰ>gQ?gQ?} Vgj9!ȐoFtV(@ ~nd@fȹ}z9Y"<1PG7L\fn-D^] ^α ZplQ9 < yOe`6 BzvU Sc~uk?γɶ [:KqC~8r7?L+Q? a>I(AF1 ?,@=@>jKO$oމn2w8f2kS>m[6[3r lz=9֌|˂;WO@)|.]s/Icn22׳i 3ҧbVs7mQz l毃QR :@~vM [ > "Vd9']2YVSXi1ڜvuկ4xDQ6j'v l rR*D}gjGwYwa4}Axm%&0ٵ.;q^Y8j4R6ڽ)4?4d!Ck̻;Bn]G{tw !`'e~gKcpW e6 ~(0Ӗk<6K’YYK@TCO#(cP }z.9}gVXC2 ɶlmJԈ& mw6LFV2&qq\%OzX o-YZ<&A〾n8_Ұ}Z=48bTކX<c)u!ćj([_dΪ@y]vXo:gz鎚-Ty[{۵Q_/1st=r]xJ )9oK MÁz0 .\&w^+kUS0aQ7ƨp޿IM# h+m/IȐB%wܡeq ?%o0.iF6NQшV⠐gA00DDؠ;Ry[r513+r>nUAoat$ L戝^- 6${̋1yOJ=^tņ9=Xy쌨2zZHԟSߨ PS ġ Z&$z|5Y#fl"پ Nj챦4}_Hzsgׯ"=z|G`2 )Aܩ=KfPEX]덣]+cp:v$xC@^ ~vnŻ'tp{) tRʟxhPȜ wnnpuU)d\6}Gžj`OexG=z`wj@?wR#5Ov b?יQvmy j:~V&.΃=dX:qߔJW+k=p5F*".$i]"[?}=zQ-gg!e{CRz ڿ=pt$ϻ)B|l,3Q۔ᆃY=.9cW 0vשk^?αvKgσ+e6[E,=PYIX 2_3To̷$cX#Ji i,·%63E÷{ߩCZ[AǗ;LmhKTn̩R2GKJuwwrF޶٥’ZI ؒ\Do>SLGc:HnB8zE/w+#˷C-v;Q^F+R(*ߊDj ]kLDÜZLcX>%'6_L"ļ~Z +RE==4kvmazMdcLj \fݞ#:S.:uī{uMd=&ɪ#_%3AgJ&R3k]ޘ/Xn.tzxIfo0ALqސ]VY{s7"tOJ5v}ƗEʍtJR5?%3U x)v 0j0~"m* k ˤ`$Q]u;>S"s1ȷbAUtr45nnp_g+G!{[JacoVq G&z5ͭ%R܆n D@2ȵ(;ț21+m`*?y#Ŝ̀=J:.,q̸cY 1 3Ht0b+ai?π5VЪk(F@~ {]V5q%dK'WMi۴eXw{ 'tajb'R=~Q^Bʑ=fUy Ⱦ"WZיIka2ڃ~gM/6WzO皅ŭ,Z42RѽLTd!QJNvҊt$kڲQG+?ɣ[ Z3>noI0۳隗qj2\ $kjp3T_9L`,I"j(iFQgmۡEl(}f:3)uY|J1J aUgF敍s5ݏO)nOyv (A0s@A=G}ָCXk1SE849ʽF؏=Z enxh}-.-:YsL>ޫG|2'쮺]錞gvMl5i'Vz_LVA 2e)kLog}/&:tkYMD@>?SPqdfƩl:hM6cP㷷0po'Uwx[J>׺Lrqѹx,H+:RZJ,E  zA|=YYIp>Fڹkv 3Eo[gϵCŨp > /$YjQJ1=-SLsdջٶYO'т? t* ſ0~5u3kź}=S<,J}g>s(ѵ`@-[Ii3DͤYHD a1澈Pj8[ G+o3=ڙt(;[NxC`?!/nYģ,bj]g|vY1Râ o<{ 3cٓkh{\9Ji"wYiZ'=_ժ]GV͓? ߕw_mDo2loнjj/j2wsOa5PXhYǞmr 'g$3lz[-Jv%?~|wsme|>In=L؝AJFs%BAdoɰ/%p,uh_Oxl}dJm'miIEcyinw_iq @f>ȡ =^Aٖp}4E֫1mdg$iːq~/?;A[!ЖJة2Q3fp2 ?&]8:[N*6fCfݥFE~Rhe@:\uVtv{VD2ƝT5)WÓm^>5fQbz {0d1=S$z{oҎ^]`n6ËK׻8Zkf1yD=nTS ?Znu?qtw窭ͫh?Msr6- \9'ʜsq:uZ>RE\1c:x,'JLNC<1ЙY.:iQʤվ71\(qeɂŖ:3q/M<:0 ?ťYWf3H oL8sDU'cEE _JJ3QE6`ա΋]6ܹtqLfIzY`ٌVݶ6iG eZa\+qfrC<;GӠG&g3̝R?:YQ[$cKt0ŋt[+֌$js:2s-PG+O&~4ʍjPTF=moHWl^voOOW_`(cMHpݛJ)a,#MwT74'کu_χ8ɢ1qͪU{U5ڒ[S%جʬ{+M)%Мnmz\-nEI#MoEDx60ZKH5y⚬֒'2JV_,ĵZ}R;J9(:Z=:Beo& J& ڑZ2AbZhDc7@/:O4I'[W p=<%iPז~mX?,wn{zݹ;&iO?@gkRO?JgR3v-(RBC>9 [Hb]BcggPOPxFCA``Bވr0{]Liܥ玷:қ?972WG댏2P*\Q <$d ; ȅ?@) f b5Who?:Jx*;0[%bqX䕝;-O.(rohM%tw;|^|3uPoyZ?tÑkV{Y0~d~<ǫw&f|g9(PRz8QZP%oC@)TPŎŪK(vAg$:6|lm[_|(cZ]PC'z:LܡݍriNe {k$~R#Gs@!t 9w3lUP6e}OF RL.<;wzƋI_˪wlz>YX?)b7N G<BMH[m?$ɬlWoCQ?M ζux)6uxVb<ΕqeOPL%Ö+J"NsJ8WKdJY 8,&y)SRV#P,5.ro~;{H=w7>Stpi2Lwx[7>i@!8Q\ȕl_iE6r8xUO #sdȥRq~ST)rTqEoGoԮ 0˽D*UK=&; ŵwh^}&쩘^KW|՜uG5,6^g{ڟ7]MAPg- =(?8: &9oW'eUw#?;in6ep;5ĨY>ٓX姯Әn8=aOXgRm#CX}{:?-+g. ':[ƙ)B1foysybMѽďwō!6_QUO8P*C=l -|4$aASlk#4OVY߾W1}:M|OK?Te P(87~<ɾx2 Ssǒ[ASݖcIK>wGj]osex8 4*^vW2- M\u ?=I p8S>li^}xW0M ^V;Yf`̘ejFۙvUn2Khl͜< DҿYI/Lry4QΚǗ%jx}_S[ߞ!:/$^*Lb9Iv|+) Y+J!{FK2[Ca)Ny=sTEVkג:Zٱﭧ\$"zF޶:IIVwrgE\C&@w@dHu>O8ٻ.NxO~y7|m-6ي:UOT} $qbVLXu'm= j^[LRܱW-E$iې5l.G@?oS2('bd&lQDW0(tۘDeSTS~ssR{HU*喪 +Q[g{fG@bgj4f1WvN~΢sx4Ғ̐mNnLʢ֏ ߿+SM^ٚi#̫_3/11zguvY kRG­wJ;M`j5m4uo^:ᡵJkEdjgmd+ m*lcJI#O%i$ǡdA/r=PNt:t_?5~J"u}e=?%%C ى.<sV/\CfT+ph>i|WEu={" 6v/aOFr^[%㓧a>Dߎ޽pv3V3h@ۥUˡښN3&!x!`>DpaĤ'XdF@o$:'33ݘ͗&:̭q8Jc&tPVfNWԎ>yNK>ךz=&u,i!Goh:4Mğ\04}_8 eIzt*`ṗoXzEAgX6=0Τ $\Rx_ċMk4R7'9gI=N:-8ed5Hwf'>3R:n)շꋴ oj DjLXZ gBפA34YnR+}"6S}OYlʬg5 mRM @*e>;I{CBǤiTfrK4UzZKkPg*M-YRQJdRj7RtB%q>7+Ü eHMJ*өTFNY9"o*@Cu褉_\W8NBGt,{Jz>*"-YWϙd0OMUs%Ed@z?ʝ9@\W; " ʹ!{g.2 $lrXш ejh`~K9@+szQ-:q茳T-8pCQ4V|RV8l<)PlA!cPF&}zmᣈh0fmcլg#zYg Χ tA)o  -;:4nRPFA Ckb(Haw6m.X~J{_,v#XdB#`bpᔆEmC@ '$Ĩ]bo=Lj (@Nꍺ+PJlk8n^?XVY{Cru9i +q5tHd k%"~ϟ.Wd5Pӊ*~á3Fk'Tsܫ$gm+ma7%xh@ Hr%)LG ktOa*Ɠ~;>7RP^&~A7~wGEUjϾqh%ɵ̚Z^ƁZF H eG<NGPg8_9#K#t>ӵo6X<=omd/}wt}`ϻnua"]_6 \3X6̡* DPԜc|5/aԙ g쾝71(TCuc梞޷Arp?MFN)l8,zc\cC 1I@6u;6E|F0\z&gmdnË{]ns_^hr*7إ잷nUV\>z}#̫MeflP-R>)@y(}p%_eHHp/?*pa{>PHo& OOm_rp,k[ұ gv |HLA_qlP7O TyYQEV=v km#&uq ;Z3Z2͇IJTۃصbkb{^1zV]d?vBif577yy9{{ֻmR=6Ml jKݽ-}Ʒ('0 k^sftVI6'lά~C{<Rgv-YH-fTZsZ5ٕ7>ȕe5d ^ƼT\sY^ R-5 8I?VqZwHM 5w_?wI ͖²P_=Uͧ-]¥}jw7^ƸmGՖkb|bV/ݽx7x';`ƄcԵjC-oФMjoMȅk^`sK}U4+ s[v+soOC7?6B5g,R駪+iUYMX)Ԕ_+)i;ETC^OzRc̼o㞜=]4(_gx?Ә4ejtOeڨ|\xTV\>PKrz޳4 h>Fx'>xDe.8 rpzW uvҶ}< {:=}ߟKI}U˻wN)7E{~co2llD SY<Ґ]1rW* j=矒RXEыJv^ ѽfAkh7+Yh܄::qzZa?TFANi9p;n[C6Je{Ao/R6+r?9ӝ}Qy5|5!3έ:ǭ*z w,-fVrs)9VkxYӊz]‹CI[M<;8{NV*/8X_2,W?2+8=ޤ&?ǣ q^>/.>l茬1YZ6Uj+^C)ViYn sBQFr#dKhiB֯ueНTJȸVWkE@b6g%> oWޕkٚȉeİrn{Q+Ȳ<>jhN/B1`^qgy}yh\Ke. g P@}mh<#x#Թ,,`JU-BϽŬZ_ #^w5'WƁ숓zߵv~8iT~/Kx3mao nqwΏyB#[n`VTJITK(Ǧ5dCH'wj7֕fVq9=z6drfKɑdIiS8<_dR-mnu{帧Mw+&y❒i ?mk]vs}tz6x77]*Nn [v"g9i-/2ߊΰqjWOA]h0'f837>gW@xc?[ZgOpYnHhJgq{Oҍ6 qHKݷFؼy.ns{0_R>9^5vUɇYRHsi{Ln+76Z^g'6'H"\:t_TTR5yn_ɫtbKغg{jk?l]vF>ƿFGvY&#ipG nXuf3 2`RF#ϼ/ v0 )QZ@c|5TN' [!85UgZԫrf${AR#gVALl4&~}R+ 5޵"lJ#Vh,%=J]ZO.J/:2-f|S U/ eԵq o*7k͚F;nw?nXL*Md)[A9 GnuT*"Yv]DZV~{3'eг,w#Gjr̊ߵlS?IVʌ(evB4/hYmlB|j˖3QDD kiЬd~dl:\#U(X:tC#U5=jߏ 9x9 )ȨH1P#\^WWoR@U2U }`5Wz7uk9P{b'@$@Şko-2m ގ܆RH{ig8MBS=Z;@` 0ql~l +tۇR/ݮeewD #Eh>(Q/*CV')(LQ+1ơh0@`% b1G8ǥ`]` \yޘ=4> %(h4)cM[טU0}6v'ǿW\nq]lQ^8aWx +j^= <&m]~^uiZ,̞ C^?sd͇Uޘ^;3߅8E&}q  E 9TD]}p7[8 qځ?ߠ;Yi4 4yJB;d5$9*c7"4/ž˝Eu/Ԉipa"xn8nҀh}YDepok~x\*sI<(?AIƯiM,on9ാZUr"-"+]}I78s$B=_ْ@V3u3Fm߿OpT񞴆GvK{k!܅١}5[@azH(xMF.qSm.o" <9hZ"p/Rz},@ БPWox9#LV7Ѷ/J.:ITdPnlr)fO}uؿgP%[y4 8 (%4m4`z֞ѝl[gXpYX9,_?f;n5C\u(nUiz7nMefb4~aաγ U(05TB~yB3RsnQ;tKafs7o]z'꫖[3]h[{=k戻W~8I  "2-<~=EHvnrNmu7N̫%(rJY>[jŵEw)`Y{yKZojLӠR) ]S Z5:A7K@(R"{͑AUNiSQ=~9ޚ]/ԧЋ>X\#wյz=2䬪MqYXii„ۂbN<ӨlYoy[Q '|NRͣ\@`Vvb^kI`:J٘κrbU}Yy#Q :Jp,5 wP'}-zʫL)_:4~}TVw٨WmW+y-y%!N=&: jU;Dv,̊t_%K@`3ed){`'$?,ߏNa& (q^2oԵ6O%zJ,X{xhhd^zܥAoe!ͬRA<m@PDgۅ:9`xYY_fy9}^L0r'ЫfW|zG&=7]szxξ4:sEN9yO!9e!XJ>k`)!5RfWg%[G\䗀|zP*'n +:m-nޑMI09bh S/wFPc#fKrp5tCv}V3,J\VuB<3I) - dw7 Wo8n;+\l^p\ ifpϤSQ3SBs۲(Y/dR\JM-wɦG?h:Oem6)Eߪ5ut{vζ!߽EßkeATM޻ڥ$9أjA5X:::; vf)%̇>)[}9> ܼ *z9S+?Bi6E~uuk-)f-s7vL9:gCfߒ\eTt8j3;Kmo7)])ƯX'Y?c){_8G gj$xt l3\]0gϝJ˸8x ÍES.$AzF*uvJvKÈ˦wdqKZUAJ^=nab]ަ6dS.E)Qyx!4.l6~咍NvsQo)3ώhgLXVz2{WVAQ <[,8oj^7h~v=μ'[\cgQ:Uz$l sV:ܻl}unx&> qJ[ߡ(2 |Q=9> ZRj ̈́V\gYaxQ t>u_?p." Z˰)7ؿ{t2[ћ|63I[Fsm͸`_!տN@MjKd Y9t`kueQɉs3Ѱ^Ӿ)k*;ĹQ(P{ћ4v:D>WF.y7T6~MoGcOQ?jw}t$7] xw14ڷՎUrIAd ?\Y'M,ָ*pmŞlĆE܇I }ΈR=Yƾą"?>Fx=w~7y=koYB0EO9o˅ƈ (-6wnʟ'{{|* X0Ϋ.h횮й5 lH,S?Ooz>qVNIOUn7?|ᖬ[ݯK}P:~?lj=`ҺkڬonÅ}~`ߔxjQ nD7!`}& 7רYt/ N,K.l>ԋ_~MO 3{>r4Hp_g`B谽gfXxi}͋yЏyGg`_U[9;=[x!èVmFQ /6Ȃv w%x!K"`8QY$|XEIpkä')<߷McpY:,]fJUz{|_}d%N:#ٷ~c'L.8MOϮ}Z%y v¹gtFE'zqe"zU[{1ﻇE4x1DQynA:‡Qg=?7PͥřK~~ 4 `DC! ' {DttT˘$t3C飻F[7W :^%~2Y>嚮Y6}3n֬^.'P0G54K4=~otA[e"9=Ŭ{޻3[JzͶF㈲yt4\l+{qEOkRaX 17 < 5X&H6dFʏذE0S\Ov\+yqt#L(0jaq8Ӻu092\5LW?Pi# ɾ82܄z*y8oտ@`7} NqijPT@˷PM]řh^;S^,%Թ fʔQa^gi0ohPV;Uw$< 5ґt#pFp,7$zРF6RN>9]hNǚ.ܸ_WĬ5Ӳ-ղW/ U\S%q!ي +m_bܖxڋBnuƎۑ`䤥$}3cKZ4Ԃɲ Sr$`ӒY O 7$<jAv_u˩rEugWfguR@ˏ?9ϫP@N+X@ ++ ITbYJi[\iq6Q2R^^jR=_C [٩B!hRlPOqEbwxQ$?Ho@~^b܀"$R6 .M0YYkjj<Ϸ!%/N-ǦSJ|9N|7$8\*1E8|"-g&s FR= (5(JJ7%]|]v?ޮ}v!۵r=܊z.b{^γNB!3i\<`()ƙ1=Ai Z:ZV=Ka3_>[Gpf1CZ(Tvl OբA)#KsK[&$ob_\^^Uy9MwuGge*nڞԲօ]z,?\OԎBNNǡ?0$hߎx3xuzm:b536eTڣEj-xѐ48^LnyW긔i O 7ΌjX~m 3|Vއ-q:u^t7%Smr|V\[Z4jW`je V|c1BC)/Ʒ6N7Aٮ=ͮqy}5eɷCj NIKU_0gvHׯGv`vX4x>Sn Y754W9딳WKKf4R@tËlǡR[.ܮ}i3;X[&Hj^-`x6 ˾1:U"..Ei(: vՋ{@HBl*Rgm< m Bɶ%uoճJ'w[IzϪV-Af\3 ۪$!3Tc[c:'HLIkJt#ҞN3M-i){ [A!n\%n;'.wyo\Y\eE[^)ZJ=qO1GM@J TC{UAxKԴ[Ҿ ծnHJa^7I@7;<~#{Oq->cSɞM׻+n䫟 ͑] '~9m~I¯JU5jV\}9?ib浲HrRG2 _τg¬Be&}…nl ukPMiJd܈u.)ЬfT=,etJ16eoڥOpo?kدV,t~f +t'SJe $~!4ۏ7, SៜFTjLWنSRF7[V>5c =)P":Z=}(%4I\@0'>_4Z!U'yd2JHeCV ?VLi߬$%K /Zui7%R') ОKD@{75/-@"/'{.W O(8Y U?3{͛ -lj+N_}%@оc@ ~jɋh!@D+y&d\M^i,B@zl>RM^cUߜ_ӓЎbߛHln@.Ok{1uEƣ.@ommPNeZ+.@UI'liIF7@dҊe^5h.f"t{W3y'_9u9A:v gjGlK]9@aXO^IJ/O*"YM]Fw4~_pmYL[ Hx*a$@ $Ta~Ez rkoN|AaЭO`O["7_~TNjEf{ z<oi|&4uC &ѳ/R @G dVHTL|O[9>^sy^׎xU~(/pO"TӱCe#I[Thݪ<%}P)ZOd{ gAdء+8\;9~{=٨5.`yh|xɍ4/Aa3\r.uE9:[8OxAVx"'>F;s[4ZpS_0{}n*8zUKnu%Mx{mY槯\x5p`|&4n;)^o{ ߛgF Gd8=J\8V꽯>Gtw8מzɜߋ!n?єY;lAԣk/ܒxSk{~0]kX١da Q1o.'ĀyItƪ 0hzJ"RiǏa)Nuys,,>8#+o1{ z&pq ߔ kmA=NoN=AOTo$R :'7:k=tpoޗGsY=`mb}Y1ΘƮ;)n^9re*̺ui5 49t^z'_HO==.8b D`x=US0p]wSLS ԮE?km,0hM[\R[dytz=mb|24HWQ~BWV̳oXym\:?tmpRE>i/ef@OzF\*X,phz-|1٢0.dO{ FSDR :"gpdr#@oEf}| PL$|mqi%vwrvCB70ErswT '劓 I(ɢ3?퍠i"%y6&RR&Ktu7AC[x wZ}էx9(t:/sm~.9/Y4%͵.* Ex.Le/qՐ SAH&ّ$.$Y0,U24C_zR!{Fe\Ժ̵26Cw zE C[}ߍlky_~.f&X%Pϼ>ptMr%f9 vj<>6I0S8]%_!et9 ^-onmyofo&LK ď}ϋ'8A _~N],x9jٷeiw .y>3M/P5 3sdTpx S(r ?L=LكK4mYM=]^]X&bnq8؄'_+U|Žyw9Ǫf(݂:nt6l~#S+˻]1,10{ҷͿXv7{E;Dڷ2>&*e-u/Oɮ*Z.D 8@vg@x뱷˔HH;bfXbzB!_eHjMZpZ7ZX'O>1N[;-v3b M\`,E"wGrEe|tUr`k_3]ˣAFJ ! 纜^hwo(e"GF*FЪ;a ɉ4e<J h-r=W*9/y{Ug}CC;k)wxDKߛ{\ #Qȧ `zcd_"@ Xn/ N)$MzGpami@ v><n+@[}?g!"R&F 1vnUvoNBF?EG{5.6kA7$^ eA&,[SȍF5CC@M'idjooDf=*}>լyo2BR_(vS6*^S YDd[ad-@>: DAVs/f>^ᆛg͍*uPY*lN}\ 97N;?׋ހx64s̡p8ߐK?;OT4P\P(85,?>p@ݜo]*̏p_ȍKn4oMGT ^Ok=QES`3>vc8x$}$]a3ޭA+ebQS՘kzM3I%Z$Lw0Om<`3/%WRў\cUN-Mf3&isYs^Z)ґܙ9J<[&`uk2$j>F^L\S:෹^t"҇v'F-sP#,6,|=Ӥ K2șAO1D5`3=4UͲ.>N`mB>ۚ0t۱6Gd#`zii Jm6Y과 W4"]W$f |}BV??WBm#N΢+;?s)EcVB߬=b2reT5Dwg )SVjn⃦dm )uSAjz@~' o̓ؔ&!~ke.ǝ4w339)a`)vݪ7*ܖ/&|a~3W+EO3XN5/T$Jtz`g6 33^l/3|?_^͑8ɶ=zڅVAn@yDMݙ'_S rT+N9IjW @J ,ɫ˃5A>yy:&uQ2tQh k_]wg+P( 7`>JgZۏO`f]ز&ًE:`M*QݕDW.=g5;ʋuwlvCv`}Mf)l.R/oHeW-Q|̧ۚB{*WgA5s[mKi~C%eiN-<2gZڲB}_tZjzHi+JK""Ja&Sc>RXefL|h/nb}D.[6;kRg[Aj NIRx5YYEl՚Ӊh3f50vs`.ǥY_(L۳vM)t6Ulg xcjQ;S0f+g{Z_ʤ\.ʚIOZk9.l \iO&sM[8ŇƖZ-lDP,hSdG}@>8]RS$q{8='Bz@m=U d4VL..G&tk W~<, GI8Ќ`miʭܾqbf98S`&Co}u鼧aֳReI^.4wfѮ6B,*|YK]d^?~'W.UWX=m5NԤH76>ni߯]a.e};(G+w-ǁ;ߐd(( +Ebb\qdٟ>ң"ڋ[zGud/` wkɃu<2Ip;th ҍikirHm|d(.#=kR5f{T߆R2 6PkOS\4%G$Ec+‰}vs^C#D`ԩֆ١ӿcaRwUw(v7Z:j2X^mfSw08CJ/)% m< vITtު0O3ǂ#\ 13g@Hgx{`N}"duu!%L; ro]YF;'vfqR:H-2m%$amefhC3g`vg"w[qv9WGyQSuK:=RS3q[M~k|HHuңy:! !i⁐D1m= aC&/R'! wƁ{*1w@vژ*KYJp[5|kV IBI%b[DKd"贍Y]-7^lh64151zb/4-V@9oY\Sbc(#nhRר:<3IEҺ.ؘenpmI8"1m>K?(skaFv+*zl 9~W5'v :o0')&nx ?/y=ƮN??%[lu^ޗzȝ݂mjʭQ6;qi1īfuZx*\*S(TM+W9u͔CW1l~u+&?VOk%`ͳ7@caFr$zNƗZ:LՈWBff2\hiϦsR\͈ҜVvEeȽDxXMl## .*'ءA{|  Nm9 ׸՝S2_DE.}տ˧f,6h& ʷ0R)r:}d{Tz<<~slnʀwFˆc^f\vvҧw6 V}74# K$$!btDo6y [_${$Zp'HR?dg7' /X7;YIvX`pF'gR>_Jlk}8Γy]U)ϹS~SZ1?f~"hE" 䍷_ z N$+D*7mH^Z*#N:( И,6_:*D -={C`nVYF nszN_{Mժsלxv{8s I)':ozS G<=:鑇^3,7 NQDϡxqU0|鷑s :<3_4(Umu=2e㸛OGM8(ݻq_oHg9;0Jesnz:||a'WqwO^xgGOf.A8K|ot}"2]څ)ݵI LETE@>i@Mϒ2g$!_r<"jt{7ά{ف}*6cY1{e]Н 8bo|hmZl$D פA>tsQ`EZC }K=a~~IiRߵ>Yzf7aPe"Wm6kw_iw?ӯbKpt #i]`7\ub%TQʦvc+7nt9^jZh},|(h_\K6k65sJf2 zCp|)7US5t)k c _h׫nջ@ e⟩>s=O}7eܝ(u 1ھlv^kO(].YmJ:e5oSɼ}IHxᘏyz娆#~CAIb?ɛ[}a>=ފ‹Ӥҧsٽ3˴?=hkύ<eT[4}uӓq 5h9i߹"rMTSv*3]lؘȊ :[iljxޓ"j=>eϫؒ;rf xpwtHkW`Mw6ݐs-l/<.Rnr8eEfd ]Icp֥2'5[X+`V̓iW4w%Dz_g:0+ )Οg;Aq+E] |Un1n姩0^2+IVE]}YFjljk"2q?O{]+hNQr27z_KFU1Q?@IqگvwH?XpDe緜M=oQzWrxN<©ӱúP8:Ͻk顮K8n)j#4.h֞_CR{Ζu]'lv1NAvSEcFܒ|?\,q]Ǹʥ= nL*l;ZCX7:n%K;PXb#><k *ǓoBĦl긏>6>SN1Xz4o@%+m3KwҙmBBiDvJSiE bؗliڻΛ^/yxC{M;ݱܗyH7Oy_N(iC0btf@Wq,Kzi{"ظԩwp*Uw gnyziM&9;Jg4: e[կ*QU,V1Ӕ[H$;h*f)zyT~,e&~EJ5s Q'{׿ T=BL+r=@ H5oSS7oWM6 ]cfwl[٣Ԗx";l'2"VƢ*/zk<\t TtkqD]9۽AJݮOg2em#oF 6LSt,o D[/.۵O~ddW9ӟ۳2&Omc@&8( 6 8 &^d22>L0 *Ȝ/`dPaXd|6@}| S@l@V ;3 [J [H1L)AL6_L v|/- wdJ3z[ϒ*`@,`YrcLOc@ .sP(AUIk Z^& +dePMib%0GK@NKwc4 m}*FTt);cY.#ӭ'DOT;$loi EeXc5%O0PX̌C̔iټ .\(I+k>Gd efvɺ}y37oH|YYI 9u'wBu%_/Ư3c"Qu , &3&sWK㔷|1c86#d3}xvSOPjAsj4=[qxȃ?0]_~7,ܮuP(w:fxrE `9הڟrLOhThqZyu-=&wWIH/Mk- bI^ԦyW{'k=p5'j,m݆$bO祑GϩUB*Ā1K/3*/P&\6'uUuz['Aon]vg>1^Պc n;iC%7%73(+E\&B#ufM#>ҟd1|aqc!1SوPYVOz|XjoZ2XH퀝#:byJ3O"awYSChJ7Qp0ҮF{Z; [z6vָ]M)~d7pAN_ޜlKWb wBxꈷXu4}!]uP=T[_j#S|k_6v!$vyz|cb_ADn~\kZe|^N=fP`]9* 31᧕d(m˷ ZH+)Sbi{3Po⼱Ltr0uz7>Aj\@OgM|Il]d^]gU?M {t/ >Po :=PUQ[ŽIX]J&.H&eOHJ7N6/ctKVۚys^N?w@n檮ɧV LL}YhfY?c%!ѰJwNnHH,`lhcJv<KbD:D Pbb_\:!ƝjkӺ x%l碸T{5nmwꩅ(͎L"Ef^Ll,막Q$Y&5EsW(p֨ Gb0F/buM㜊8B;!:߭Y2eJMjٴ=g-3*mדk2Y6B8XŹ1BJbk XţZ*qTKr`N G2Hϥ+Nך/O"WAkawhr.=|<ϴYg4Y/ɟ$+G#H9+JEipgŘ dGƄ.XpKq3B73:,_,5 #9l um0@;A7'B&*m|wi;h<Ҩh4iݾ0$Ձ{{"k n?Y ]k lo,ݭzu5zm16ZBaID|m6^]nەWc!~&~v.PljS/jFz|WCؿ̣.U~HhMI6|oD7?Lq)0>i=KV\AmsA%hT9 !,Y=p8I!5b:]^/ F<5w7l$cro1fCe 2{]yqOMHolU_p(~]Z [UƋ{.can/ie A¯1 gcA/_E4NnOun_ϝ^z9ˬ<;DD:rvo]^ke 1TV8)}/u a!" =tGk6c$p$Bcouoշ)3?%rQLyv~G>_LB@JKie \\ .Gh r Z1k1((q:(o.J$DDE Sr:O9f%Q–);JF1ES^OK/19ic>XM㜷j1q11WV1PQ\?1Hʢ%%/IST5希77}$d1 KR4;Yz+TFltknŸe[)}4V ¯*cY ؏K3Fe> w7&Dă '7I&7zȦf ~1 ~C|9FɧJ&N/,Knʉa8sdjAٻ[8-b-^Zn|V'X/|( 3!朤1 h Z {[2E!xxx_H sg~cyWs6p~\.@+yEs?a.v}zky95޳ixq3N7MhmyRӟ+Knq;hTnwG~L[kϳq~Z1ڃclUz\;kCx[!7  cC3\|0fs -q#1kgiighVy? >ZP؛:mx7$ K> endobj xref 0 32 0000000000 65535 f 0000000016 00000 n 0000000144 00000 n 0000051617 00000 n 0000000000 00000 f 0000056418 00000 n 0001085563 00000 n 0000051668 00000 n 0000052034 00000 n 0000446586 00000 n 0000056717 00000 n 0000056604 00000 n 0000055034 00000 n 0000055856 00000 n 0000055904 00000 n 0000056488 00000 n 0000056519 00000 n 0000056752 00000 n 0000446659 00000 n 0000447034 00000 n 0000448097 00000 n 0000463363 00000 n 0000528952 00000 n 0000560851 00000 n 0000626440 00000 n 0000692029 00000 n 0000757618 00000 n 0000823207 00000 n 0000888796 00000 n 0000954385 00000 n 0001019974 00000 n 0001085586 00000 n trailer <]>> startxref 1085769 %%EOF FreeRDP-1.0.2/resources/FreeRDP_Logo_Icon.svg000066400000000000000000000151561207112532300206570ustar00rootroot00000000000000 FreeRDP-1.0.2/resources/FreeRDP_OSX.icns000066400000000000000000001664111207112532300176160ustar00rootroot00000000000000icns ic08j jP ftypjp2 jp2 Ojp2hihdrcolr"cdefj jp2cOQ2R \@@HHPHHPHHPHHPHHP iS ]@@HHPHHPHHPHHPHHPS ]@@HHPHHPHHPHHPHHPS ]@@HHPHHPHHPHHPHHPzM#\fRGU [}|d[{/S;[7v]vC_a3z(M#\c`1 2*nT䬸A lŃ"Wf"W9*z0M#\E>ߩ12Ȣ_)*@y4?I^en)t( 4=Bz0O(Νp_Euib,AfbԞc׳ٟ6Nzb!=fJDd[7'OTiϼ}S6H za1ÂXβn;- ;XpWG?y\,+Zp LfϨxHVg_>όM?1nW3W^:H䥷#E4Mg*oCgp_ʃ3˧Lac)_ZIAϼ})0N |4I">Buf:bYQ6 vkm:u"cE)M3>*ߺNɞ%jxc[~Qo zV1Z=,o&ٓm@n"R %vQo$q(Szyyx`CD=mϼ})-,L=I.aӲzOU9x79#[n*ͬ^*M+p6SJgz\D>:e|TȈ*KHq ˰X+ "R)+ӏ a= yQ̹,3;vB*z9@ϼ>6t9o׋W"*\QݳP6 g99͛!-r=$I}HֹTԳxdF Gz\1*G"r_Ca]骸m=laz\ "*Z3y5?ߕ >蠥Oi3nĻuw"_(Rהio0$BnE@4+''NFa#=&!䦉-6,\ZY͸(R84* zUe j7p"h9'l儅D󏣪D̲Pܭ5}H2V2O/06a+w8 oWmefoBϘ"@M. ZkyOА,5lL3%%ѥH(,5kh8DphF)^LF%Ve&S*B.FMU?e[L0tPm>Kr~FK/E+P'k˜U4Y_.̥y2-m#Љ:U2MAcz<ezrOlmϾ}},:Qݦ!{ z|e`L9ؑxciɾ+=05\c& (i^n6(]9/C8YOY ]-^&.Υ_7x [J<;LR(f3>uSF h:I,׭' ~Tj$Ц۹2tJf'''&,ϗƋw\l2ee EYEs-S"8"x~2"1MdFJe:/KE z9R-§A%mT[0;ȯ(mxV0eۋꀵ<9M $l"^a\ %m-ͻE\yȷw1H , yA9N1lSwU]z-.Ͻ>(@)[/K8=Zj^]z VgXcY<$H׽q?o^49uaNedAY}"lj 1?;j0"v`HbYIck䞌uRLT}ee݉8I܃K-f 3O :W.~h5<@JK!-3Gs-gcZT({Fs:BBzckfeb4%E ٶlWbkޡLpJJO"jZ;쵀$>xJPoL#Ӏ?S_NH+i&{:6$(ax 7U6&!WhQDәumϘhdy.=r^M<IaCueƕTkOU¦hmiV] ꒘@K NzJqfyxo25 >H|(nJ jS }m3`%a'j4v]ᴈŧ1mKETN;0 O!k""fy2: ~2 h 7Ѥ )M}MS O<ۤoIvxŗsbХ5Be62L6n[z,QΛ΄g%5X Q[5qxh-DI":bX1WPg[?waM 99@4>^} $چ[JtOxgW0J)?dR[ FV\ 5X5MG鶜`udSn~FyTؐj-[y`;J{}"S*>?rLlVbGLSp?Mtrق> 5'5 FuP– ɲԦ@".}Bަv :VJ_ι]'v:^-lI­~Z^b P5a,Nib}r /|h=;)o嘆;wbݽ|2m5k.vm5pY}P6F@\{qql-CvXy$B-@,0Q7F+*Ll̽;GVa1 != ;K4ݥp}Urʩ ԦZ: 2KOH!je>j*ŏEAG:sȂcI@hxX`/sSaϴTeY՞T0eϛn2jpypx%/;Զh7r&5 )5 40m [C?YQ M+#zĊk[MaVL(}8W@l=dդj}MSYM1>[;gVy]N^ѮO?X?+Jt 35a$B[22O5y2ܽ@yctۢe)v݃AҮ(%ݝ}f孀NZdU/QOW-g5j}oӳUD,B?Ͼ֟}u}iD`Pd<4-zq@g?5VaRv&OYi3BWZ3 h#Cu(+HI=AnzcR )n#49;}Cx#gBph: ENBJzJс/ QW3b.W@2sgCEtQNPL])Q8c ̐uٚ _>(T;4̓5GEszT+"yQ=`o$k ,& jGe˻[vlsD\+RRQ}#ۆ@fVhReθ߮|q .mQ8^y;@L#Uk4(cz[~ 8hNf1?\ K'Z!\> `1d*ukPCeDN{z3yAUz6WVOpwul$?v*en4pNźX!+K 48}ϒ^{Dj*R>XP?)z6P`U?Wm62iy^2`[3dWkuu#}/M\BTR# wԛw̅>NR ElB(ه[#@޹X,MB':5?}ESe& j?}5O[*btPrcuHS_ @93Ph|sw|2Jb+96d+>!U0ϿI\ X`t*hTb%稄;إ} eJt]DŽslv xFJ+c*L@SW\J((e1(6ǫ?h XԂ(crv4ѵy,6' fJ+*?,?Yo݄ɬܚATwH5 Wdr #5G6"WX6BW(_PH(Fc(5hB+6s\lTkRF`9w0ૃDw)*e/&K.y}H#ODX+R"4fN@IRE{cL'O[H.),Ģza5Ej;C5ݫY"R&5'i f3>_c^[1(=a=}RW+^'\_O[70vkookC2dٝq.QDg;fɁgu)RY39BVJ0DcK$wԃOX]J*y"b͡޸ E JǶ&&s!eB<MQ9`ױJ=A`XԮMg4ؾx+8P;OIsz;2[p:FxZa#XXzvdFy-n@y&SVWG|ˈ!x1moJ2At+*I!u]k0!>dI,b<$|+YYTݽLo;U'Q ;s qqvJ8qĿ@J KZJ>27dj{B!e 1?ï \`Ƀ C()NU%“gɬ?toU8ʞ'\gSQ/+ #!jJۜr%6!ଔrJjp; #l)b;2]2Hl(AȨ3 ;LcWBC]tX֊y|i=G4[$.2*ׂc҂'Rp-ܘM-N_,nϨn'^Bm#`);\htC >hTA"k7, #;Pp鼉MTh>X(e޿5ݙv\ȒO35-Z$X`(0%8_"U:j%Kˆ[/mҼrcW9M6Qv`S#Ꙇ[c%VMȾȏ&0N* 復5# nJ sÍZWF,H@zvE,YKdE0" f"w3@i`,gC"8;q\M2^3vNKd2RKxr!}WQ&VVْbAZR򼺎\4켁_F65eE Nl3 O` /]2 D ޣP y%ql"DSrŭ*cai'wPs% %z,Vߙ7W-PȯvD-!ҭ2duhSd PAk<ϐ1ç1-\]L^*X$W8ҰGfc}6lB)S$\\(/qB șDlW+ȹ`%jƇ'ɗC1e#$o;CԆ$Xe^%FcSbS]`Ck8 }oh69 RGI0јUW@6l'Ъړ F΋~1|9v $Jr : Ys|k! YX2ɩë2F >:;ϭ^k!iTF:] 99>2O&ՠ z\&xhާ\:hOh"#c"5S,MbKmeE=)G\] ¶sf8,kf57},ٜP̉C 4 Ӈ<N4DyTN>[GnPdq-TU!6yyZh}$a:r:^gr;j*@tөڠgf,:O &H2F :)Lt+H[rY nб\N=qġ=|9uydk[*1!h[YZp$C5 6 o'*~"QKr'0:uwԎ@ ~U+=a.6msu~8Lu3B#FE1;b~Y'e`3mHy*fEd}9RhLי.F_; oՋ߸bԘ(0jIoٹ@,$Q׼@kqc@ -g:jnrEOXAY8`ܦzUN{h͘>/=\ᥡ~?lDpORwX8Q71u&Q4 ]g-^\6Y/z~lh=N`ҩ2qrc)Ȉq))/ŚlbR7\"TVm</f>Olc Dʄl&h?  údp?ĭwfw4א3 j L_M:s'ɂ wZ=M1Yb$l]WPu@? ٪cŜңT<*p?%cW.eF=xYU&me%σ in *w‣e/r~@a׌T  8PŎϿig߬눏D<)ن!x"v u]xPp5yBeBf]\ d%dKAKHup,꽫dCqR说b8G] f }ZL7;w5ı+fc)-LnIδi;IN߆R?1d6MTOe_>.UCapKEɢ}yi0}xwdg:R$85tώ*;ӗmG1;z/A,ToM $ h|-vUeY";"Wdv+c f[|b+lJF#T3-!bZP-7./4*ou1+ZNHWT-UtHH)Iv;%wJ_NWV{o):}m,0sq%t:-,H'?9&Ԍ Y̟[`h岷rߝ[pGM&ꪞgI5|X`:".h:d 7ۥJPKf3s~0<Pg-u :Q{c%t/R.CRxa h'N#-*a_'jI>Ix1p~v'HIbe+Nmi)B{4Ap SvUU NUi:E1uR@y+Ky*OIL{8U)޽%lPM: # JYBn&E$C9!NפΜC-.ؤ'E*5;:г 99/;MzM8dOeF{ȑ4FW̍\jǿKG$Q\-H[sjGi9ھL;90CB!Ew`KT5E5v>9lOV@&"ά>mw_ݤWsp$bT|iNeF&/wj8bb9z5j_Z %Bwd_^yRH7Ν_cBS|׻hϋ$g"fS_3^6Dh"z /Hou7R?cozMpJ,Fa;{z}>>fmoTiv m\|>K~:-&莌F9zTPZ1I9ʨ,epstxj껫~gVF4;%?ͦq3xM;o8"3rBGrPo.ǡ ,|~lق@R [Ƥe5閕AuM0+7|t10Cs%vAΔ/~ELմI^89N0KMރrXn2Y`Ith^UC\~V`.:h&sp IT3s,XK9(}^*C~Z>Pb4˶+\=OXNoщ'CSVvE:N)xG!SJ[qȉ )ebjesE+[jO22qc'o!jA6Wp !gJ](~H<]^!'"J8&"7 я]4>|E7WDx=YۃAwb2cŸ5pv5uN]sEZB1/vm40u+')@R9-UBflw +S1QN&/x· "+Pwn}Wԧ <\L8;0pGa.Wdv%.yy}ަC{09)Lcfj+7?_lVP^NH^,Wmϫ -aT! 2RF{O-eZr3Tŕ_R Ol*#Bd ^~VC*hCt<ɣA"ioEDw);u1ܭ u6#\a+VNIXD?0]-&LIfGƨ+/^V'9!EH(Y/"?(O 1?\?(~=/&_fb*oKB_Ay,B|E-V;xy;`~SB|H8 8dID"3 kWcuq _ۈdOw./V- l"=\Z ʒ!Y5GVX֤ I4NSԚ֖NYV EJq=Еcޖb8-b0:bs)c+dQ }1*!W?WTXνYPa>\6A1n ,0P= `"D,8R plI@QN [72`^`q2\(͵k<΁V]ˑP|'@m )~KOc#+j_~A9disK+~8qYzHBU`ぶoÇi@M}/2rSHsmnjw q?m"v"L*RDe?Sp?C|N,UWy=ΑΗAw%L{8@r5o/AMIkRFހd- *u6~OgZ gImoJx4*OpyM=>˼M_I0h6d֒:9J̿fj[hUCF× ȆF?W>0qxE䨇90cGE@aFgAF/| ! 30XBpS|޼ʨ&)Ngv"Bc6qp`;ߢ47KӜakZabzKGnHƯ0a#Eq]6*1SrqAUԃ2-39ъwZI12{M (NI3Ӑ:SɦuJ yڂW@xp^ Y8u <]-ڶa9~yW Pi G۲FtTY2’/Ұ>Rn|r=KE5[DD=BNUaAٗX6s5B{eC?CN`x/"_C w"NW[x=Z؅?ߕQkT' -U=B]y@F-V!i4c[yDFQ'o!g1L:>R9'ޭ[=o/fGcՃ/ Qs>!eU)?&wBݗϿP4Ma(]W/7ꡞQ̾d0-*>@`nZ=kKdE P=XH=0PݝV!J%.0< HCli?8a􍔾'P~θD6q\ٕ?F ӕ}jhۓY{iڽ;O^|&.r ec^!(!MBVti3`ڊdmH_33ruݳc*oPݺ/Yhٜ w=4j)r,<(O1}ƆH:8* 5) 17 jf"_b{0E{u[Sg9Z +ٰ)ˆ픢)1QYF7sTPl Y73q=wƿu0}-P7ؑS݅`VXjIfjpOpcCR,DY(|GSi=!t+WZ#E CM,k!!~K>-[>yvX:q.)+-E<^3S#XѠyDt'ڑ̙Z)DxP{V/~`϶oL+%²~m9 5$tU+wBXNRpzwM6`tBۦ7 я]4>|E7WDxPߕz?.ʛu=B[ū -HSy.H,hiZx,7 ߩ-܋)׏8Vwc~~ hQV$ۓQD7Fb8_&!AC;~dҨWp}$jaGMiL ׊r޳ ~L_gfASVcΒ@+qLۘ7'mTk mզs!ƆI:Z۰`U Fl^hg\L'} ŕgq_:{rLvdãR҆g l+ z/ZI]`lA9ƔawtZ*/2\pIR.B1aԎ2bȿp(,gac|tntt&{&Ta~1 k>_>:vYYd F襈qvjGi9ھL;U@q P6k/I@#MrkEB$y{ fOOu4,WS)r\?zU-B^`wԋGC եʒ1d.-hj5)ߌmf]ho[)5?cxVoLMQ"<|vtD"X\<(ÒsEv4IYYFU~\ZXmzibcn.^,ňV5Ev]#>W_FZS lo/g20:hd&PF3*+BFv&дFklPGp ֡NhƙMr1NEu_6u2c܇l)pdjGo7)mbiC#s_ǧv-N[騨de$)Zj(5S?á>ere)~g9Dùd* E1!`͞!g3ORhoa ` p!Q,xM=x+?i<Pitl4l"MyX!ߘ]h eEPG 8s+;p},y8;!Մ/榟'+~~a۬Guyg^пq)vZe4^j"_7/ `(3s ]PiW&Ul$Oud^>>ELL; Ni҂aAɼHU#bo}k-`>k{J RٽtܱKrߓBFz1͚Y ^_#?@Ҿ_Bj >C\~V𛿁:)dx#mq yѢf,BN!oGV0hnyM],+‹7cKeGM gI<'YCb͝&o&\Cf)NneXn:'|tfuO41@EXz>"D%ĔdRr71XlW͋''o!g1L:>R9'ޭ[=o/fGcՃ/ Qs>!eTH/&!I-שǨV+a,W{kW̘u4֐CV$ HDGꩋ:8mj8h˕9`äJױчaLt0͡'ldBA]+h mE]S*[Є\F.8 a <0:޽O>j6"3Gŀ͐7T*>]eu燦}5rfje8CUI.]1?!cW]p0Gǂ$8- `*Mٹ[ |de lI_o+X́[dO< ͮ}ofZ/BUqXu 6fMNkUr_=-#X;jidN|m5bUGtIo+dl_!95uhJU1|*F-^m4`˳㶓k]{S0U*#ndvոI_GYo;Ϯ)#~&9c,[DlcP-S% ?IjhCBfd7 я]4>|E7WDxPߕz?.ʛu=B[ū -HSy.H؅=q ۈ(`7_( ?΀}OylØ"0tWgz#Me?[ypڑ 7Fb8_&!AC;~dҨWp}$jaGMiL ׊mop[ȝnŽ~OD8@T-\~C"U 6ǻ!;AB`U^npcռ:U潋̛4ASjg\L4mn  ;V% ᷌">AޝD+,iv6S4h+ϿCmOSɣ΄$} Dʭu8 Xe9fZJDP5/w!):)Ob''43RC-9٫oDR{Cٌ}A{/RpmM[ۅN 4f`ߜϿCj R#Ɗ ~Ctbk~@#+a:GW+/CwI/g櫢zSqZgR7/RR雥Jc^9"p{0;Zp6L` ӺUW/-vkMt@cZ- aY!sz5[WnR Ug_ UNjƖ){tPB0׀3.ϊ$1GzuZaX&|(DQ9CS`c?`DGo?q2D Ww/qiQT]ܾ/Y|*Uonnз$UI$QaQ>[/ l\5B K::TL/v*KD.EGDD$3ϡ=ޮAԶCAwj$Ď_}W/˶ftWw_cHwvUhL'Z9uPHê~עuF6?ܢs&$(@-L 'v7\WQ짯)_ek} 'م 0ĦQ* I{ \$ ZL`0 xDžzF[fsP&@|WB(Ѐi>X 6TB@C* Es2\C"{oB[{X-yy=]--Q*hR`Y 0 CdKuE,DXY9@6'0KzlݴU[ؿ,(tᘐic(Tأ*0-eIp,CYM]rTb7D|=q$gOlAlnCjיhy/3$yk"7^$ą SaR t,< 46YB.'a ͨ ӹ}`'aS k6$`EU 94Tig},}ngoC1P!P"5U(N$}?w1qFcΙe!z%Fvg~^ Fq\kiDMwsPѴ$31>zahDM5 *o&懘'i0ۺHgdm.:n,Y.vqQqL>R"େ< {M%U85ixv ź @8lZզP=(q>kxJa:OÍ[$ƥ7%?T6 횧H9/N ԓSh =L>|dR2(m:AxEuJ?pjc}u"?KD>TaΦCz!UCY6Hu, 32a<&JTFߑ- ̞Éc]崵@" b`*~K"YeGrSPǮ[efu6.7$;H~H@m k:KҒyQdyYϕħVK_J˔[nGQ08`U0[Ѷw*M!ݵ/7No6R8b[hF.!sN^K[8xP6mۇQ" &E,$bBS_@*jZ iԓL;]NfT75p?2S3j(cxI S04vX(l@(Bf;'G˱5!x[ 7( p9>sw7Lb *†H_ o+RBm =MRG9}q@xl wMmexl+bh9[C՟չ=F{)M\V8GN,^g幱M3_0hd^!AR8;UF16k0N'kb *b3  AWfj=m*1ٷ#mmξZV8>޵BDn';,=kc ][r {dNXJ@XAO[H]5fPAk.k5# 2㱁i ;ɺ?W+{{  ׎P녛a:)O{÷hiTN>ED7=A7z\K >]7D4l1 #6rQ;)s*@J+^f(L0:'_s#Kj`5BSie\?hO)ֵ)$f/lwaJyniX5`\it32JJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJammJOmJSmJWmJ[mJ_mJamJ3mJFmJ emJ)mJNmJBhmJA4mJAYmJAmJADmJA fmJA0mJA[mJA#mJASmJF$mJ]mJ4mJkmJQmJ.mJmJ"]mJ)HmJ04mJ9&mJA mJmJmJNTY^behhlmi``UM@1 mJQ[cjm]C>mJKV`jmJR`kmJKXgmJL[jmJKZjmJUhmJNbmJWkmJLbmJPhmJVkmJZmJ]mJ]mJ]mJJ[mJWmQlmmmmmm^KFMMmmmmLmaF1# )9PimCmiF ,YmeXSYhmmK'`mmh' Immc%<8%6mmcss4mmk Dmm44܆1 ]mmY@z@mm&4@~1Lmm]܆[߀c1 !mm8ԁvDammTCmmfoc,g+mmVg8mmKcmmF mmF%[%mmQ%zP%mm\S @ #mm ܀6mfYS[fmm(Qm kL, [c VmmISOkmi@_$mmi ܓ܀7mV,mm@[T cmF-WcHNmmk>mL,mmXԏkm'kmmD̍cmkmm? ]m3hmmF @<amL$fmmY )sЭs%4imeD& cmnA<>66b66F6p686R66>6j686Z66\676pA6@C6L6hS6DZ6b6l6pw6^6V76FC6F~lV>66R|·ķƷǷȷ˷̷ͷϷȷɷH6ʷF6ʷV6˷6lZVbvF68RR6666r`666 fH9zʻ9F66tq66B~B6ʃ}6\B696tH6āE6f~66{u66>86UwjB6J666|6f86?܏?66TL6`66H֍H66DF6V~66?<66Bn6T:66eɇb6N\86JP6 RٽO68p^:6J]YZSS{SSaƒSSTSlSSZSSTSsSSuSTS]S\Ƅ_SgSnS_tS|SSSwSpTSa_SaĹpZSSlŐŞƠ¥ȿũȽŬȼïȻȹƵȸȷúȶƼȵȴȴȳȲȱȱȯȯȭȬȫcSaSpSStp{ĥaSTmĜlSXȥcSyȥySXȤeShxvhSȣeS`Ԟ]SȣjS[XSȣSspSVȢTS{{SnȡwSs{ScpSȡS[SS_ـSpXSrȡSS_ySSȡiSS]S]SȡSSnS}ȡS·Sv΀SiȠSSSaȟSScXS]SSTȟSShShSS\ȟSShShSScȟSS]ֈ[SX{ĂXSStȟZSSSȟySSS ƣ~cUƹUaȠSSSS^ƐĔ^SŃSuȠ^SUScS_S~ȠSSSSZTSk{\SȠeSSɑĀSSȠTS[[SSnƏgSyƃȠSSc܍cSS_aSpƄȠSS[XSS^Sn…ȡVSS{чxShuTSeȡjS kƞhSTĖwVSeȔih32JJIJIJIJIJIJIJIJIJJIJJIJIIJIIIJJIJJIJJIJIJVllJ\llJYlJ"fllJ/lJTllJjllJBlJjllJKlJ)lI$lI, fllI JLRWYO3* dllIO\flhlIJSdlIOclIJWklIIJ^lIJ`lI]lllkTQCldlgJ87Dal87lB  4ill 71˙1"jll PeK:ll <~89 illhj Sll_.Hlle{)EOlldlkG6ZVlll@LJ)l awv!Tllljal4=ll e$NM\l_16lZIiG7G5MG55J55CN5U5b]5Dg59 odP>85tsuNRt?59o t6YլX5Z 6n5w Va8^_>75;575V78Ri7IŅ7kʃ~nmb O5ALUCp56{ [ppKlC55sǞǞǜtǜeǚcTǚcRhǙcRRǗeRR_ǗiRǖoR{ǖwR_ǖRVǖ |kZǕ€ǕǓǒƓǑǐǐǏǍƫURhl[RVÍNJ Sq۴mRsŌNJ SRNJ pxTuvZċNJTŀRWRNJTRnTljTk~Tljd΅Tŝȓljz jR[dljo_RSlj uτf^RRDžil32JJJJJJJJJSmJUmmJ-_mJ%#mmJ%KmmJ&lmJ*PmmJ03mmJ8%mmJ T^fjlg[TmmJYimJJPfmJTkmUlmmm0mjE)(?gmU4@mg55`mm/i: mm kO`mm dH HUmmk92cm[[Zmmm7'mA#S0mmmj6+emCgmmh^Z^6_6Hd66k66nv66\ kJ6ca}pR\[Gi`V J6EqD k;6kbZ“sɁ`7Mtek^E6QȓȑȑxtȐxSȎySdȎ}SSȍSSȍSSvȍ ´ȍÈȌȋƍȊƏȈȈeSŚ{z…lspbȆwpȆ dS__ȅ XSȄyqƥȅсyTd}ȅŃw`SkȂis32JJJJJOmJ9VmJ8lJ;WmJLVV3TmJK]lmOfmm]2mVJHRmgTmmlkk0im mmjqdmhthmm e]mm'&\mxvPz6omxu[ 獷`RȇȅkDžSȄȄƃȃȂǞsāȁ žþȀ yiich8 yzyUzzyzyyzyzzzzOzzzOzyyzzUzzyzOyzzzzzzzyyzzzyzzzzyOzyzsyOzzzzzyyOzzyyysOzzzzϤsyzyzyzzsOzzzzϥysyzzzzyzОyOzzzzzЫsyOyzzzzzzssOzzzyХysUzyzzzys+yzzzzys+yzyzzyzysOzzyzyssysysysysszzyysysysyssyssysyOzzyysyssysysyssysyssyOzysyssysysssyOysUsysssOzyysysUsyPsysysytsysysyysOzysysytsysysyssysysszsOysysOysyssUsyssysUtyOysUsysyssysUysytyssysUssyssystysOytyOyssOsyssUssyOzsysysysysysyssyssyzz+sysysysysystyOszOsyOsysUsysyϥsysOzsyOszzzysysysytysystys+ysysyssyϥsyssysUssyOsysysOssyssUsϥϥysUssyszsysysysysUsysyzzOФszsyssUssyOsysOsysszssVzsyOysysysysysyOsysysyyzzsytOysyOtyssys+sysUsszzyssysszsysUsyOOyssysytVzysysyOsyssysysNsOysyOs+tyssUsyszzsyszsysyssysyszzzzyssyOsysyVzsyyszssОssyssysyssyɀO+zssysOysyϬysyicl8yzzOzyzzzyyyzOzzzzzyzzy+zzzysyzzOzzyzȥsyzzzЀszzzzϫsOzzzϞszzzϤyOzzzyϥsOyzzyzsysyzsUzyyssssysysyOOsysyysysOyssysyzsyssUssUssysyssyOsysyszssyszOsyOysssysOyssUsyssysyssys++sysysyssysUsysOysysyssytzsyssyszsOzysyOyϤVVzysOysysysOOssyszssyssysysOsyOsyϥzysyOyssyssysyyVzssOyssyOyysssysysyszzOzsssUss+OsyssХyOysyssOUsysysϥysics8yzyOyzzzzzOyzzzzNzzzzyzysysssOysyssUsyOOysysysysysszzssysVyszzysyss+syzVysyOyssyzyszicl4o}o}}o}}}}}}}׿}~|}~~o~w}}}w}}~g}|}}}}}}||ǿ|||||ǿ}|||||ǿ|||~}ލ|||}~|||||} ||||| }||||| }||||| ||vics4׿}}}}}}ǿ||ǿ~|ǿ||| oich#H?Կ-V?*ԫ?QWU*UeI*U)TQ)ESUd"$ ?Q!!($_%(/B(!#J'FBAL+I=%X5 D" q????ICN#U ?U$/!GHKCRQ,)f?*?䍄? B??ics#HOҗ'7????t8mk@X۰Tp@<(< # 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. """ tool to preconvert an icon file to a x11 property as expected by ewm hints spec: width, length, [argb pixels] """ import PIL import PIL.Image import os import sys def usage(): print "convert_to_ewm_prop " return 1 def main(argv): if len(argv) != 3: return usage() im = PIL.Image.open(argv[1]) fp = open(argv[2], 'w') var_name = os.path.basename(argv[2]) if var_name.endswith('.h'): var_name = var_name[:-2] fp.write("static unsigned long %s_prop [] = {\n" % var_name) fp.write(" %d, %d\n" % im.size) i = 0 for pixel in im.getdata(): r,g,b,a = pixel pixel = b pixel |= g << 8 pixel |= r << 16 pixel |= a << 24 fp.write(" , %du" % pixel) i += 1 if i % 8 == 0: fp.write("\n") fp.write("};\n") if __name__ == '__main__': sys.exit(main(sys.argv)) FreeRDP-1.0.2/server/000077500000000000000000000000001207112532300142435ustar00rootroot00000000000000FreeRDP-1.0.2/server/CMakeLists.txt000066400000000000000000000016751207112532300170140ustar00rootroot00000000000000# FreeRDP: A Remote Desktop Protocol Client # FreeRDP Servers # # Copyright 2011 O.S. Systems Software Ltda. # Copyright 2011 Otavio Salvador # Copyright 2011 Marc-Andre Moreau # # 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. # Servers if(NOT WIN32) # Build Test Server add_subdirectory(test) # Build X11 Server find_suggested_package(X11) if(WITH_X11) add_subdirectory(X11) endif() endif() FreeRDP-1.0.2/server/X11/000077500000000000000000000000001207112532300146145ustar00rootroot00000000000000FreeRDP-1.0.2/server/X11/CMakeLists.txt000066400000000000000000000042331207112532300173560ustar00rootroot00000000000000# FreeRDP: A Remote Desktop Protocol Client # FreeRDP X11 Server cmake build script # # Copyright 2011 O.S. Systems Software Ltda. # Copyright 2011 Otavio Salvador # Copyright 2011 Marc-Andre Moreau # # 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. include_directories(${X11_INCLUDE_DIRS}) add_executable(xfreerdp-server xf_peer.c xf_event.c xf_input.c xf_encode.c xfreerdp.c) find_suggested_package(XShm) if(WITH_XSHM) add_definitions(-DWITH_XSHM) include_directories(${XSHM_INCLUDE_DIRS}) endif() find_suggested_package(Xext) if(WITH_XEXT) add_definitions(-DWITH_XEXT) include_directories(${XEXT_INCLUDE_DIRS}) target_link_libraries(xfreerdp-server ${XEXT_LIBRARIES}) endif() find_suggested_package(Xdamage) if(WITH_XDAMAGE) add_definitions(-DWITH_XDAMAGE) include_directories(${XDAMAGE_INCLUDE_DIRS}) target_link_libraries(xfreerdp-server ${XDAMAGE_LIBRARIES}) endif() find_suggested_package(Xfixes) if(WITH_XFIXES) add_definitions(-DWITH_XFIXES) include_directories(${XFIXES_INCLUDE_DIRS}) target_link_libraries(xfreerdp-server ${XFIXES_LIBRARIES}) endif() find_suggested_package(XTest) if(WITH_XTEST) add_definitions(-DWITH_XTEST) include_directories(${XTEST_INCLUDE_DIRS}) target_link_libraries(xfreerdp-server ${XTEST_LIBRARIES}) endif() target_link_libraries(xfreerdp-server freerdp-core) target_link_libraries(xfreerdp-server freerdp-codec) target_link_libraries(xfreerdp-server freerdp-utils) target_link_libraries(xfreerdp-server freerdp-gdi) target_link_libraries(xfreerdp-server freerdp-kbd) target_link_libraries(xfreerdp-server ${X11_LIBRARIES}) FreeRDP-1.0.2/server/X11/rfx_test.pcap000066400000000000000000036272041207112532300173350ustar00rootroot00000000000000ò''  ʬ @((  GQP@,ffw,  ''@  ̛QP@`ffw,  ,  ,  ,  ,  ,  ,  ,  ,  ,   ,   ,   ,   ,   ,  ,  ,  ,  ,  ,  ,  ,  ,  ,  ,  ,   ,   ,   ,   ,   ,  ,  ,  ,  ,  ,  ,  ,  ,  ,  ,  ,   ,   ,   ,   ,   ,  ,  ,  ,  ,  ,  ,  ,  ,  ,  ,  ,   ,   ,   ,   ,   ,  ,  ,  ,  ,  ,  ,  ,  ,  ,  ,  ,   ,   ,   ,   ,   ,  ,  ,  ,  ,  ,  ,  ,  ,  ,  ,  ,   ,   ,   ,   ,   ,  ,  `  ̛QP@`ffw,  ,  ,  ,  ,  ,  ,  ,  ,  ,   ,   ,   ,   ,   ,  ,  ,  ,  ,  ,  ,  ,  ,  ,  ,  ,   ,   ,   ,   ,   ,  ,  ,  ,  ,  ,  ,  ,  ,  ,  ,  ,   ,   ,   ,   ,   ,  ,  ,  ,  ,  ,  ,  ,  ,  ,  ,  ,   ,   ,   ,   ,   ,  ,  ,  ,  ,  ,  ,  ,  ,  ,  ,  ,   ,   ,   ,   ,   ,  ,  ,  ,  ,  ,  ,  ,  ,  ,  ,  ,   ,   ,   ,   ,   ,  ,  p QP@ffw,  ,  ,  ,  ,  ,  ,  ,  ,  ,   ,   ,   ,   ,   ,  ,  pp  ̛QP@`ffw,  ,  ,  ,  ,  ,  ,  ,  ,  ,   ,   ,   ,   ,   ,  ,  ,  ,  ,  ,  ,  ,  ,  ,  ,  ,   ,   ,   ,   ,   ,  ,  ,  ,  ,  ,  ,  ,  ,  ,  ,  ,   ,   ,   ,   ,   ,  ,  ,  ,  ,  ,  ,  ,  ,  ,  ,  ,   ,   ,   ,   ,   ,  ,  ,  ,  ,  ,  ,  ,  ,  ,  ,  ,   ,   ,   ,   ,   ,  ,  ,  ,  ,  ,  ,  ,  ,  ,  ,  ,   ,   ,   ,   ,   ,  ,  I  ̛QP@`ffw,  ,  ,  ,  ,  ,  ,  ,  ,  ,   ,   ,   ,   ,   ,  ,  ,  ,  ,  ,  ,  ,  ,  ,  ,  ,   ,   ,   ,   ,   ,  ,  ,  ,  ,  ,  ,  ,  ,  ,  ,  ,   ,   ,   ,   ,   ,  ,  ,  ,  ,  ,  ,  ,  ,  ,  ,  ,   ,   ,   ,   ,   ,  ,  ,  ,  ,  ,  ,  ,  ,  ,  ,  ,   ,   ,   ,   ,   ,  ,  ,  ,  ,  ,  ,  ,  ,  ,  ,  ,   ,   ,   ,   ,   ,  ,  I QP@ffw,  ,  ,  ,  ,  ,  ,  ,  ,  ,   ,   ,   ,   ,   ,  ,  II >> ( QP@`ffw.  #.  #.  #.  #.  #.  #.  #.  #.  #.  #.  #.  #.  #.  #.  #.  #.  #.  #.  #.  #.  #.  #.  #.  #.  #.   #.   #.   #.   #.   #.  #.  #.  #.  #.  #.  #.  #.  #.  #.  #.  #.   #.   #.   #.   #.   #.  #.  #.  #.  #.  #.  #.  #.  #.  #.  #.  #.   #.   #.   #.   #.   #.  #.  #.  #.  #.  #.  #.  #.  #.  #.  #.  #.   #.   #.   #.   #.   #.  #.  #O@F|``s9cf6>';$(QJ$x|X,`X,,X#` @`` Ĉ ?O@F|``s9cf6>';$(QJ$x|X,`X,,X#` @`` Ĉ ?O@F|``s9cf6>';$(QJ$x|X,`X,,X#` @`` Ĉ ?O@F|``s9cf6>';$(QJ$x|X,`X,,X#` @`` Ĉ ?O@F|``s9cf6>';$(QJ$x|X,`X,,X#` @`` Ĉ ?O@F|``s9cf6>';$(QJ$x|X,`X,,X#` @`` Ĉ ?O@F|``s9cf6>';$(QJ$x|X,`X,,X#` @`` Ĉ ?O@F|``s9cf6>';$(QJ$x|X,`X,,X#` @`` Ĉ ?O@F|``s9cf6>';$(QJ$x|X,`X,,X#` @`` Ĉ ? O@F|``s9cf6>';$(QJ$x|X,`X,,X#` @`` Ĉ ? O@F|``s9cf6>';$(QJ$x|X,`X,,X#` @`` Ĉ ? O@F|``s9cf6>';$(QJ$x|X,`X,,X#` @`` Ĉ ? O@F|``s9cf6>';$(QJ$x|X,`X,,X#` @`` Ĉ ? O@F|``s9cf6>';$(QJ$x|X,`X,,X#` @`` Ĉ ?O@F|``s9cf6>';$(QJ$x|X,`X,,X#` @`` Ĉ ?O@F|``s9cf6>';$(QJ$x|X,`X,,X#` @`` Ĉ ?P4x8x8 b8 58QP@`8ffw.  #.  #.  #.  #.  #.  #.  #.  #.  #.  #.  #.  #.  #.  #.  #.  #.  #.  #.  #.  #.  #.  #.  #.  #.  #.   #.   #.   #.   #.   #.  #.  #.  #.  #.  #.  #.  #.  #.  #.  #.  #.   #.   #.   #.   #.   #.  #.  #.  #.  #.  #.  #.  #.  #.  #.  #.  #.   #.   #.   #.   #.   #.  #.  #.  #.  #.  #.  #.  #.  #@ce+@!x&Ο`d@$=le%MUAM0.ȈIpɅ%e @tooB- QĉWୄ3ýGS D&D j 'p ІP\` - h1``lx`4 anС( S٠ Ї*@Th( ѧx@L|{4 Gs4=)Q2@mP`&%HX @ IP!Ԁ%Ē(P8j @>EBPx =UH9 I.Bƨi WA Uf]1&,@ h(툀hA!8as$ 8] -K $hOOp9QT,HH%@HPo.  #.  #.   #.   #.   #.   #.   #.  #.  #O@F|``s9cf6>';$(QJ$x|X,`X,,X#` @`` Ĉ ?O@F|``s9cf6>';$(QJ$x|X,`X,,X#` @`` Ĉ ?O@F|``s9cf6>';$(QJ$x|X,`X,,X#` @`` Ĉ ?O@F|``s9cf6>';$(QJ$x|X,`X,,X#` @`` Ĉ ?O@F|``s9cf6>';$(QJ$x|X,`X,,X#` @`` Ĉ ?O@F|``s9cf6>';$(QJ$x|X,`X,,X#` @`` Ĉ ? &&2?@ `vV{1 Ab7A$‚==OH0IדE==](MQ`($6UW@bB ap?ԁ9! Q+XqX,E%$@ψ!@gNp|ԝ g!=OcCKzc`0܁9+I[whE] |@Pdˆ@.' R⑀0jSXB`BH @%08R{N(c@JE;jXT_B hɕPi3`"Enr2߳"Op\a!@3*gJ0p`as1'd'rNIP F!tu@n;a Gь& {A;!k4𥃠qq 1;*1@@S ut] P?6Xj{i=` H'eH`;+~L֓QF" gx!I ` z}q\eXx.rȡD]U_z5g]辑KPJ\*3 ~t q!ZǀwɂAuIBA.(b8;!CjZP> J%,'J?K(ڙ 0D B) H{(t5yR 6t,KdY,J(0 j@ aQ?< ٌ9=h~rQ_a|@ld `nSPM;B T@_!:e<K{k=8sk\P ,X[Ld,pܔ|j.7!FGC@ȆY"*Xwxב.'Rf"@ [Z1`mTۭePPʹ8SUUGudY¥c}ֵkW28ư Iaw)x_*N6mkK2Ҝ\:rڥw.(L']8c[cJg4E(,\CfqBSL+@AHβA+2lzV@'>At8rl?MbjYA=^$z9b_}@|Q$ @* Gv8Ȑ6Ð  ID*:(ӈ6A0 vxP 1M#(G+}Z?𹳙f I͜z37b)QƳWe̳=L7 m]Hv٦`\ł ̗ޓH) Ĉ<1VIF84 =>fsrBLz2bc@K;$,,]XQ@_`s03d̞d'8N2qs N1  !yK82I,2ryit>_I ",J"ЉCs4ݧH$>LP-/W?_Ȟ$J z'a 1 0g11' z5#= ]>FV5#l:zOsu>ybA>h3m[,Ē!>iuM@^&G]pTbnpLl})2U`[H}CoTп1EJ LX#L{( ~(.Ku=H@H%R oa>s)q ( q1,a'19'$䘒01ڿh( |.\pd[eԄH LGDE4rc1Faf#"FAَ}$H*8GfH;B8Ґ tXbn,t>LH|Adpp-ea͟ ѵ;kP;Se)8c0 ĖC4M]gZ;h Q88vyҔEnAE4) ͎"jb-銱X: [jiNZV5sSZK(Vl3^ TP-"]!@)j`pۊe2q@B(X]J(g|$"h  QJN"</Hb!,L/"ֺzk#MA˜c]]0tC,].K%dY*#@f)% )Vyo̧4|T7UۈFVN_Ȉ_d P`B Z^`iB' 8M|4sP0rBj@< ChQ1@ 44h[造H,a#DFhGb<"JSiRFﯥn1&P (0E Y!o~{D)~ѤDbD4dqg@h+hӼ{aGi;!qDp)*CHJ Qq&G,tB-QI'*~ /RzK+[iʽf:SKW\r>oDP׭HU1,@ $>޾CI N?M0; 4=@UH E$j 3fW͏@ 'THHG9*Z+wGp" h%Łз_8]>hkk0 8%ٷg%`(YA*Pr7:ŋ/0F"@@q0BlE&W1t"˻|NpEV$_9X-' s2V*3 I8?+F1<VF 9y 'g-7C2$D`@܄cz_#r I Ѵ 0H4KFJAY(P<ՕV`Mf-C#wEH}+~3$sj G_NiIDg}x'aAi@! X>QlI1A) =.I#1=J$z|5$.!@6ܨTC#%LP2O*6|Ak^¸+kn$n)$|a ,K8s3Pq4cN4~[@/tY,K%D "hke< plMn*ЪRaFih8,A=7Gͮ_iF'u4:fQ@)a1b_Ϗ0$+ C:#j 4F~~!H Xtx P"I)%M QlQ3 ?SXZPuf/עBPxQ`B.#Z_vJdn^%X*ÞAOX1}A_R#b05 } !Ht"/T 4vLi`v(\3 FCUL({JQ)\@)t+ܝw`, abŗGxF#@ @3 B&lDÊ+fS'3\-gePlŽ@W z C$Q>}S(WDuB W$H}\|`F a0#_e06nyAF@D/O-_7[3Jv(OzgԎV1@ A)mtGES2y% UAM2L0!P SRޟP弟Ob]VH{-Yj)Ж$]+;Fhr}03XSb|0j.F(X+f\c3f& b8>Gzd{f t.H``͜ 4>&P f g Ad%9Gł:?4ouǃ"0e$SV0U0dPa10c01l}O2y̜d'8N2`x 5a]6jWVG 0#]i\h46@h^u3_Jϲ!:> 0;GSa>0.- ZE .[Q/9 G3z011T|O=@$(PL@a؍?`(pI  A N'E$F|I _ذR(F  j$cD?D541PP_W%5w0{@x !fz_h R1ve0:읅$HF% `&HA4cIj٪dqkU5cA PȊRlk|Gۀ(*kQm 9=J݀ X!t(Sӈ!^` 8A n}l0Iaii/gxPT`(Uay* ow~`abŗG` D"@T#&!&4" Zv0RDA!!A+'@(իB҄O:E1|0fZ/Ni<-x}l(,1HQSo0';$(QJ$x|X,`X,,X#` @`` Ĉ ? O@F|``s9cf6>';$(QJ$x|X,`X,,X#` @`` Ĉ ? O@F|``s9cf6>';$(QJ$x|X,`X,,X#` @`` Ĉ ? O@F|``s9cf6>';$(QJ$x|X,`X,,X#` @`` Ĉ ?O@F|``s9cf6>';$(QJ$x|X,`X,,X#` @`` Ĉ ?O@F|``s9cf6>';$(QJ$x|X,`X,,X#` @`` Ĉ ?`[nn X +QP@ffwSFEd 2 DDHW´VR*EH"@ Ì `1cll}`L{w gx3@gn,O @( ABa0H$ $8j@d@2 ehpǹ@xq,@hCF5>>:tӧN+,``, Ŗ_1j @ A(J$SFEd 2 DDHW´VR*EH"@ Ì `1cll}`L{w gx3@gn,O @( ABa0H$ $8j@d@2 ehpǹ@xq,@hCF5>>:tӧN+,``, Ŗ_1j @ A(J$SFEd 2 DDHW´VR*EH"@ Ì `1cll}`L{w gx3@gn,O @( ABa0H$ $8j@d@2 ehpǹ@xq,@hCF5>>:tӧN+,``, Ŗ_1j @ A(J$SFEd 2 DDHW´VR*EH"@ Ì `1cll}`L{w gx3@gn,O @( ABa0H$ $8j@d@2 ehpǹ@xq,@hCF5>>:tӧN+,``, Ŗ_1j @ A(J$SFEd 2 DDHW´VR*EH"@ Ì `1cll}`L{w gx3@gn,O @( ABa0H$ $8j@d@2 ehpǹ@xq,@hCF5>>:tӧN+,``, Ŗ_1j @ A(J$SFEd 2 DDHW´VR*EH"@ Ì `1cll}`L{w gx3@gn,O @( ABa0H$ $8j@d@2 ehpǹ@xq,@hCF5>>:tӧN+,``, Ŗ_1j @ A(J$SFEd 2 DDHW´VR*EH"@ Ì `1cll}`L{w gx3@gn,O @( ABa0H$ $8j@d@2 ehpǹ@xq,@hCF5>>:tӧN+,``, Ŗ_1j @ A(J$SFEd 2 DDHW´VR*EH"@ Ì `1cll}`L{w gx3@gn,O @( ABa0H$ $8j@d@2 ehpǹ@xq,@hCF5>>:tӧN+,``, Ŗ_1j @ A(J$SFEd 2 DDHW´VR*EH"@ Ì `1cll}`L{w gx3@gn,O @( ABa0H$ $8j@d@2 ehpǹ@xq,@hCF5>>:tӧN+,``, Ŗ_1j @ A(J$ SFEd 2 DDHW´VR*EH"@ Ì `1cll}`L{w gx3@gn,O @( ABa0H$ $8j@d@2 ehpǹ@xq,@hCF5>>:tӧN+,``, Ŗ_1j @ A(J$ SFEd 2 DDHW´VR*EH"@ Ì `1cll}`L{w gx3@gn,O @( ABa0H$ $8j@d@2 ehpǹ@xq,@hCF5>>:tӧN+,``, Ŗ_1j @ A(J$ SFEd 2 DDHW´VR*EH"@ Ì `1cll}`L{w gx3@gn,O @( ABa0H$ $8j@d@2 ehpǹ@xq,@hCF5>>:tӧN+,``, Ŗ_1j @ A(J$ SFEd 2 DDHW´VR*EH"@ Ì `1cll}`L{w gx3@gn,O @( ABa0H$ $8j@d@2 ehpǹ@xq,@hCF5>>:tӧN+,``, Ŗ_1j @ A(J$ SFEd 2 DDHW´VR*EH"@ Ì `1cll}`L{w gx3@gn,O @( ABa0H$ $8j@d@2 ehpǹ@xq,@hCF5>>:tӧN+,``, Ŗ_1j @ A(J$SFEd 2 DDHW´VR*EH"@ Ì `1cll}`L{w gx3@gn,O @( ABa0H$ $8j@d@2 ehpǹ@xq,@hCF5>>:tӧN+,``, Ŗ_1j @ A(J$SFEd 2 DDHW´VR*EH"@ Ì `1cll}`L{w gx3@gn,O @( ABa0H$ $8j@d@2 ehpǹ@xq,@hCF5>>:tӧN+,``, Ŗ_1j @ A(J$`[pp>>>Bb $( $QP@ffwʳMzIcn>E#wg` OZC@ dThlc Li>0uo9 ď<͕ ؁S@ ֖Ϧ/`Cr)һ O;t3Y8Pғ_(0)M1b8qDW}+#ʋp@@p;Q+bҠK#RxaQX$J,B1?eF `c7B&`eyىXB$! Z+EH"TR*E*#!Cn,СcD=P, W!C)D+B@.(8d^-k2@ W.Y76]C1 fzؾvGdYD2(Qqg9N 80LL]A=(GLm)jE\r6iQ>J$@ o݈:3\1e@Q_E-mLZbH"I$B`#bBC?WM;VKl{p0"6Itoz7_dNkM-gR.y˯p )D_V3GVvE' \jDHM)?eywY'$'=G(2 P`%>kk* 3{P05O" .C%m=?c34Y\^TYi/QQ$xpbh E'* "Q^R~1`j-R(YN#%ÇP!c`B_0L$ A D`Ti$b\(<BAYCəVbat\UD`F/|dF _AddL'pj5 %`I`b+1><2q`ES@MvO#AHpg2IUG w$#ݺGӚ >g~yrVI 8B!p" @qN~_##ayAڋtA ne DHy&M*)ZGX0cJc v( ֢Jo~;G(,HX I9@4 1ȡo !PQz9~{l^Ѹ ,v}:DPJ#XP^<dP`P*0iž)Ÿ abƚߟ:tӧN7 J( Vc%E!(*<.ui Y(+k0_=D}0Ɖ 7i,dafJ})-?"'e9^Ex*NZ̖'='rNI1%r$PBPG%L  z_G&B /ȵN*F_t *|!裄KHP?ptXQ롔23a]?^DRm@J~14 yTdːJ*_]{,ApʫH!=!!^!) ~gH]!G! ۛ$M-W;*'bku圧ךO hhV1FAyl`fnިDuLeY]fZ5O?1gBl41- +h (?`]GS_eY} uNŒ3C}[L,)5h nd؇8: mh@P5Y0Da3*do-^[@9KUCBrѠD@g'20I H$""G´VR*EH"TJHAABQW."8Ǒ|$ 6}5^KpNP ǐs L*|5 '$nKE7;A8Nؑ0ihij"`T )@T ^9REW{SҸN]P tKI֧5DG -mlZb^DI$ qx>v7X ȽաAaC N1SN";f/͚ ,ExU;PPȬAjo%f,h 3Hr󗜼*4Y9-n\RA%F|vSX>&GXkiNl9900\J42F 6 ""˸HrcrdRO#Yԗӈ]5nPlwP&+AW ɕ*PkE>YHqj@ML ,"p*1fJ kPyRgĖv kBuɠB0Pȏf`B"MusAJ@< gf/Lf|֕cD)D )SlB!bS6a#bwq],S#xQlGER?ĢP{*+='$䜓bJ$HB1 R OJ?cjF.mJH->'rއT8 TU{/j;P n|>TU%sUNѝ5G]e? ʂb|\>~/__x~ @d !Dt:< i =g5 V?G#'``}& 䁀 LT /#=%?~\`|ot r@G@?]ms q6D .Evw .E4huH<0â4hJC`O nBw7hn  "757@P=>ZA@jߴ~p  06 6( ʬ @((  6(wQP@\ffw\_  ¯,G6΅7t2j % (hR')#/@t $`n\`lMć(&& EC!'`tCJ~I 56_2jK@zF$;Я$DC q) E"^"F5Q i90D =xC5((!`$kE Vf@u Q+LZw` < O@QS %pIQlYETH"PJWzt}y?>b?Xt$$=K"Y;D% 'F0ҀcCB !AC) "L H * _HIh}$I x ?@t5h6`>4LɎ7Ppuzsue)nM )'w$D( <1# ; h{'k w?2L$I%QXB ebGQUqF"Pffff<" pQ5ǀRbt<sXf'}`Iz'^|A%X+@BeTPrft;G7@k@1' 8ـ|IaCm*g(Dș5 L  b12)0p S¸ъJjS6[CS1}<@Zw(iXy}U ԍ+Lb 7 @\ ai (-$׀R7&o`Ҭ(<5Lwe)iB}0 "*S@h RJFҡāJ=CCA#GJGO'\GGG1`DiO€!D記,G,XB %g `3'A)lUE/uxHL>o0^0 /aȀ(P,BIB1b %s ߲`$į )Ȁ28X#Q鰉?$U T`1FUТj݂((PV}5.ob;WeArFB?+e@ DHd!`*+(#p_<\ @ ?$l%Z7Hȇ@\o EI>h{EAZ @!R,Y4)Mv@[!wD!)/BpjFDrԯ;.kƊV:EpJ Ozd8&-]H: lpn ( }2BTKi< ^+S^@ #8Ą P),Ę3 & k~B`I)1c 3Ɍf]."$GP*)+!Cpd 8[xACB:B_,AgU!p!!`(߯ՌC?㼁.@@BEHCS(n ) Vg& A^L-h. $ & Y߰Dg|+.Q}>U\H~!' Ȣ65HCD? :p:|YfAPY5| X4r~ב)Ǐ  MlPA@ 0 0 06 6(6(wQP@\ffw\_  ¯,G6΅7t2j % (hR')#/@t $`n\`lMć(&& EC!'`tCJ~I 56_2jK@zF$;Я$DC q) E"^"F5Q i90D =xC5((!`$kE Vf@u Q+LZw` < O@QS %pIQlYETH"PJWzt}y?>b?Xt$$=K"Y;D% 'F0ҀcCB !AC) "L H * _HIh}$I x ?@t5h6`>4LɎ7Ppuzsue)nM )'w$D( <1# ; h{'k w?2L$I%QXB ebGQUqF"Pffff<" pQ5ǀRbt<sXf'}`Iz'^|A%X+@BeTPrft;G7@k@1' 8ـ|IaCm*g(Dș5 L  b12)0p S¸ъJjS6[CS1}<@Zw(iXy}U ԍ+Lb 7 @\ ai (-$׀R7&o`Ҭ(<5Lwe)iB}0 "*S@h RJFҡāJ=CCA#GJGO'\GGG1`DiO€!D記,G,XB %g `3'A)lUE/uxHL>o0^0 /aȀ(P,BIB1b %s ߲`$į )Ȁ28X#Q鰉?$U T`1FUТj݂((PV}5.ob;WeArFB?+e@ DHd!`*+(#p_<\ @ ?$l%Z7Hȇ@\o EI>h{EAZ @!R,Y4)Mv@[!wD!)/BpjFDrԯ;.kƊV:EpJ Ozd8&-]H: lpn ( }2BTKi< ^+S^@ #8Ą P),Ę3 & k~B`I)1c 3Ɍf]."$GP*)+!Cpd 8[xACB:B_,AgU!p!!`(߯ՌC?㼁.@@BEHCS(n ) Vg& A^L-h. $ & Y߰Dg|+.Q}>U\H~!' Ȣ65HCD? :p:|YfAPY5| X4r~ב)Ǐ  MlPA@p vIQP@`.ffw: өl}yc|g < 0(!_dWg Xl=XmS#Za0F!bzCܴ:"VR _#Rn ݤ fRBk$(Q B ?Hf@CE6Kf i8~AB( = LJ8%U;8hTPAlFcȀr]YBDT ,,#Pl+ tޑ&Y&,0IH !~c*& P Z_ "8 N ED{ PPB1$w-/vrC0P11N"(\؅)T jxIa$YP6y"1  k~ ðߡ_JmyNz7)-24G$(MȵCUAG~PH5@Fe0 a ڈf fH(KxƢhW@s6Qa?魹+λZ~aKrƋPE%bOiB2ʅLPԼFvJ>#]o*bEТKW%]:(QhAxPj$RP2 R+E)z,FX # ߎ~%@ X `'1k/  E78u(l`acJBj9!p`96H2+F|3DAB_zL?zvX[pya 8@Mu@)h^,;b8a@qa@t!€wct~X+^נ hc^i(:d#&Z C0z@P,|=U,9I 4#@J`cl@GF( J$<#O-LΒBʄd".NJd@sy0s'|"!/ev]131`L bo fhŤ@i%CR &: @Dt z 4|z,-BZ(?# nQFh4:Hh~`6}Y~_$jl/T!D\@Z(QMfQEyLL%F'?BBJh^ PTzxLj|.tpTSFVD D Ỵ0YWa3zP f&6hjj̠ ZP@ 8h\%"|L @BTI=T3RO.w !!B`OߴwN #șR L"0&J̈́WIR`pGk/?(}XXk L[=\TE\,!aq`IG b`f*8N`' ,D4d4ēADK"brR BA`K`!8 !P )CUHQ  PL\d, @DE% k "  PaB(*1J𜾖Jo "`N h  @(@bB&Pq*W   @$  #?g%`!,D+$&P@Q_0P" d hz $#P(F",1IUO a@hJ$A0(RBcd@! <0b!JZ aP"H)(ZRQ@,@, J( a "`@{&" S@A@P%Ce^G*,Wp PA @@$W `T",o%@PDJJIE~ͦ@H  % PDpP1(F*"0Hq`m #H/ #\QA$:@ F""WA @$  <0XY @А E b"P)! @( NV`0 O @ʍ 1(!L@;8p wd. <A PTĥ?%%1м3 K´w$xI2}"E)K!koFw@<PctUb1Nj0-@6Y2r`QkւH(x 3(` $H_`¤ Z}ߣ02$GV4r?^NrDh+4*n?F  ?zO( Qsކԏ%RtXP aB n M&7ɣ%ZQ A| "$Wi_Jbq"4c\0-JF@a" 5[ramy7cG2apӜWF8F@0QљNZh ,o B>L>%B'gx`d4RrT_e's@q2 - gS0E`c *U -?L 2Qrc,5 $?.\ %@|L =bbM!GG!z;u/B+AD )=k"+5efI <ÑJa5ZT I axWy7XǙ`ygLl8 8,b>f/Ӭ @P r9pCIVê >P]ԃ 8@D4D( &@i R %ZW\#9" V?CÑ@z2Ҥyg&l;Xik(z(%qu0dҵ -mq(f Lx&"EL0Jwo5$JB< CCa*%Cx>!`$T6qޠHp+C$X jXb1 t!x`EP P @NXτq&K >\w@hBmkx@d4DC! F,ᑨ@uGq"HŜ.I9'9Vs)X)KV{ YԬB-VJR^Z)b$`ykF#Qs'f*8iTQY+31/@ B$ (t-2,&r)T=~d s(B5u "XF@@ &,h-9n ;N/FC0! n|I6Pmb X~䓻׬<06,P]Z4yFĖQ>/1z&(?7qkj!A\! u>,x} ]?@ p怠>B#8g?Nn;5PF*j24 E!F  S砒(dI-HpZf Oˑ@R %"I|@Wzvv'aYEA%9)Cj@u:[@Pό%^ rcXLHWa"DJ# s 1 # Za0\2yGмLҤa(94$_~D!`@AA1 (ml0NG.V"r 9|@    J٠8E w`sir%(bO  h-t!@PТPAIB_D^~9{5&H_), l(P(@EJ_(x^?@)ЀL/" S:Ӻ ЙVz?P <<@|^B.B">DB _">D9P9@F2w)E`<S,:xLSry  RDD61Ο/dd| p'P(Q He*TWy?lL  `@fAHPpa@JA$ @M#@r&#H 8 a \0pP!EP~XMP  R   DP)(&P6j  0%94RNWU8P< # ł"$,S? P & t#" @b A$)YW;M$H @$0A` H@B $Bee "HA 0p㘂W섀AhB`xYAa`@@K ? ~ ZlC@dKNSLIA #{Vkr#<$ E DRR &HSHGJ .CT @C5+&g@ dNt7>Dax`(Z#X0K rr9=jCpEj)qw6`hAAY~ ,~>?%#&F Ye_B0"ojok5܅XJ,.KGG k@XtUqUh"uu6e t}[Ox N!h3? *~kAv  0 7#AbLdj Z.P F*P$N,"IY*rU&||\`GQh$ [?E+cJޗZ` AHDbBKbu"l 2 !r D(? "p@AC+ @pA oS4౺Kr%$ȈMpe5CD2 LN.b̥xWI,u;E;+3 cl7.P?G9XXpV$`@C1|$Ha"ce@ D.82vy0h@&"B8)22$!_>< \0) I ({̡tBJ))E 3K f䟈V?< >U%4R D0UG#U idO_ r$iX8ƦJ1!_VOɄBՙP镢$?DK`g* ,LPR1@ ΰ$WA!6L]/5Y"w'hq Y42&f>WFxyc3X `bd@`. X➱I2AV!R*s"?T C4B>jBR * r̈B(9. GQs0 ?qHF6)iS4 REM @D:C"ZGBqjn}N׵  Yh÷wr#quRm-+Li(N.z`ޮǞqU" .c\  j EP} <, ȆGP " DO$\ՊF9xJ_<m &Yvƣ ]GBm'ߵH@$: gZ"&P.A0 JN䡤Uy<@AA G&@)L`( M#A!^@*ocxgsvB01P @[ceۇK8 ·+@SU+.?L`dPh$$(STGtҨ;%gՂӑbQ#hܘ4܇$ HqTԐcW0R-H)_0!>1.R8=#2p`(C.8P(BB0 wP;\oJ!EbQ` =;`P |I&XJ*c jw+v _bSkH\;e0fUHF ptmElgHJ$RͧIMʌ AH?BzSڊ`EJ?ҢE<0'{MқsWh^p4R¤k2;L]VdxuTDh & :h\LN' Ax4V]oΪ)>֡uJP $d,$< @ʩ| $BUT! ifZ  5 %U(cE4Dˎlb}u\|f DPU//G*  @!_V2VJDVD$KL4().P"10!U ȇI+."6+o !AhGXt* ^y1{bb! P [o/yi* )їe#.#UE,CQFA2 AcTzQĀJݽ-L#AUuyF, "ȵibhE,b&*$ϠQ4Dr1%#A6*@!.٪z;&IkI{BWd Q`1'?HSWSeJL]cVnFY~g4i pq@$| W_#ِY / 9ZD N )cBB}J5ÀTx00HeBDXJ3A]L"3sv TDATIJ`T<N A \)Uy-R B> QTyy`Lj iFh/Y׵5ب/*,+j?}!YvrZಀ8^ K?6@@bhp(/@ rA +_J%N"f X=*k/d$*'D% eg8yA!M8 >"Lc- 5&^C6v?)5f~Qr\FOIJR? f`Qfhqv 4]NH#m R(jJtK10Oqp' @:C:@ BɡZKC+_2 DF ft..mA#I{נEt) PI@;%@cTE!Ē0"IS2S%Iʲ'pP*&UU[T}ꭁKxkY)/K V@0 COW_,d@P,Z=p%BA.n7i0aM6&R߰ e H D] 2)`r"QԆAUЄƂEhf+2XmFJ qG" ڗB'# ¿`(ϊhAG9!fZSOlT`x 1x7/A(l}>Sj<"J(u4yrjhw 8 0@4Ax&TM(1bD$PI?*(Y0@? 2;I{C!_ H~5 p KC 2lĿ;FO\!*pۼ!a!a@ +tfG0XҸQ b `(|piQ\$reA}LO7A yiz+}GxV.Dv!N> TY||"U Rm *3D%BF>%|7 Cjt4SX !]`&B[(mƠJ 4QK*0X&9k@8K`A T!ջ/ GU!.,T}oM j@FM&C-{BYH)4-'Ł"4R2jARCል$*E4@Go@"mD#?& kaڂq 34Hˬ1!ZWP_@u0HEG^~/? >\ܿ@  'ET!@})( .@ktEO /U\B]-[_q.w@,*(ȆBBD ,BPƄ@;J" (rj%8z)ZHzDEH$Da!*,Xb P'P 6L>D8*5 EIA =&";8ݒQ=ܴ yy F8$)@(*&jVr_U8L#-xTZAJ5b( 5BۄDڎ\rrWVi2)z0m9 J·"`}/+8[rF|v2E|yr#@) [ Qk} { ARwfAS䚇1@lo0I.Q4#0~k@{ 'Hx{C8G'"?@O )%4l \] j1ÜFU+dIycq7 4F<ypiӀ K6{}lIw@rހjo@6q_?@>|^zjjF`!M }R1$\Y膱Q'@ AYi0CnAȲ?pM,_!%'L(/48esIQPe0.[ 8dCdCqun.D^G^>Q""""^4:@sX-3Ӥ0\GHj@AkNO(LB|/ QY -!DMqKB^i%`0XGi{(ɂq*@ C%D (4"0F)QHDL%8JA1(NE( `4{'"@$@" pT IVE D@ `ʂ 8=JWI0Ծ_IAvkyDVtp9,*QANR6ck?*]k BU5/ J (@1u7"Se1(2 ?T4T %IEqa5B5@WI`hBpziU>N((Zmi ($h<>4&$@M Eq䋔@n% @wxdrAnw"L}C[.?T@d?;y&J "{Glɍ1 tqU&h  AzBlI`҈C-%Hj`0L(D8L.""L0DHwHbK )UL!HRJA0~<@bW3 CV$QibTd r] 3HtK5 Fm=?r׵" A}k?}AP1$@PF@ .N?< ȿ =2Na7x5%8 d%`m՗-!p=H @ ^+u6WMWQBt|"tT@w 5'yep0p i>4PÙ% h&%A@DthA,A`2 b. BAJ*ʆP!@aR=% B4jjC @9+a XEa?`UѭM/ۀI:M`\6SW4MUҡj} ȽXw-@l X@bHۣLF`D!#4NViOF_*= 6`y 崑ğ(vB@(4aEკƸC 4=|x}o06bbE|G@ONa\ bTw09TGC&r5y!?W)G1~yx8A tÿ_!# ݺ #'HEgukwӊ%21ːte;_~!jA <8<`$@TT*i(Ѧ$*98SE+<}z Jj2t U">|XrC:1C.!1O( \ A* 1Oy2Qa@~li/ XTr9ZKb,/^ )kK#AZ;H)/F?,_ᄏ& kbDN‰ * 4  pG5TYpX:A8B9C(08lGh(tPiQGXU%3CiLjz|TI4`R9 xNh%v' A%n''mNM""K͢FŘTNTp_̶3#@fzHT "(mfL-9[*@EnS J79I'gyA8q $=JG`5 Py W^]C0""6lo1 <ޟ)!T!S|?[[?!YW)2V4#2fj`y!W( ^y7XƟ҄\Bsz<4$\hhBiF(?~,aٌk7a2$NnnV/*n{. קn(1ӏN h;UҤ7>a/]P" t 9 *Puʯb4"~DBG+@r頊J(X0ȸAZԤ * d@GK8f9!2iC J=J,.ѠP ps?PX( Ě-Jvm J _iQF&Tk UB8A55a)FkB [BXB!WPⲁF5_i_KU@)V/t T@tR`}X \ iA"{8G_V*Ydup:$F8T~NH e2t9N%@XCk ?Pu/3 PQH@G(bHTTt&!M@km^?^Z! N2@#NPG՚ٞ<' C CƄkhr? ds*QA1ńxk+9 $^ Pb @ER =2BU(%B?U  f@'0P0-k/ #n>!!J S< 7=(_a׀EY dbtrFZV*tPf ; *rRJ zaԪ`[8<\'@!&QG}@*u"AR_/ф+>Ki>0*M2 ?`A*PhG1A >a@(w_,#B?p?:-*!4?BU'` p  np@10㳊# +#3(B!:I? - gn0]AL5q%.LA?t, G1h+s:+`,3IjnZT T8ŕj}2)yA,%p nt c8(D3>RPDR+Ȁ!wm:oB?JTBxU$ -U H('HX/06F(@lwJ/SMP;F4%W!+_"K5HB|n0Bd4@-%ŝ@V/#C 3|.1NjY O?/Pſ1@Bda8 ( a캃eJZ #,dj0!gB9@Jb,7 @|0@44Q@0:@:&*1D 0Ui@!AkQ Ah6HGҪ׀ף69ePO0O!!-,WHՙ %)@FҋOWl|C!@,u4qC @#=R+T2/ d hψDY52Y(n "b@(0Dxz 7SE`B@}D/Hh `r*V Wؿh AZJh@+T2&h8NY F?ɴ) ]* { |?@}M=  #7gfbF^W`O*Ur1xZ o(_ʔxٛD0(N?xn@dxJA(G N~( 2PtrJiJw+8C;M5/ ^\D Zhy6*z#E R+R8>/TF`!u>I٨ @R- iShz 'LG $0!=5HY P]UE G=QL4*|Q}?&P$7@ d+6vh~ ҡV\X%hRGz|gaRGf #Pax5P->S^~ ,%,I00"'B,M%AoRR L#2C%JP:Av(` vB ꥽[,},$K$0 P$I I# @db#@@0`@8yFʅ*#%@ 0!p PPh Sp;f095xн,g1'*i?` y ~&ǜ074iMH]FQ,+kKɆUAu ԼV/Ӹr < r cYwBa !Hު%P`:WHEt\D04zd%ਥGITtdQ)j%/f X$pL?ː?y>y(h^.^  B1 hM2#a&$M( fG <+|x>Pj?tuPJȃ nviKQu4PWgŪ#G e em1## "!d(J(\(U( /|$*P+ .+@`@Xbn "y`AԃqI %(r 6' eɢS1@A_%HILydKcxL%p(0g$Ix)"lT\w@xzIs e8 #Ǒ(NE@K $ p 2{ ~\ªLLA"ixM|`w5&2B|bl ԫliWN>?[&cf'i;~PT菩R{@՛GĹe1]޲q./!DS@K]V9p:YQAAěG.y4(@(dʲ#%gJ%#(II:`}CƁfX2d#'#72!3DhK8~t9Yzf'-/1$\cUGP?d;D*Ni3frc< AZBG vbc\t貰gAqp9z3 D Uzv*Z*0LH6U5-+_GG `9L1P m `=tAjLR0kZ0!ThVBY<` 90#T{#dEuUzȀhr@-:X8Iqˀ^ cE G;L{(RE09,Kdٟz`¶P"i%D "+&QzC Ϗ(Fh!_m }TIɶA?$!jB&Xsa;BaA$5 {p4rR%'Tp6re{ ?GP$P6,1"HycL!AptrH˄Q P@aWd]D@#,N! `z#M3 !%"`UiBhT"z=;P_r/s8}V(.q r- *2A $44$D#1"_Xn_[hS^<A +"UQA@ HAZ AI]Vkx_0;y_E xRGΏȡSMX4S'HxZcё4e=Ze'`2@L5?#W \Jh0.ֿS0]Jp%݂Vf &E)"ŎTb| :!"RAF]lSUFS}90$ψBbmg)Py` $Ht&!E@؂f攣V{cu4^rY8g3d:jzD!Rk@Y7"H5BI*P&Lģ@/;,E-52ME0$8$0t˖4Sʀ12IPIڹOYlHY01*]gP! Teoǣ@Ffp9$a1k/SB9)6/%A.B\|p2)RQBPz)]b-wHJ]> snI!2?5P0ትhGtV\TZ1ʔBG] qسCI!a# A(sQlrTQ N ⌭pRt Q|=g#QP1z L ԯ (Ag(BA$ECQFXHԁf QuZOViVN$XFhе$TJyC($h d)J Q(` Iya y|*'Q@$Hՠb2NO"G+ǦD$8D(|A 2}Bgr@HpPR%g0 *.*K8 VC΢'IL-B ?)JC_T$G`,EusވRArb+Abٜ#@ґ !1о:j*E,qA8@Q+"iO;ÈS (ϘqO)ka_C]QvME8Dij4WWԇ,&,)^85#*Q. 14?HE1H,DxD$"p pT( . P$u8z?ʬt Y+0-GW##(گ##4"$@R+Jj@/_h,ʿSZm#q!KE$k]KL%JaNފHF׾B#j'cH*K<" )Cg ~H& Ps ,">CLm!"I м\Eix @p`0-(/AyA QEC rÃK``a(@ `'TtG*%B|t63C! 8$,Šϥ΁&C9?Qy.=.3y (|z/Gp}@-E`BQv]QDZXI:'֑~/ʑye'Oుazō]EBON a)<\!@$X. \/?!#x^,B AiXx|d~P?(7c(\|zPoFy@  #@T8/5#"4P"(@(@! D!B F !@8n^@,J:C3ׇDQC*hS? @M(Pz!Z(O^@Y4 ^,)Ԍ^\@vF7 =L@/6dQ?gB"\A  "-PJ0GԎÇ`CA/ zi 'VP5(r,@(L XdsQ@c3`wDY aA~+p@@#E` @ "5I@*QB sFV@ Hvl N,晬F-W # 4 ddd1#Nj-&`5G'M!i*  %4'PB#)D!_爇& @ ah _0p?4 A0aK'!((AoHs搘Q%w6 K#L?\a=N94uJ@ )3APLU|$ .6(?ade 2* Fbt8@<@P5B(\U/3(})?ojTt=׌I]E\\DSA{,D[(B@T!Kf0&1?s vN jH"'etÓQxVиG@BYg53 9 Y#& 14UZ< ՠ@ hI - IB> ]y,L~0T:6m CJ0$xJ]@Xպ+g`a<n*IYBH (qܑA0 q/z5+Ɣve2`ʗ`gEA9EZҋ$5CN-@ BV4 M7(%_QE W$ P=  @2?aHgL@# "L~G(W4HNə~*#$+<V?M@@`4\B-,d/(i$iZ X@Bt``  $ D^I@< RN $tx`%@ Ҁ4n5@/VQHY]@| Ӂ*0NH DEFȀ }!b(iÕTf/hd Ac(-I`x!I Qn>!!D0D8 H¤/ ,xMP$.-X-(RtE@RdK1 :a&!* %,gDuN~r 9UɕծE_ܧ`AJʑH\9W~`W_W(]`Q^潏 |1g>Ph>" *,(Ddɓ&ij t/$DCxΎ{tl{8@\B8R>oeriD:F`<"LͰqQ-qH?i, 3a؆cEH !H)ȴ(H (Hadc8d T"1貊 T"1X1踆*Q #@"Dddd0 %!!""Ai^t@?\.(?HhDP5:1޽(u$R`Ϭ'DJ)}a,$zr:if&*+0B1tkeXB#?F@(FTJ)@EAja'#GYL?!UT6= 4<d@Dbwa s&?@?5|P`D`" Rw$r ! Zn!h h^$t%B] A^ KC"A[J3:٠Ba{ `S%h1Ά{E9Р#: gBиЩAjt  8>hh$Xdx!Zh|<<]>.JiC`LDM^&^)oen uj| oX~N( !&184b,;W#=0c{8^M )f0^ bq&~(m"Ɉirb+ 12QJTBPA* B QRHm 0%(i)쀇ݏUGڱGfsS>P[/W+W-#ZCA:9@fBET>HQ# '2mpPJ")i@7!aCGo󞧳@т]i d\V@ R]0; Zh8&H$80Z ' Q6hUYДf2" ̐P,+@`B0d"Hi UJT @Pd Ex:GyA,`K ^sii-]Sba wu'!Px82'! p,GBwIJ)Q [ɑ@P4ӆD DqwpӢvSEw{Ԍ>"y!-79u9prr" ', =@+䣳$A"ʢ 8s \bƏb`q&N3ɈxAP @b!\3J Ck@P) Q/XU`R_46EVf 2F0D8yp @&B2PtP)ChI9$BVTF34px4@T"y!jppQ  `1$kh5 dj(ŀ/TQ sH@BÜ&hs 5 sh<S44S8f(U3h>ī~2r ZPA!H 0)@ZHyV `B$NB"jR#v (!0@h(D? APP '9Hx!xEV,5F0.!@F8!Pp*` [nCD$ ()ӯ"D Wc-*(b FBA'ZYiSpATpt JD(*!PqB$z.DOD{"dmE&#N]?\)2@Ր|(ϒ'(b(,CQgL_2?HD ʠ8&\C 4jf $AĜހj>%J@6s* z92 $= X)K0XF G% qB%W))פ!(qHVJBY4)sd@E@$6)k@kiD|`7FHH t4AZzGH8@h%A  ] 2.0P!fBH)aBPY <4hk)O}XP8ro` A/QEb$GJΔ$K(HpIEt17EI($`؁ɓ/亊K`@(_h>~.J8%0LңBEwaSWB H_<'E{#,pTˈ@KUHi@vS*wfۊ#;` ^耢V)"p4b҃ˁUUY !ƀ @@Ph(&q=" l!Dq)&׿hno((! V$m ``hh&aNo)(gK̄K`(88)A:?JߣgKmW8e7LttŔ]PNeVkGq40 Bϖ&%bz^Y`U1'AE $\ko:(ք MI B{aDk++-TEe1=A 1 $賈i0*!\$`@D@K~Y"!c#PJ*u&w)B:wa(<ĺ(("[ᒐ_Ĕ)" 0-A EDPX*.#ʠ수`4(>5@Y#D⇞8etyHPp$a&R@<)_hZ H ;C xwHeH>h+: :\\ bЂ5NÆ-#/ ]d)jBlI|aGЂ>DT@,ϐT[?ang{b#ةA+ ? MED%NO`RM_,Ru30+wbCqL>+"tK74HU* D`FRPz#"yn3_q)U zJr`/0_J`+3X$?T &" Q:3/d@խ  `$@slGT BR$$ pjF (Zo$hzՠ_q Z " UGj4w$3|ܸU~=MSUtlXY Rlh'ȕ9Tv5gs%owNdbKh /*8=$OPGH0o`?|NRn~e* +k ]9fu%ҪYsH kNS'[1^s+Ve0UG X@0(:zDN@`<j5B. q~9Y: Pr@ќb ? nF91 M~""M@1 y,!APF/5 j}>}J# @-EcCڐ3t5{9p`PHh3@@p@$|vF|P x!L q $ kB$PA 4n _>C]A 6GZ%^AXaad 8hy*V( PM&J? .(=A@! o\=րS`{!urgpP+PIhPӅR-786$d? m`#&J g%ʕ\%|hAt x/ɐ_ $@$ p2ʁ  0B^>}` @DO x,4A/EЀ 08!-18hhC((!K  x`x ʧ83)@ @~H4h Ѐ  Ph(V`@4((@D"rR~}@@T )R`@$    @@ p pʑ _TAP, @cv`A|AN8•zK*KLg.{*VhT\H8A."<'$N%Sp@! KnCU X QA$ygZc@`Ba"-$*(@I0,h)KCY $28_op,}𚻪r0 cJCo maC(ҏ]lh<NhA= =9P `i|ifP@ME9"/3,($Z trꃔH<)XVdAfAwkɹ XqӇ~7 \I÷=C PO˓m f{5ZqІ'?w"C͙g'uDP]6VD }ʖ'EA )`2N4 MJa/L H` aWG  b??<2P8/GAY,8Q*KB2$}c4(E -Uȳdk9ꣃM̀<#(Q|rk,Y i/ :P ^ؓxvz( X<8ڋ7P!mNjnFp/PJn>n;a! fJ&Nd u@E,2h$@<} h41 ٣ /&a6#iM3QX*Gz0t EIRd@FNĊ$g32$ ̇P% V@ J%SN\M Dا*1+s Z+Hd$$IiU&5/v^4Wqje8M4l<Ksr@-K #Y?O~K4+P?hH X ̌Ļ(e6`4Z5AHJ?p PA^#`  jEN@G# be lXf02Y0C}b0B5F?,_ Aʀ$0(XaznDXF@b7#QU'`bMaG.xM'4 ][f4Ca8eJXV"s P"2ެԠxE3d(TajAZFN_)aIG(". >aCm)VX@;ZQjLSKOlUfڿH%Qg91기bTHT*2PF'0 v@,Y-@4Y2 ( 0=~@ͦ-@ @B?~T#I+!JPVN`1DM񭊲 z0P8IY @ӂiuJ[OA`dVBxy)"&ʊA%%c+XBF^O\+a4JQ"&&&RV)1@P}o VRβt@"'Ϧ,dmXhU).4v6ܸ |` C8+ZNnLM(DgM`Rش1V@t -JP`2xFh-آ)CB,y. BoȮ64R89S"I +1BPuSO L XAC 2K-)uw %/9Lf|̺jAIdTAu1 x`2`J  hc+(wLy8,bcJ-& \9*ܠS @ KIPG Aʬ`iDW"TaP h1h,Ql8zAYT5OQ {C:-R-GK4" i5JԬfGp %BB0 $z"ބt8 /qIKHh &$A%(hJ4@zND}VL4X 4k@xJɎ@I*5A:@b &P`yl)8q\L !:Plr_V!G~A[UbRH@cLR( (A  BrQ(BX$BHzic }Mq@9v~Qr!W)s<)@}I)u A #C?pF46{"*N0`s`Y9"Z sFt*LP1QS?xfℨ鑁iJ]QJS!Cy_ hʒ6xΚِVN](*ր+,nfT25 N̕*mc ݒ .@a1 i'^ %!B)X,.=0'x&68 }55oDJ2\ SU SZ !`yZMo$KQ|(刁kpdHP= QFź[R#I1(3>YU.E(ԦX!'\JP )GfBővqGQx&l)PQ4ڔufG>z9}tUi"epa5o!^8J/Zl3EEIȵzE |D9&B.`]hw@~$>,Zk^KP!FX9ʀՎDQn}$l *+KV46@5H7@4E4@/@R z]h -hOx  EU ,I X+HQт>Bp)#Hr-=0!g&# y]xb$ W$ #"tB(%ԪJ: WEPUH*J-QKJBHH)D5Dq2*&P@`?:E? fX$@ ̍ P\*hĉ .zC!`U*/T!J@?P]O+Ny2i' ?-$#O+I la@AH9@J 3rzF(P9d=Β 0*5=":]!u #>l/ wbTzH@XQa N"TLI@3D0RXbuo(U!`l*^"@` Y|Wh[XW{ ,p`p<?t01O!Zp0t%AÃM (d0ʆb(ب1G0GQV$pD$< H Az!HA=H@m@DkњЀA:!M*&*&<4b %Hi!0()OEAޅt)-P$,?]V9@ ɬ"%Y+1`TYA jVc ý ~ Q WD!H݊0JX)F G_ZF\ l ?,h0<"e]EF,l$xc< &e0pGWz89 393JOl t r w!rgK&{OW@?@?A=ByrLXNš ؀@A jUG<0e .r ((0/y?ǒ4dA ($(@"8OA@rx7Ar t$耦)v( CxMF O) 4[0@"!T,0:@GH i$%p   TfgbYo4t#q,@[3 h0(W((p @60p$琹qs !4_@0.#P) jKB aAe=$P0,ŵ"D0Ʌ(0M) Z :ȡ`,Ga醡! p$6krD@]. a?#C4$F ]e0"t`,_?8ħNN"  Q,M@_qzG-)ąT2O#%X!ن(\ey87 ^PJWM1ඎ$ t %T QT%@Р6 (  .m+HT:? &:+?W?1( 'Mp;\Zaw =nQGQͳZd(XAr0>meOpA;U8~k  )BrxGK6~lxHJ(E11@tEDIpZ9T!%I_!%P ȘQڣԡ 2 #5Wf1eD xS0`@6w_`ҕ@xV(^mHH0EM-ApuX=#SLX~сZ( /6TĴ^/u H$ Et'-,K0Mf(L%Yƕp6@8Adx/DP ڐ\B#M`sp ,_tBIm BӨmodpoQYaQ/&hJx4 2LWlHa;7(2NiAxB0 1hxABPbѵxꌥ+@fUG 8pZ 1 I`0!! AU 4N.L瀔w^V[t@Y z$ dBMBEԲsw;'}{XrnmGEahG r} !" uQEǴ-&n4O*_b-UcH(דGsBS4f0#R,ՌIʈO)EZ=X2 HAH "A :Ta\zMP GEB;@h 4iWpeoz Q5tpBȏ ĄRд%Ҡ-kF%7`xJ (c UhEHD;s`S:̅2"ؼMGs<0( %ɿZfm5(H0NU[ p6qMꀹX=##dz* ` #1D!@3F@P'Ad^~/B  K ZQBEP A@Дz_d"9t1htBN(@@ۃ PUhrR/E -5ߨ R>A(H7lBW6H߁-C< O~2> JCW0x8ܵ^zC.s3XAfh0 ?I@F)`v(ZLS>@ "\_TO& ?xI*|*_* wdXE^f˱`MT}@D5bToCAК2V"Ǵ*JI@6=p BJ&0\"ha DD Ea:Xy@.\b4P hCtx`#xFb(S pSl $cPQ1XqDRo 'sJ` y<|`,X<')e"oGJ9Ƈ P>FM (@( g@PPr-G.W]@z EQ@&U+@m db!-4"+o#DI8 %ePf_!Bl0 QO?Z? :!r9gArdO@PHP H.+% )$"" LpNp&E!@b@ b(yoBO\Ipb5!A(!k!eT4N (m aj" tpΙچ4 7@(; !T >#C%G"p0+p݊jpb"Ms"T%J cW:8YDŔO V%`H $ **a&S]BYOy+OP[OG`*> A1OSjHX O 1'7BcbM!~t1PdT ` D+d!TB$6<#}lr^Db/`eJGBp7RzP%/ 4`0Fh"8?44y$ xa`>2Wr';~V W!\r +.5vJ$,Ǘ͘8U!p!еpѡܡH-V,1k %@/,  (4EbN`PxS'W+H$LFwmhB^D?H#0ra"9l["Q]6}NmEW FD!,9do!$h&CBX ~(<J8lQDŽ$xi ?@2GhGڡrBB^(0`݀K@%#Q*?>PP0>#H _ BPB?'JP?=A[e@@Ɍ1]jA]آ%XIÉ $1__ J 4{Çaa@F@rsYz/"𨭃͡j3S A[a7'&Q0K?(G˗/XL":KЈntGj'dF9JI<W:^tOR(@Y5ha GhC^h- @¢,6 Y  ХAhg8D1{VS_L`RIIC4&P&ȠQrP@Vo}Hbt1+!,g 4j#QYd1} p,; _`7РʇD (ԟH@P_K #)%! kzif~[ACQFX)QF+A4*]}Dvq Hq$Hao@`8Y5h >oFhu$0X=$UCR! tpUQ{(Py8@\ U?}i  ԛt(b1#/ ϪtȠ=Rj(v`@2 Y` uX@N<@2E14@x:2^ZЍ V#E+F" zqq% CF.F.&*gD0]bX?( (IL ,$a1Z8"чP1"ZAQ,ߔHao Y]#ʜ(, O%AzCtڅ Kȓpr"Qq8e B4(Z1hj%F`%i(Kk3Q?Վ! xDʝca(x)%uBe A੹l%9QD o!ܸ |b 2\|l7 @ A UH!JRa ȆɆ1!n4SnʐJAEZh?0ae 4w0 ',>fZ#-Q@  @io@!yu3E)_Gӱ@pʎgd?Cg o!۲ab!O䁀DB   Pa1P! dh/A 0<tBROH+GY(PU5@GF^nnn_B\ J8Q]Rb+#q BdQпN??@OM #!~Hdn /DtE  Aky X.JLR hPH2 8pTP$BCah.P裃1ZaG-I@kO{ f)@G0@%5|HJ@Y."#H0q(brȍ !! Ѩ$"Qac$i*!@3u$POףeRBTGk:=lc\!dAʗj5w@ b4D:)U 6*ҟJke,H^A Q*qԏkMdBfuaJ42\s>A~5&/˖'1zR %HhD~6x),=c!=-߷$i}Wr >BJdcQ@Dk"n!!}iBW@M E22)JP`eL@訡)5!_pݏA,]9%Dε9gX1&ʘ:fRB;,)  !R!I@PQTV  tVy1W u$myxm$4础Ej(S@F,j\Yh +C!XNȮVr%kN? o8:B2bﮥKMdJ1F+Rtus"0@@AEj PbBF*J#Ɖ/NZ~|9w( "%BPG (ZƀE. dRpA^@ y4P^R%<)JP`l&} $(+:A o$"հAH,q/0FTP< u4b e)(s5ĸGƙ#HNͧ<1{'̩zpoEWa P+ .',wV`Asi5P&d"\J˼|eE£&s?!&XcP3` ݩ)!'H!(j4V |lG) ;ĖJF/(M=[)F GLTb}icEcC0 "K RbP>V4yDN0SWFK%b1i0p9tv AB9@*Q?(U8r!x"F@AHݒ &XON4ij4@gF"(Vanj)0̸c@aJ+ ec  AN(3/2)`Uˮ_i,'ȭ*遛0\)`1Yr;)4z};C )!$!S]\s}) w}@H|sْ8YXB!_XCOv t0B4HЪv  `&>xw! |hfp\4bH$"R,++ŶxO^x[ɨ\hj~Pa†Q?#.C\-#?4Hb )?lם8I{aToHFNrZ >8jk r4}:~ue=&>dcfJ{@Jg1-@]M@Mjh .4)@M X5ZіR.B L.&!@Le9 E}/CpCcHAE OiqBQ2y*?HI8*%1,$H  JQZK1͏g X3Fl<\sF E BUN;FGX "@00i"60q(^,>H6ؓXЌWL:[3נT 0i!dI $4CI%RbBD4>yU:L $  @d٘ P` ʲ H-*BAHtIIREP @@ @C3R Aq@%TȀBl@#$ThQ0U(!` ~8 8hnAh4Ka@!soN $ʻL0,nD$hbRD8nK` Ɵ T„ r p8ZQyٙPn@$!KQQ΄P 3Ğ@UTcz"A4HjȲkx @UPˈMwJam.PvW99@d(%{+P@9 r'$(Ġ#DR)81 u) BTHPk&[3j@L mEQI*F0 _0DR*&i'@3g1p QTCD@nAT2&4ZB(B Ɇ@ȳMX"2 ) ,cb{sIVI Ae>|X T!tO@l$`ť PhT H`|/FȣNFOóvv;;;;;;;;;;vvS:uO ~=@A A PH" Wy"@$I0x#(%(}P0V ht['zwl(4@NECJ8w"f~4b(0 /?}f~C@tANY Pj0!@t&ܠ ?]=PPQ@$5:@%BUYs1( EPw]@ꀈ<P.I*T) Td(BN tδfħ'S"(q!d@0~@<!@0E ' )K'a0H$L ؀ '!b} >`x0Q1+Z?|+2MHJ wZT 5@u $G - h! e&%Eh8QJ8Xi AW^a.YCZ:-%R Jx9w!WTА0FU, jb3!@,?ؚülM:Fg)0A:_FPS oHR1Ixu|*HC$K#`%S S ‚0kӱ#LQB'NA,`bUq>Zu䀞#)!X4Aж(=J h (hw~%DJV0|$^}  @="0CH b % D3E Ғ3X9 ?.WBXO[JYb!_zu Yqr@A|Fa_TRBWW'nC60mQ>U\C>1G7hiTk+ "Z)ptS 08b paq zĮ橘Љ~@cgs':'e콗2\q&$k$ ""iNJdswM E}4GJH"V%מEF-YںFF Qs5K15 ,UXPdti f>o2He68Y.5Т f8&*ۍ@h44Qoj5FQ̀?@HX" 8-l$k&IN]$EE^\X8BW!EOGͯ Xc&0{П.IJFDZhl D6#Kgu*pg"hNmEum#@0$r WzUf렆VG` =@$٦tUU- AwCuJ(Hi!S- (Z*h)Q j RVI|4(%Jo2SNt%U@ (.]D`UO'E䜓bLI1%ϒbLILc Q|20`1:%!dQՉ1R%?n1+x<.IQ w:LƔUx׉E|)Jro, BJR,`!Al@Pp[ dbA iV(Ђs(BD'm' &Ij3`C@P !Be]?)Cŋ R @E&C Q LЖ^! `2 |jdjM&81ɀu#TWP P@$acjzɋU ,Dɍb@B1e:FTyť* i @D/I`Ig^VJ!H 7G  `ԅi ~:#Hĵ (& ?>JhC?-,^G?Ner?DDHOһEfVm[p9c@(PI#PBFG̒VE"|\xL -A-̀?mخͧo?yCy @bbG!)Ԁp.Ftֹ#?( d|+_dv.m2$)^ M )w+ s?ZSHANhih=]PG&E!74s/1"A<@M / LUP?Ŝo(Di^IN j2nlPFL4`EBAV*1PQ)Z.i$di .sD?.z@YV P FԕKbgiw :`TҖULΆA=\ F0 $!V$[?WW2;1ii">fX\!"'Jp;X2 b*20("%'͒ ]AP( J$h%v.-(@4@`T) !0@RAiQIE1ꠢU}8䘓"f\˙s.D̹"ǀpA!B J j$Nv(b PW!R*Paj(%5Aί/p8>+O@^` ĭO, ~BO!GzX< dXh^ b! `U͋99`~i!܆O3dZ2#̞ Qɂ!I chGBUv]dF1EQ:p9Nt& nZPKB\iB:P$(EtPfABdRipj5Qj4 |@DH(6Eİ$a֠/@Q-RĠ$ɈKR@xR !$cR1KMv (LgL) C;=3 up9P=P9f24T P< P Fn`PF(A~^7 P ijkCDQ:`G%1"[oۧOn=ZyV0P `!@B#Q)$T_Pq~7oRx@SwU-7i=b`~8 xINpH(}Z@_BX ea!Z‡5ea)ap4EpP P-ZOhK??$H+)PC YQhQC07NNGASp,\ $2Pd 288`0<&'c?` 0$7TL@Zv$ʢ364bX Dh~S,ިQA:Cj9K%(Iv ]> C - A'􁢭CZ G a 3P_{:׀{-7GSaC(ĖdqSnꇒQ >: Rf6 zp@8,t;=|>ᲃ&C H\S`a Ŋ@A4nZOl°&ɻz<2$V)C'ʏ@>.X9#0%"GK>֡7Q_Q[PDLBCEQT~MO" Q$ [" tA\,n2ZoY`C( PLQD P|*e0dFAq10`IB ZW1@N@TëG q<~ ;Ljp*OD  Dz$#aɹIPn4qJÒ6lF1DJ $<@!$W(CtQӦ}N;YNvv݇m;q / (~!L e!@Dٖ>RDO`1B0FI $IM}TS%&"uȇ o)_4Y Qh j?K"H*=9&0B0D2Mk^Y M>`App0B D Jip XATuF8)&u+;,VBbT*A /ɧ'u=#ǜD OڨQDŽ""|ET?'W |P($,WT41}9Gc6}'t^I9&$ė= PEs' J4AE EXdZpP-]5+A‚"zS_~tU_P_yWGf8[$?ېFNUVpؒ)'ψ@ G!PB*M= Xt"̨FIB"I/O/r: ,<#0F"@@HDKHpTXA!qu@a0 Cp= xL$@ 1x`} LϤ$+eZ:0̠V((cRR_xP)Ad e?D@2 F7&F"R H+T6)RT_l0[PNh . h!l RhKD>=;H6 4H @(MRk@5@5R!x^_YnSۧOn={t 3'8E`a$m;" x^N'" "Ax|fYl'Gwާz@@v,B1 ?y@j aA .8a(С3HaAEOj|pƦ/lbUzC#,6nJ h!&] k`&Q < I}d"͸J(A@ Vj p r!\%Ϡ U1c@LP#1M B@ F(sųZD91Hc6 "cQ *}A]`Gr.y<WԆu)邟G|!Hz"nlF7(@d/62b1pQAm@-PE+yK:`B_0L$ A@$ 0 TЦ qUUx44 yyb ~adByy0 `b\-=Z_0@ arQ?XJ7= pbp>dFhdJ@-{_D?4 1,hH/@`FA~4ѿ ͌Yl`Ў 0 (XGl4h}c`/y~B|.B/!`rC\m{=g ACRDG(Q]N p$(E'^=eΖ>XLC (d TA 1EPPJ  ,i9N@J5D[e bZdIUą - $jW@@ CHXգB4ϨlS\LpçOA4#jR',q +QwXLG^F 8GbJxa*Ta,C$CXAb!(ȎgȆ>]&0ġF(J4yh2q@@ A Q< 2h:A4_?\|HG7oT;x =tD AP#Bx#,*1?>D$\@?(Eʡjq~ii ;R5[E%ɓ^ht9p%v9j 0&$")l CM^K<ւf(K a#}`Q KG# &q?q MRU@)}feFU<㙃z=/N@H&2CXB LZn}0+d Nе-X`y'kn`i iNmو˘d5<(0X 0BnqPDMm<Ԁ:ҙwg-eA'h|53zY GYOf Z[h‰$D"/GP Ӂݭ%u×ŋ8 T_ΒE yv\} (A@൤7Q_&%aCD&,* ϔ{G / ق:It{ <1Ų?003U;䐏WȀ/1(ruT,0,HE@EBIDЪ!e;;F|ȥx-5$C}EābU@M`S/fAǩУ4PdR ٫*rd1R\xlaGU 7`2 * n9\ҽh('vC]8 C4|<(=5,,!я8ۃǫO:ҧ&:|nNdVUկuץD&ߋxCʕ hA4t0.ҫZ&3Z(dHVhvI J9 @0jPJZ0Pq. QAWG-ZPWֹ X C(GSJj,R":BqBjG(<:dT %%u#)CteKA]V-@MCw9($6h"(AVX>jҙ!/׻mg4`gJYa}kNgz^Dy8Vh K؄9y_kol$p_?q 2G$` @8F!'Np2<` S| _YZ, ONFt@I^m>@yKr5N!ˤHAtĜesI1X[~c \8C{H@JrfB%*Wo"is&@P i ]j EZR&vOCa)Ĭ^Q[J$+! BcJA T_l43O>8\\f/A%8 @>BrvxP q[0>b&P}?9,/]PLFs@[c֫F?|,a#m12q*H5 @@@gN:`>CO t0΀ v/7@] OZ +T0*VR?KL[ T> CXӘ/pz4q$4F$ Q_";H= [y$̎[}xͧ N=`3h ,x N W38ʜ d `D(H~ Ӱ ߰8Ѡ,5iYYL@R#ZEj@ ͭ0>B@zdS Q(? !*{ +\J@8g<$U*JjН 4 bCT @:l *0.5kG I)K IڔM|"|[fWZij]dd rk/` a(wb S( $__ v3 #;wlݳ}zxZtXh F5L%?'&ߏbf 1+ 4|$`Qq>Kʽ`@Dyw<@9TPVܶ@v@u DS[P  b0 4B%9 d }[[_0 8 <jAGAHև`3_`^]Ÿ0` A0)@(c33 +d!gqZ ު`˟/`~haG EG3#oݑ-Gp©FX*Q>:Nc` 7_ !E/@%)^9J,h~&Z9}T1ÑqTPȪl>"Ap`Th D%E)vV@7dH #DCpHz! C$Q@ QBB(Hj.wf>IMRYڨ@B A/EB"FF ABɈSVw/@@ LW|zm m6Ͷw;wlݳG`΀At.iwNr`"+JB7E 9$HS@_`9»cCp0|@(  )J1cAB)P]]*R-@?_WTAGQ"I䕝 (@=\| @P((8.tiIDyA09/zDt,BfATX. 2`T!K6cl6;;wd9eq% $8 Y@a ‰H Q#%Ʊ )#% &JN:tNmBk ^` FT/!Q"B/7@ RDRC(( 0  ̆DkJ~p܌@~G$ PPE*9\X(N;08N K ۂw B Rώ 19lZ2TAR K4pJ?ILZeH1|'(P )0EizX vV%PhM,d yydH6`bn\@\L@  Tg(Nƈh YYXQP@`=ffw@lY`cL !($v ѯ>ˀ,Wf Hx-PfIc`aɍ.*@ So+-Z@>QA B 0@SWhJ9hn]c0@:1re`Q%tyu-g r w*0,Ei4#I#3 +1%ϫۡ2m |q׈窸1]y\x>3@24`&dJ00AĒ*4m d '<X+ǔHr򢯎~麀sc o;*~rc,JOV@1%(zZd #9rFv}jmMlZb"Ûbl2ts `T _@B?7;, @[((%z;:>?)&^ٱ[HrݦޫsBw?cAsVl@ЉKqN~AP&H- K,Cy BD[*OP 4gӴMKjSaUV4XSd7 OA;38ydi Axڅ.4t 6\>hΧc#,s0٤fMg4JJ-@BIr`["N是|@ъ3cH'@4M%J@T+ME(Bh$UÀX= TA F5h:@(JCh 29C(-QB9 T3 +,bsE5"@Ev&J@u}+ZZ;j9VM8QA@`C8< ']Mw䓣g. `I4"Šӱ~A"tV#\#g:ޭoUHKkr@S3QD Zdba)_A"թ+_(l|>"R4<(+j@ |"L ̀5gx3SlF )$DHsX Ύ%b@ jF )dPzEBԤyL Qި@, <"@uŹ5 R'%L$(Aq(y&(Í JjOE 7$؛g`pƣ#S%KU,tkB)Bj R_,|TT;h23dLnnd$=\E g$Z RTHxODRRQ#F @Q- !5bBCni9"4B[SqaB(>YANЇ-jrG , R_DT%T_|;ڇa}mh0XdAl^D'V.*jm]k톘%"\ $Dj}mu4(s-W(!NI(@_ausF.D+4@"Pi A$Q!`R,8YhKzvRh|+iG:b1ZVIL 7- S!ŴtiI\N}$j)Q4 @P!!AH$SX@!UR:|HVbꤊJ`@C8}SOu]dxpsci* I0ʢ apHex JUSb> R4Vh"#@% PGhij6EI 6*d3D H09gձs 5G(bQӪm񣅑J(wʐa#* $:nx^n m @lH̞R1آMʻ9JʩNZ/p Ⱥ$F Z RaZG,!9U(Bp UH2U6b!E+2.wVHHK!Խ "`cOx #f@!I("\$\A ҴP>=P -P#|$C?"ڿr %CS:5{)"jaE'gA(JHTh=Ia \VN"SZ[/!P@(@ Ddn,7I$Y.i- +rdBe@O"R)ƾXǍhuS5əPt7y :3 vڗyCؐ|C]n"ʠ)(=@I(q ')`$J‹+$5 ' t`4 (Qԉ]'ħ]4V`9R"#*ZE2o |Al *y? yvF@(OC $ # ްy΀H 4Ėt=>$ýBlP44A=B A?,zm% 1!K~^?,۴Ʈ<g !Ä!K̅C+`J?@TPf8}i7OPS?(!8 )}# @ /\f ǺD$jw &m =0 d2 (z⅔ @"3F y:!2%)@(Q( " 0I  *\>L B-$)@":}GF t ";4P'#b@gqL,=kjy!6XAIcf8.0Bpf}n ` C퀈ǺAv4)g}j2[ѳ) 9K?V`s9aH8؞ ]gŚtWG CAHl,0(1薒(FR7M/+Z/=&%5lFZ5+$\vL@˭µXi_?#UAd@xxM?(Ap>`5@fr{SÂ˞$^Dp zxR||䌋OZ$($0X8 ;^OR Ƙ ET? M_JT !HQRNHhDZPVEN?Z{:GzqPH9,I&Dc 2@ ;Zz{R_b!XDH\_帏vu,o@d 6ހr31a!TOabC$#d送!>(xjz|0:"tX҃)*0 G"i`HGDIN cK`$x1|jb+e)Bp_B>EAAR4Tq(AZH"qJ 4@)g (} (Pk(?U ce P%hQrSAL. @0AI 8 ^Z!xncߟ  ;on 4'^<B@x,*0 s!PZwԕAY-lV@Q3=T4> O ˅aIY 0QC Cp YT pUipPkKlXWi۸p>Q"5\blŒyQ0B j^2HT,A`{7ZԠ|x/)] P/ YTyu-6a$C rD$= ` !(\πA{@*(C@+JH, X+J-h(z4P}A |9I!*$xЕ'E47aN9UA)`e{ɁÙB#w1, TCbrAOP}""4_0ut%,&c@s "8hCttX $z^!MH<@:Xč06R"N(GM$@QAOM:MBw<@mAd(rH|Y!@ z"tC)Cל!ey bbIU%*10 (\ T#?- 3PǗ  <@9^BO<EmD?p`Dsb ; !yZNL  *a eFzQb1@? PX&tfР2+ F 9==p7B vJcU Pm A0&Ry0?h2$ w ># ]:GiyB*~vqO!B? {͏x#( ج fU +aOth4-gIFL?.`G W 0U PBi@Q?K"cՐ'n"Ys<"sF+|\+Wwv2?j@+IyP$5g *@#;"2Ec€#K@Wc##^K}⠎~ J'Zx s@%@ z< (^6p zBH.(Pt P@s(dɤLCH΄-Z@Q`J|#BqHMB}9w(P]N^Ǣ( XC"F'Q!PAgy-UFٹB0 nJ#K)|LԘ,_@5RuƘ+1ql\JA6g=m؉T1",Hb@Bt~NPA/!"HLL@$D8D6A T@=@h +$5Hj+A -DǓGHjj5@Q'p9G\Hb A8hZ7B MW~$SQ}p@R)!mE߷+< ˀ"E#G1 tW9 0s#@%FaKH8 qDh-"ar$(nzHPZ`_K.FD H3rdBzrl@LVdwL<H&A &"aFdQrI>Uо~`գ e ZR0PLyƒ) 3@ zDO$B$I$៝A?E#@PJ6MO!ܚmJ .  KLc ~FG b\IJ Ze?K[j1x @ \*dcv`?@h€¨ᰆss0ŀ@Q iG~1Q(h) cqcGԎ$b!~(A5Lm8@i !)ñr  t?@./@t\`Jev/!sho ­B$%ЦP*ų_`,PVӾ[)aZH4X@Z `q 7HGxPm q_61l яhF(la}ckhl7K4>EW 5!x8z4mbxM 5E+! F'#Cj!!!!0PQ  (aa/7߄aKxSc)3a~SȌS̸@ b{X#}~O@i3z@V)FR֘i!tM=:Q G1tCH``4`%O:-v Hk3O*?$@B~H44 sP)D~C"P(c`ؠ2#,0F\%(fvx݉0km*"Q?ϓim0s>U:H/\LA 2 7~f7 8L@ߐ !<^B #t  +;XQy"NXZ(4Y;<P$p<ѪVj6!1oq@" 0Rb/ |b/6} O" % p 2ȏ}BSx*(0ZS9@`B-,+e\@;zp&nZЎB0# NXjAB¨-CCRzѭ ,y Y1R TD r hHP +6)O^IUy܍@(Q,ς(*00Z h4P7(8`$.&AHL Y3ЋGa~C J& m?)˄!T"1yk"k:q)#BҤ0`p+F`BX1=&!Hej  0xyL1E*IH&2I̒DTQ0?%QPJáb= EG]>> > N+P } {ާU" IQ5"+|P7X)k$h̅CAxXK„Pq'd<ՌR|{wSܨ4tpC:TT Dտ7ʺ WS\ 3p@hoтfT ;XzaDF;Vl`0e W Ѕƞ%IY^dYhSh4T"J*XU*B(.M$(hY HXM!#AFC(hƌ~p*n(Ez.Ұ0A׮A[" %<MHH~1}`h:z8 !z$LJWR@Mn G.zZ\J@ Z=PGZIK@ HA4ABbLF_o>MS% lrwUA%1B ?r~ 1Cp^Sɉ&z2H@Aϲ}o EwNp5+QQA#XIQ-/ Hvˆ@HAp&"yihLր%7ʀT?F 44Q[ LD5tBX`S-Ԫ(HBP5>H=+0 @UD?C q+PADFF>9b |(@xXTiT~ЌL:5/:dޱ rDFN0Ę04 FRO .rK"̑"Im߆ժcTbB*$JV~M uY 'VD*2T,&CXbN 26y\"Z (S2g YwU4x,(- CE"xnEE62gA&KJ228kPa&@VR`T ӇK(,UO ԋ:8>RVf S~4*/D 41(M2_MAL3?#G8c@-iJ+-_r8Cɴ % t &4ǖ!y wU\K|%$B/#ȡp($haQ!YKrrBQ U_4 @`E eg@ d %R0X4v$$CPN=xX yc)EGhPH$2TJ$I4@ )T9"r(q  :AH4@He8 PRR@3S) Q(#E! PG, ("C x; Pϑ,@@mBzpGw@ػqK7.1,1бh "9V@0)"/`@Oe  p~jQ2CGˆhq@5(TqZ/4 J0փl?FH!C 8v3*. Zuߤ6A~RzPE_*}$;1HB7:xlgƀ 6@ci(ųĉ \ &H&2^:^8rI )pUp?/\ 'Iih0󁯨wtjPCCQ2%!!?efbR`*Ԛ""j_bʄ2 ZaS?4+L 0 c#YJ 4&A6)vQ8g'eYvF|-H8CǺ~0@t9GEJDiǠ&78F}Ҡ G `Bl#BހQGi#D#Nq J#bgjqJP 6^CB* mX;2@5@d4b$Sހӿ̉ o`Q:aQq A91$[3["َH ŤQV?0`I h8 J%~Y(&$&7}hCZUP*?h7‘ƺ! Cx$#t"y.AEX:&n$8V1#5`F⹡@m9A7+@A) ̀<id">69S`&2օƦt&PE,B)(RB^4P^TUnO5ͱ"cɳ&ҐAS:J:FnNP† Xd@ (OIY WP_QMAjTBv UJU#=p98=ގ‰ `n!hܛB] _`;cgPWQG$0@@@E*ǔe)"4RyybŋThti@]%)d#*@((80$PH )IU]\A$*Nky,@=d"N W_?S X :D HO[Ǜ>0 qp\hLbCŃhI2*y ܰ,A`$ #@Ag] *<I-x0DrK!<""+.@p!;NdT @h,JΩKyYS@8V2R?P8IPCV5fPCU]Q[|+?lN?iȧ4'8` S?݄`cvNLQ 0q EgNF\JJ G0v#IE;QLJ( pWq; #| hxBTFD 5aO˜;(bPDBMb %r* ir_s: aK.VN")Pj14B$*HQЛPJU@6J"A l[()@(*::P$@_WBQ/vłn]h;G GFV P&x̙\1?)i  HI1GQ!]JPZ@5/ABl ^OBL/!.s^p,Fj=! {9(@!"ňJ)BnRR`2KCYVP{Eh#-cڢX(9b0>-A ?N!`o~ v偯R1QBKAV%WbTR1bxQ' X#!{,DDT1#šL @]EVo!U7&\~%&r6< )1v JC JZ#w䬠 !ι!+a/y^svohB5ED]9~%Q*2̕Qk30U/P$ V b_}VR`D? W%:,aETrZ" S Ta VJ 1E$BE"  1c@0DQQ(Q&AgY@ehb JgӘBOJ0R֤BQaD (1$a84V  :$H1"A`z,GP(}BxnIb7ؕ *X1S-8Ua7 sr+QJئLh냸ҁ6"5 pE֔$ Z(Êr-C=JDcD-!]0!ij^,+s]AcjGBD&ƏP/E}** b$dr9? ~c U V#%⨧ (q#G HYL-yz_OY,#:b{MP傺ȌF@| 0KH vFԆ0#uPRVhduGQ )UC]C{4BA"ʌ4(bX>L)"]9I‡*v<HeATbTx $QJ1Ϝ+˦F+X⥋^|ʀQ|pv=*eXqk ¢^0I/ԬH8 @"4q@щ'FJo|2"JJdJ[oKH^ыnW( "."iE;_($]-RrP@eT5 24C#P Mg@]HdW ԖS\U,y+h-d~0 @5U[PA h #CQ4H@DOi`B娇{$D$-*< .Vؘ|J ?m]f>:Eo/uD+u%po1zR(qt^C,`1 SHp&~l SJ*12hIr_N?CmQ@(­#eUۺ0̞S`9נ TWV4s]8LۣKpNXXw1$ s_lq(ӮɈ#N`gN+r88‚I4ߜJq!WDR;ƔaH@W|a[TbGOš`o(,Bkp,3zeaQl H~cx$3 oUɤa ~I9g*Q w}a8`}'^*Hf@ }>P< a6"&D5. Y ňAՊ!8IUAX4="bS~Y~; FD($U#̆(AJb UJ(pM`UH'EKPAzXc ,[?s 9 STj)"b֍\0iRтC 9H,e(@2 zLퟞpL`TlE=i6*%a0d aX00*˃Cf dO#%Xpc 6M**V}_MiirAQQu01(`sCqD$r0 !Z-AL`hh@F2+R8zxu_^$C|?$ 5I2˔K#!iK2g$ CQp&B @\PTWb'ʈ (- $Gz! =` 2pc?L[z ȑ~ 0x##ɐ|x9p6@,WXt藈 To :=? H$= N PqL@K\VEh$1eF "5(A "8;HIa0(״X]vp"Az=@he/d_Cl\R8e -paO(CR ̘ s'px : W$|?S/a  ^Â)!@+0h0ʰSkEBjB? }~y|*! V" E" EBkBEr(gN!SSyKG4Fn%8d_Pj ̈ yPEr4K3hKwMI?Ѹ5'p7 [9sP]9˷ |Ȱ`W[>Q@B*@+>c ju,6x `,@2k$iOHz )U )6G0õ'Vm#|? 7/-ST.Ly! &Y!f>!,9ڕ?Šƛ(ߍ0TH5A4ap G1,w_8yh'nE,`TuIQ|0d0|Pgǀ' 1R)E HH UP &> " yNF `!$RHE*|n!!!!!Ogm!Z \UA & Gʨ$ht"J+9m>X k 1[LSO@( +P"u&$FJ[`@YL,m#  Y`1r9YpwLZ>sAk3C,2`$i  @ t)H5">VN^BDAAA1 z AH P tqf/G:tT=/~n A]rY VI !Ei D.˿B ߏ5@$S7av@I1.z9/T\p, r'qsT))MDq j"~H0{$629wf$l @+`3 ,|XK,!G1G`1siCCP.TChCJ} 45uqꖐ3Y-$ X a+y AHd $|zzgaJ Fʪ]BA'd< Hjd9A fHB"` A ɥw(@XSǢϒ+FD Dt]H$B>X( 'XO@ PD@> =C1,>g ^\ @4F%<ҘԬDFbB餰P"0P!pShJr!RƸu]X0! q @ťN?hqR? ,bK<$P `X@aL` "HZh~ŵ8x8aL | D8 \ F/  "D3Fxe$UꨔhNd (: 9it(@v@*GQR_AIeN,ד J"fx$:!R@g K|0CAA_ P` FupBWA R U0H|GHQ% +'Sۄ=G&@?6K;o&ri@ص1_xQ@\Ɵ(7SX#0l} B 0!H,8ARޟBdHYpZa‚(\ػ0 @w(?$ /f6Ux @' C< D8B\5 W,x( z&'  R@0R SQLL3l2LOz CAĥ (dR?4s֡I] EhA„3"w;ŠdqR,b0WJZ(o =i#6exFXB k4 +'D1(n~'5D$X5pGtH& [ Fb@" 918B#P/?O!styW#xcP!gUf{-0ä"$G(DLDt.Z@¯_gȋQJ#HVy D&ށ8i2bάgM' 4zBz]M& $hpe~&GALiD)xR6@} 8 H1r \$IvQm;*zC 9 0TB( @$ dc FC!XEz^:ـNG-kgL23C*M 쎏o7Ԑ\h ׿ YVu!\@`X !O;dIAYCC@U'܋ (Ae4RB42*@1PP84!ļ.Q1Vz82$R  ~%TE! -U@HZFӗu3ZBA6XM,CKR/Bh4AM_0aZBz ƨά9(:MQLVs%hЖFX}芇 t!)dCMyt A *|X7cU?*VU@nV^j(h;taU?‡ٰ! F]0^V8 6!bݤE? )H<(NfH` plB=!"?"" ܀/ILh8v JH05 - ly(BĠ` e(@`*$W`)v mMZ% ŒGSG b@.OhMO f] -*썢 $jl sGh ނ\w=]@4@`|C/ G)AL? >_X3h4C: h %L0( Q713vupTUD3j؂!kb "ǐ(k7S *[XA'5K<289;3)Wα MF.<!KZ*ҳsX $V$*Q*ViD3(2CDrh $BKA5 }<_)^ b+CЁuU!ږFj yc1%n=$U%D;ZD4!4D(eOa@bFEȔ`l& mg^!TUE#3P-~сtAypAJUNuG\? * Z2Qw0S[BPq20l\cZ%b$(B AB%"le GP9 GZd/(J!Iq*KT!^yu9+O5SS.|*;_@шU R&TA 1Zc$!ǜb0 [$Q+W $A(9JB (.*!J8 1DL8,y 4 6Q!2ȎDK􍆔(BBgI q%(X"3M!#Q `Fp@l(4+ B@h`)ԃHE HxA tl%䌡ePDc)JЌ҈H4UAlv0TVrkG[!|I@Yܤ傴iQv=.#TaDDvjMjR1@K* d!J` X(VJo!60%QL*;3d\i'dNM-UBP&*# &TFP_CaC W CU"()?6=1=\ʱFQI2lӝ&Zcϋ;Pч$HsUT~4 !(Py +4Y-?BET, yiP骴FPa3Z%(B}꾑XaJڕkl2V It~^|9$Q!O`H>3@P"AG0(A*j٦ b6A#L5 AՀdT)GTG8j!&aF@2xX@ʤ :B JT)A`ht|T $b@"X,,$|8 **,%HB S( Sa>O _* h%l*??bO1$ : #/t 5_~B C`f/FH-D#2HEX}o?lS0? (jд$b [A# FT^D_@Q:5$CB©J8]𩀬M$MAE xQÒ2G>O< ,d4 $nV;bd4G8',GNJހ@Ë ^@Oo;179v#\)$$ mGa40WPp0Qwq_ Q.\y* %VX`l> \0`#ДN^i|r_,9V?'i@21eTicF#E(wQ Ezғs33 "!UuR#?@@`~@^#l CUAR *=$M(Aj/#Gt%90@D2(JT 8cTZ4 B=˦Ut;Y!x\QW.CVnTkSc Z N@f$؀ 8,H8TPtRcX(! ŐñRdαQ<)/.W)r $/U;B"nDU (2 ,G#%R!! @+:~@0N!G51pQŒ(A" U]c`1O98}@ `yHZ5JAn8 B(V#$2 !vQ @DXDdz@DJ{)S%c)@rp)<+ʵoג Tu tVL:WtT j-1x  "b;0R0Q b(`Ӕ"z  {CEXI),R?|ULBaBF+LxgG"P`8i-(K|ٔUH_o36(}6FX D> ":Rz 'jh@iHǤPR]OEt sy$6bXb *C&5 $2Ux&tQRRrnAhRY!$p\A%AtXqv`c-5(zd,:O J hH?@* &#Aĩ-4q:!c4bJCRrzWtHV!"ԩ!{*($fA̕.RV:@ %A@QJ! dX;01 S|Xpv/З[k/.c`8qINGS,dZ2^yDɧ^j9clr@( $BD`i+B% pr @t4 o4S%beykx_q e. CG\0 D@8Pm z $  p&/[)1(H @QX/GHKD: C.-TRD! &D2(9Qa4#$4R`lLBM]$"B/ׯh!ICR.lĵ8^Uz9pqɔM Q"2,ZHʢg-ZlF^ ::nNYWI7}o`X!iZtP8.t! EP<@٠DAC(T UIH?A-Zb4<ʡCa&)vH˽nPM=Cnl-r9v0><ApD@E 0$@DRVegh X CNXDxn)f#"R .\$*axD 89ژ o>*UhYv$ 3Ì`]U0$ GNi*,R⃐W)JXPV H} :ꪔקŦ!]&h!:bB#STo7‰ n bk˚HT$3D T pQbTe GHţDL`D "!DaűL Kh`) @M4IQR HE,$PzH $q@ R 2(fáT (FhN Zu箜!r/ 6z<]hzRs ,̆DFOX`lg`2o(HC QkXkH6PdT@LB^ LGU%3K+N ^lS0U0]h(=q6@h!PѤ,(QTB$Ic@E -(@46ȝ .@ @68">a! @tX"gԛH bEA*P2IEADL+83$i @s24P8!XFfu_O]zu:zJrjP4V<<ބt_.$OG 5WX*4\WTU`h1Zf”5jCٴ3CHRyj܇u P/iDf˭qͫz Pw1eM%R/%vKfUt"r|Q h&p!s@!@4C0F!LL١爃l̼hlB!# ☂ D|'A>@o  B!X/j@5%FJ"S;%"4gdb`z)A`{),xEg`MBдV.@BhUQ,Hi@4q#5en@B/  @A?>hx-D단ҏ'FUA!K0r$'RT#aWW؇d D!I@oHt̂G!pK8A-b"MDGzEʿ04Sz&(L=@JVq R%^bH'hSV h (T2$@6 !Dh\*Q %aR4R0B\@JfEV!"qhĂqNх ui/@EŊ$4ՏTh{ge,dH.Gx#1R)R,G5 Iy+E5s(kb9։stw=l%K5 ի[@G6l:(h qA@FJBzQ1"pHLrCFLD:r% aHkLe$W>`6SBxGxY_R\& `)`@'QKMcAZF[y&]ɻ7)i SBjV(v-+XK[ֶJՁȯ1( fA@Pjj : >R*쿢" R5Ȼ:8B|A+x:#gQ!_˶Q(]QU/ԋ$'ΓPpj%kݣn i%h ŢZ|8 z=F[ MEEg-B9GpX@QK|kXK?i-H*4 H( HE   JBj[@4,"EXȭfQ"B4Tu7!|Th"$ F'.:~ RvPl W?}U':.ԟG˯CgѸ2uxpiٰ)@Q- pb71P! ء=c0(wGpǟ ? !"#IX)Й-5vH6.Nxk Q6bRR1x1ꕉ~EuB@C C4 WAY{_$S4` (Ռ: Wzބ [BV)gdaZc2K[ ōAk5pejҥT$hF'ձc%ȹyd%P]*!ꔨ{DžQ-P0M2 I(3r(0Wp61-y9ʻ]pE/{> aD_f.=0i=7i˓k=')~&襡v]"HJ B^iR+B9DBH'(mQvdB(JiLst)s47`,yp%1EYQE=V#5.D`(ʢ\V^K AХX9DV=^A `B<hf;{FA7 d# !bfkX!bQӰY"A$(‚X!L4j*V4@P!HA$IPb $BAdiĊw.SCXhI %h!YQc0(Qd1嫑!nÆFƄƣ@i|j$*e$F$ QceMPO$V@h~($~;xavĐ/fBGQ"g3C؛& H<C8N 8 ,@ @8Ro` 8үcHWͤ<0sV|f(4.&0h@58`IA G!u0= E (2 Aai :PZ~]5߈5^`qgZT-p5Y1Rח-SFKN/}9 >)zr `=ӁM0fw t B&!@!P`o1mPaW bq* , %LD"%lK`,ߜ@" Z@ ( %J"UsUDPoV1*™SHQ_A&ϥHc f P~8dvs1_kOislAif `N J@T҅%銟 )2n&/HRz$Șcm"z44hbd .* b*K r!Sg $#$uKʲ\Ir K⑎5ƛ`F1'^q8,(D%A`iI ST Py -@RZ/W&3 RH%@LT!M:QZ:$&(bB A@5q$I7UͼDYckQK =7 "B<D$k+"+W5ﰿW#raC?S1,4(%rg BSB;lC@e^i>&yn`23@vA\Zgr QV7@@?Br-YJ 2 } (NU@ h]6]>@0H:-MFLe- GJ@^~F@A 8d$=&N-?JLD!D`/@hqvR@8?*`5}jcH($v 5SQ E*>H@vAbp'| aABpnA%B(-j (%!@YWB P@Pm*I@["Z`}L ''l@4P|EIvRPp#DIg95R4 0(.U==E8J?P~9 4Kǥ]3 a!$:śzJ_$nC ӰB rd=J`7  FADA`aF#BZ#,kt*Ki|@k.qFh% CZ$upi\m4 bAG}F$t @6L5|!-ڿ#5撃w^I}jR!.TWdrna8K)*6X/ ĢGDXTb#d@B NXS q"zBaQ8zɤ(@)Hyā2!036 d+A@]9!H":cV݃U]s4+ 1 ǐ-8Ât@Ll)o?!QNL]cW q0)q4yyr n4%N*俯o@Mm =4;ZlQK-k[Y fZGhqb0C@$ 2(ș> /t0 K 0`I*`gKiTE t0y8BE9*8CL4:IXH@Ҍ  " zH3Jh}ر8sTFJ_* m[YHAHAeAD!HN@Щ h̀ W:+F)H`;UG221@JR1JKkm7Pf|.t́5 |M Жztp9@h&4(F}F(V@SA4N.&4SRIƃ$GB tH!A%B4,JRmX@V,X*0:@4f T BBzQ -@d@UAdn"BR@ZD6LQ@DjD*DJ@X= O"CcI2`5P\AOAy35P &-(J:@ JC*`$xP'Z7?PA@͟S@PYAD(˽6@;D6(OA Hjȁ @$@LZ 9HH;XFg y!2 L FH0Kv0)/ .(15T5G X{0?60 A;,bA .G| j'@ &j ©:@ (6}OhH @ q *K]Hӽd2_H#XU$whۑr 6 W@qVtX0G$DEAJ;bZD(B JF0  Tp %k݄W I2FnQ\AG D4k=!d|CuC#Aq8AkI(;9$&Ld،Nu#Rb~HYW"+&@W3D$$A.4 V" l1 q;jq V&39#fF$+{T8Ŋ R1/)yÊBT"TR8; W=rZ2GXb(5kWaiDVF$*;ƊƊV.*p!GPp&>¡(@ҘHbG(.o4(0"}cF!Р;L|),H! NKxd CyS@\ǠJgP CA$.-t"߯$e6 be#a*2IZnKfTDqȦxjÆ^-Y.% )IhGD"X*8G bXE!*btwVMc̱|X.$av" ;Ic^[䱚2: U%d J$cAi,Y*UX#n?-ң8E(QM7:_ؚ*Ğc4\qt̕XZ8\#F 3(Ni-ax Q+FPEֆ1t4N/K &vc? 2Q\쉄2@T!djFH p yvA`"S+ȆR}JNzBH0@ h䂃A vfb4x~Fq 2z4U '0!ȡ.%ƒ+ABժ@\h# ,?{˓7%g)HKf#H1,#mׅ4FC!Y- f߆I&"eC1@@a 1ɐ!baC5X3h}xFd# scp\AR#@ zUO w]܄j?\4v'9A2&/ѢE& f9]r#ʻ m $rZ5"m (a(b dPx<#Y:y#IU*c ") Q4k hr44 QH,ye4\/ @LV`(,Q M!\BdJPPAխKr 8w@HRCHc% Ak1ubpa`Nc5Ueu;JgV&hΚBHt$B)PMqG*00QJ(H1(@iDAB)K򎘬V(2WKraZCiU4B+*Ie br%$l3 2D) .v] lU h e4k4Y@0,A厂_@HSJP5̾]ӤE`B "UJ1kM  jhREDXTQ1BcZ$PBϐk9czR4ϐSjYXH,I!2#S88DF K0%A+BFJ\y`$CbA &P@xT-/]BI%5 #4#TH,ADDTє.jo٢P&J`(qYp6L"t|}aPdt#J  ERU"uqRc;\Pŋ1-^tcJP*4Pfj F9բQC(ҖV0Frg^~GhTBH ;GWhE 1` ](I (] o}DۄĢ$Wz>RD7#X8"O9hf7܇7R$bQ _ (8`()xP F Py(!1@hZB+X  )]""Sv+A(^?׮"y\$yy $|#&""B1mtݖB ji.1kJ.H'Lϛ0D@8#lA UB)qT@x @!PРGnXd:1?(q]S8Caok Z+jc!b@rE@e&-R*M :H4&v0DH@7!\n tPjtE#XHŪ:ӻ;v|wrDtj|6烋5ԫreDNS@lL褪  E? PЫRh,1@M)2B@4Ji %&FQlv)Q M6x ֘o'<#ջ搢:\%+E6%-QD~g r;Tb9ʫaAqO#1*Un%;K"U& 2P4^nXɁQ`  E & i6E:+/,tt:: BE7/HxgpBsjyqYܘL;mVÔCL(@91G@?KVmntt  m 5S3SP`Kju Ÿ@ H J}h* GHC/.F 4{(,IHKɩa^C^֕ϖ+G+ B W_B 1F(ٝbyW D c=]M0a9"+N N,EFY9iHR?g 2| *ФUu#'`r`<D<@5BAp/@b\[ d7usxt-nPsh`6ߧ]>A􅨜 H" 2b""Ł2e$Ġm-UK)1DQR3a5-jDHWngZnj!V#p#D)C/:_VҦeǓq1* (B28C AdtH^UPeRq+LAtd) FS-XZ<9.4Z'0Mӫ 0 Ab(*S jƎ@EaU$@ ꔡRoS`t"PJ2@(: CSIHvE 1A,Kv5 -Av-U\ *hUuu< q%(AC(-CСar1BgC1A(>@ACEqӒa qrAJͧ]Z8Sġ(`:t  @ hĜLAp!uZ$_0HPpd(%/jR@sqS1$D+HvFh1MMV(@8\QnƊW9QG:?X0  @ D>3G308A䴯E|P((%AR朣x&7 9rqST%G]*K$;zQ$ nA"EQR, QP6@kAq'py"!ŽA! ]:&l,.@CJzT<&DJ(P@(t%!!p~% 4B~H5C(a@VS[ _ BAIUF |s`eNY(,AYܢ˜NTR? lC+1R  ,BΕb! ej[ZՂHB({MC^ hv.VeAT'ٓts]S3KDfjX  ( rׯ_UI"D կ ,xoP{lqMd7|i@rgI"܎~׫*wkB:1hXij3: ?<UTœ @J-(A LZ&U!m-5+hwZCB1f w|/H\b;H. )Pp qCI%#Jc!ZR%E*tB_8p(ICLda@6KR4bX2JB:P+MV:HVJ` $@BsHZ05W7R% GVxis8!,G$$]=.1"`>I  i,i,AXKF ԉI``j@h4AHYbaVaJ<̑F@$_4@qopq4+IΨN{qBĂ 05pM7LW3~FsF(HľqXQ#ԴC9%qꊬaňl!gJBVKT1F}LqР x>:!#_XZH!_5@#?7@̓ [lexޠ]@Bh(e-/U8ԌORI( (Z:"7UbAZ@ 5@i]q#+ !nk9NCoCU0A`DŽEs+&D*:Ox31tVWB (WHPXhQY+C.pHK#߀,15_k:,%~_ 2N% VqBlT[r jB\ ZT!POK-mAWxHe"!Py EdơG4 L\R@ ?6P<h/LFMT r $=]vmʿӂ`<6O,A$A X@b4B%|S3D; g86 E PIj J>#CWI+ 1S@.a(,?d>U~OѼk40 (07)XH!*^@z&L!K7(^PfꁠR[8T)cD+3,$Q)!ֿȐK*:EHA!C*Q* nsbLr*AT&_ 2@nNrbBK%0_̫zz",=-*sq3<2S™"ÁӨiWk2i >oPmG ;C ?{ P`PFל, 5.M\ȝI-؋E[ϊ 5Oa  ʣ,\PÄ(H]B  _$@FBvF,qmH ,w@N(B1PI]Pvv!} :A$D݁(@ J`q(- H X J@q*2JUS%LT xdg!B AA I!: !^H\9wP˒-?1H;GѣbG6"/y !u(x(\W K_pqBwgR@jewAƔ,N,%U;@fѐ(EE(a`F\ hfD(OC/a}~hy¥K*3:2bQ L8CՒKGi+ G B]/hg")N)!h+[HdAaV- LH AĖ |1B:_rU[p-(xdZ`d~Rd|AHJ,cO(4 _i<K2{|&!KG_BsЩRKP,Hur bLA pд0Y-$ =@=pPQ\jZX2? 9 1 R'O@QJx2%7[uJAftqDE5'PL%kU"{w N\(hgvXjhBe$4~<0!o rQ OQYn $zHpRd $yr)% B J:B>T399gPCVЂ-  K|K`Lh@P0VY9k# If@ @R+ r^HfW\),NPv+ "c F;F|tɜP. 53šasT$dE$bk`Cr!PA aJ|%KVzT9+#E+A]h6U)p8b;H;lHNB+Ph dbgeⴄ]|F!}81dA0> /B贚9ljPay@-ez$ IFZҢzd[ 3sT$ʷdU,QM]XJEV<OH,"L^i@5V$8<4TdR(( Mq^H(JDA(y 7hA@A UJ Pb  PH Ti(*2$[UV !_.+D/h+4Q5.w ='_Zr/<"#gF<\iUs1+HM9Acя==lñ(MVPgjV)p}bs|@>  (k[KGy'E&J)d`[I-PgEIxJd,JCG/kkߝME*3U5 }/ OP^V((6L4!@r:THaEPhm 4cBZEe0ĭ(=PCA@:_MA0h5ttւ+RQ+ڵTpGxT|N C DACAxP6~*ј"|XpEx8R'!c9Ad"wDڰooojʆI#h@a)zy" ("dG$y^#ULzjJ2oB 3#M 0ބQ. AA;JHf!zag*TM!grHHT>zN$B8A*荬 "!TPE%$4}(@#Nl +K}JDɹ]_ 09O °"`Dr V{":W†do )>zDO@v]= Z]i", UN)hqY"!/bbM1LQ܁-1 "2&R"05BA^(\R Bݿ{e7 v(fRd)>$ WzHM+fR"0,5)gEY`DIEOX㲌< 80R zN>q%q i,?G c_ e7e_Q\xU3D";׮P .t)!STsrD%Bc(aiAn$% rBP p"1aI:5/)XƣP,U]j,JnӤYQ}/R H9F<!,"\1 ҍkh 0*< khx`S1DM jП/< "!o Q3$ Ogg#H- G 8WL JJD&Է򎽂gJ 2RWQX``)G"b+m춈E &48@d`L:GQLmj[\~0YǑm@p)J"wئ̺ǐ1ȄbJ:yjgPPVգEwI-(J}4+ʝNLRHD%)E/s  *ϳj5*d] hDd1, %w".pW $Jj0 @i тF" ƯҚ)'dy Ў?LT!~:$hJB4bЎ@j*sadV0*DR刅Hb`t^}X'@gExwwt45w*@I52T0#.(Ѧ` GJ="r-.&EC~FjJ@ 1ZP9bRC#R0͋HWDӒbbƚ:4)V QQZ(]t)5i7!Tbxtlx T.jrPǓ[, (g&[$2PҌхDsdhhU?ɐ8*q>Fux]x% \##p.MMO Q*܇deA"Sn)\Y̼26%Ghf =\щCO+(#̐NÙQ)>iV(Un|A6RMbhn>[^*,!&bW4 1^8#za1B 3`pV-* `\s}B9dfL#1xZ ga !'(O"46"m|/@:JAA7Jd'b!^Z@0R$@Xg  -YY ~ZEiV<4 5 'UZH!Bi*y0kkCʇXe5wHȌf.,|+ơ+|-2P̋&%H"Kk2pfkp 17wZ @` ):D% XRDְ(JM)Lf38fxgN8+JD%(ybDc¶BҪjMP ),$e0S`%А&m-7$<{jz9-bY-YR0is7˘+ h50YZ?Y"T-~ _:_7#fb  IxG"K(' !`e(E'JFOv Nf}CE $PKQPjzщa $ $bD8qkG?(@@MYx&`c0 ߨ9wC'yIp֠+K L? F4 BY Y $_2H rp?‚zC@#8@@D @9N” '`c@P -XAd$vUAj~F$!nw.r, Hw:L#_Yf!;f!(h$$ QphPe)"4V !&}ɂJ.rZI0'j*JR m+G!֊ R(\>QLiE܀HI.  L 5bq Q*̌~))$S ~h= _&@(wdX0T1H R Y@cD@M'+J @]@TM:P`tPaH2DIeQNPЊWʱ^<Q`S[JWPX#j$-~ q&D(a$q li0 b #ǰ EkVP:zHaGP 1P{YlwhEW4 = AܐJ@CE_Lb q M4 r`MSJ7,@ C4P 44k GRX,1^  b H$% TŌݫ6~'嬒X U,'UJp> EB4#acc$Pm PA*ІMj!BH[\BZ#hz mD%CE rSs Hge0+H~b=_ޑkqY TU;<`_zD9$QAOJX"NPyAp*DG͈[F+`D/Mz1m}fAD p[KU _%1EKgKL$ytJbhZcO) ;HǠc~'.YI;B0ΎVp*+ZtɪqDEtѢ;@c @]HZ+,jPP7L("PhG&;$,tz` !Q:IvxIy@j09U R R h%A R Ph BFH6 3B4C֎,6 Qj(j3IumkF\O*Lb.B>*wuHYMJU?i )Ef$2L$j1 dcH\ $KxYi9 HɦfS ?ՠh)Ҕ;+  ӫSBDLQ>DO" \qH 7D Ăj]9wvBh}B`B.F>E FWț $)JdQ ?ԥ@<8T7WԿ'Z݉̚Jdk%2IjL"H۬ES@y:@`(yEJH_S0P*KP 8t" -+Y\AOAQY'GqZl6_[P,[,zm !Rf `@ r ʦy@,HXE"$ &ӁŔ$. ddY J$GƠ b=l |  ,kXFS0̌3cTjc;1W#F%hH"C.(q!00Ae40ILJ$XKJq#L):HOUβ- Pa&!z8jcHbHΘ Odsg㌔Tw&,(IOw`4KreH5 zi:JGF(2HV QZu? Bp@ʡ ]0A&~ )&;G/T1 :P(Lf{&L2s¥ҏ ,&uEtB|jѦHi1N5P1$5gh3##$}=@MR]x]V PCKxGP![nvh/,FD"]g{:!G 2PKby !CJ 41Y0!T *1`+*g$` ,<$D?wo<(Q@ G 0dm2i b0c uڠ'Ggh 3U F  @4ED1Xiԯ I,4Y͐E_44ZI?А*,1 R,XDҥnl<:lW <( !d$P'4Ag~eZ^ʣ[,i1$Ua%B5ADo:O< &xV.N9HA]N`l6 ~`jnx_ n=[S/hTR`&j))RP% X/~(q6_B@ hbzu*$ Hb ]XL"3@Abή*|fؓ@.Q;T@ϰ `!_`p64Q^tjd (LP0'l"SkG%{ U @?Y`H ( ,0  APe }~ d,J* q8k֊b&-24Ap`q)i@6qvJ2\SA BzYQ "B#ajCtajCtBԆ RD-Hm!!*@wA_B:_nL<-Ps,t~KVY:THQ@4@nj鳠~>? ʀ#4Bi> c]? vR?ҝH'tˤvC1Vs2c?G%e, r\ÀI,D@@aP`U hAZ3B2Jv 7#!_<0JYox`ࠠ ,dC/^"\^ ,!nC0(AƎ[g`$ %@hHOr19 AO~F@8`Ü,Q ^`Ţh )}8J $ QiQ#A_E~ Q$ P%GC %! _zH )j} 4\-7|j)_O31~]4 ?ӳE(4~NwMGlKcDY NaVuߧhHLEs`(Dt JQ/.4kӅ$A~c>_,$kP!Qr 1ZzF,oG`6w @ Hd H$^1 *=!D0E'HDrICw"n*c[qB?oV K/$P[JH/݌a=ʀ傅0`#s $EK  Be?VۀP,Pc0F~C0 R"(x#Cn"&b%$T %=?2$($[Pb I XhP>8+0=!!C J= }em+ +ϰwG"W@%RkeF˘΅ :bӄPSix)%GװE`p(q:C@rl?@/{pAB]($ٌ:.HP,3dxHه`Fi`%FqBI05p8r,HGDpZ3+#ѠS" jNG_L+O*1 7䣋-\("=`& ^ ]p0^% t!3v@e/ij!d@QSJ!Za0ڌA54`Mo 6F#I.K  L*.HJTONL ^6@r? FV4 P!QPGD}|.4_pz~B(BJ(E3|W'g2?0 G8_B쓜4B?|@:!' 3ViH e"Yv%DUHkvG^H+@( k_f"*A<P&,a!An &xjAk" Jgv$BC֩&ݣ֑2Ȳ 9<, 9oHQ/bhLFrrp{pW;F O@ 6MH98w ?' Wm!Bt0? dA*^\*q-Mq#7pP}!LUfbim?1%#T_i<R Ѱ4 P֐@ @dSk(,8%HȢ@zѡF.,$aK yB@PUt4RF#`jT2 +` #)P(& !^yP|Hx BRz&}ӧU$Hրh01M6Z/ZGꀖg6q48Bk?E}D5S @E)26B|1Zމ:~T)%JH=/A^:Uj԰OzY"?}p:{ "tr~3A #t1X"zQVCH<S<- YD0L~uXrui EbN/jHmOI0((`$ H PmA O[AX, i53/E@,FDY0O)ɍ K.Q!B !!JaS)߂b lAFԔ@ /f A0$K|fEbҟ, I {'A A rvF g@ HUǑMH т ˍw8`vE^FȐ1/i(:j 18`$LQՅPQ+(EbaN&S(GXE=ɍh\vEY s<|@}4XUyHGCnyT%q$w4I@A24QĦ6TZ t %ڀ- ;eurh=rP)ɠa I JJ!BAh"?͂t|BbYVhtR4Jd!X|- &Mm@ eQ !X-B<i*>A(?!K%O dԼZ@d:߇]sx@a ᱉E3 | c@soS$Ul1Wa(6a @dx)6*I<g!'Za4o VJW=Fk}Xl($ADJN#`ELaotJY7@1lHDp y3z e(k_'gʇaY&(\(+LkQ!Ƴ0J(BD 00Z!N TywLubW-\u\9[Me(Y1TF֦.V0LN9BykO(ATH#AjoN) v $ Od`_uFQJ:u qHOYyQi肝^]`S2TbGR@Tt޵8xC,D8JDF>HQ'?i0^8O.(!Bj0էrg)W#t9P30LY>HMQM=EO6z$4P%WY(i!1k.0h6Lr$Ve3W𡮰c.1jm$bɀl8p }!rgFQ`$agQeM5K}#« B е+ ŏ!Uu,LBN`в P"h"A !8n!JZ mv(䡑̹fF砶x7iHW$!F#lhLkH[Z%DBHBWGXV?e,Eb> b KNLEǕ,;I#Q@J++fs+ΌƦ@-ЎNV%%:$LㅊPv~j1T*bU\Tf))qKa=@ /o(p#( qcb@701]7)c\8@RB-<! _ P ¡yZ>|= xS3BPfi0h PH`Pb-` $FxHT`j42!xd^:/ *:@TTXt]Nq K*ȡ(Q$2,FPX@Ih @V L!E@;F P&@6< V<:x3-@P\"Aˀjɝ@"qd,S4B@kTmP->SEiʯk^R 5$"#kSdB4팸"CzAŪQ-x*%9P( lAH d] ܠE/7E ~.%; T!@rBd\iE)^B )A e0mV^NJiU? )~ `4HbA$c)H3kw P+S@u1w h$@ PDl7VxErBԏ/hnA@ { ߒ4}/ ]xOq!Di@8B %  D@1K($1^AJgg)ߠ [ A@[ `Ly/ #D xt+ӣ1&+Xb(;Av+E+U{0(pu`(`<+&Br fph$8:Fhr4p3@DЀPܦڎZAJ=Fhp#z ЧKl3?RK2(x&"& K9h6NMPhE $}P(JRIq*f:(PH1D{rP1J +S" PZ ^kNB E# TaƫB(e1LD?D1We|ZI@\ᒡꑟBܠ *ˌH`(C򊉂S@bÕh[(M, 5|u҂=1f_1wR+@/uh O9(,&z3;^"hY)QF#G|+!k p@DUe2c ANRQ MK Ii1Q I0&WJg"&գT  'V)*,!A=?4@-܈`_Ԫ!yȂufAoX$l-J,+c>w&zQK@(tCb!OIGQ( `2 sHSt' `sׄ`aG&Ң~GUӚl?Nk0MXjM24)G Heˬ wVdPNGш\.Yc\r:LF i,'~ j9ƳEe%li($ p( qj E'Ql2R\Ik{ejCJNjY$?P|w!? 4Ru6>C)GnFh"(L䑥DT0s8 }YFI)/.3S3b" X (1#E ,BA1p& =c;eN Ú8˖|Q|0p}/N1UtCw{ .B{&b56Q{0y 5 `A%5ΐ%)DHA#r2>۠ DkUA{-h.ցX{ׇ &r U D :BcA(fx.Ri+M]`ygXuI5-s?H9D"b%YȠ  K9@ji(AM%2,W#֜4Ult|#?E<9?E]>S@+By-l Bk_RD+zcB> r8}x3oIH]<=CKh pbX<%*BLt1KCCm>=HDo'~\M$ P ޮKwsڰSH+ &M(ZY tK^YvDхR) /"]( wC 6ؖ9۵;dʆvs3 2"!bDŽ2@SaBt J$IR:Dڱpe"£!!x)G4sf B+"Tgd2+H RM?Ő(B?`hp+" 8~1"g<ɠand3҅Thx8y1d>&~ba 0G̖ <(L#Bt[y0W[|^J̟ZC\Y#INO"PV^x&"!,$=i?3-s>CCqTxRI'qq**Q"hP`ŤsbH o^FaLS-~b d>Oz!X )$[T#%bzf2Y4& }̹4>&EKDOtCYCJ_(caL %9H жW9x ; 'lO'gǁQ(& kr}aI0j5eB Q &2С $E{PuU,`up[\RV!E!MdoZ"=2Q auJv´GE13ȣ [?̵Rz3ȤNizE=٭d*~NHKuWW Fb+4 I22BC: BS0:-OL9\!-4`bj)e#Kke]HIc$]|*+u,l7%J%1%pOSĬ%#ۼj[BzbZnJT0@  HrF! scȚbXJ\ yX}Vej8Yd*? ]esn.&wePTSp;}!n[pAkkQ&*_"A; ]B!,j3$DcI(RolS@4N1C.FIP {P z0 hSK3CE!Cơ?:?ai5<@ XnɊ !k4 *rFRJ @4Qū:¡RJ(꠲y%ED$dǘiJQΰ8i*2 IhPxQJ$ +J8(QGDFA 9T5 IQE'!Z)H,%;@P4;谦`kBr<)r%AQu1 ?la҂"!aIJGZt֓C^gf.`ٜ˝ VYx?-$%dT$?iDb8 =3 ȃ!à K% \0 tw11b!r|(:CRd'$C'} ɰQVNnY$pP2qȷ*$D]Io( E]`Swh_՘huaO:v`Är B} [ !!jY٧;Qᔚb3E-*_D܉AEPt@yE3 `$vJVeQH_U⶛?»R%]wh %/.,P1I[ %R%Q*r5ВZ瞿_>)u[DԱyvE"{0DG8#D!b?,fR ֙?\vsu͜v0ʏ$D "MY#P/-IE8VAS2v%*3)S!5.G1FZ)!Z{OFy' IQ0'f՚%@0B F+*a 25#(ZJ-J24H$͂)@ BiFqe&J{}0,tׅ0MhP  )hJycPojbUň Fm1l};%+K"ZfcA('hiEIf,"--a$!OQCBn'H[=u"ŲE)Yd{4Io@{o| 26 Z旄fS$Z ˢUM24ތW`.Kq)68i2 `, PB  A,h?usXnU8C$wCiƎPyIVӨR)|pG[敓FO{Lc#%Kq&%A:,DZ!"/c( nm SW|pzisjT*jQ7f)AcYA!踖U;Ul\>2JQ`AzZO(yp>>;1+'k7$Hs< -O\ :$㕮t{㌼QVIn L EJ5l( BD, XK1#TXBQBSUHQga,ո f|&8:ejԊ ÙJ8Q!@2@x[E"R@m$JBѥUgPKQ$`v*Χ#"TU0`AMj\9D!VsbxΊK, K֌ *0a EZtQ⃋p;ST J3ȏ!PX`%ҩ,` ?6?9,&X$B?c1h#bPG=O!iXE$ =ƿAJܞ8.S)(QԎ0x(d2#}<-jŪTMbp'c“! 0XԼ:P餠!ap c./&#'V/D ^mzb!\)e/oN)RC8tpȂ8S ɉ@o'(L`]oE`*Rc@HZ+p5J)bH$H %E]|d@ؘ%cz a օ"x)da^}Dw3ȋd!sN&n͙`m*殷2pW_DI8 Y6癈pxJ,M/3qKN'a~ǫ2!6 (`9# 6_!">r-‹Q Zڅ"35ɤX&1{g))̣"}6)o> =gP-g i#` xeI5 zG* )QqOKGC3eɗedڐC $$lj  5.:(-==)s`s棡 (|ײrp +rgQ;IR[ffF(f?j"yMryhּtM;.L{͑Hc =*Q$RP9|I, b\v+s6 =,;Fw{NCf.*#1m#s&ֹIM& ՚ 0) #CJɡ<J*R5:@b!6z `Y.,4l)D1E,җP. h U X5fP+E!JBU%D!f$D!8ATW!jC$ fp!F<^!UAf<b)*T/iQhc'B_FWE|%{KrzPd+^u֎H;Lֆ"EZF#aXf_]tLU1h! ^":N/WsrFLHbLVtP0:* tTCBQs2ϊBƏ_VJ$!UJT& +> ZdڒDϘp>ZR q 5!mLbʨ, ??cELbJ ,4&WB P:eL9Hf`a1'Tf ـ" q,R8ȕKԓ$ %Hg$ZLS6mR'2JN$b SuA#iPx3R!C!;XBAV= Vz ٠PCf`$Ha*5SG Kp (} e|>@q!r<8 8ONe!5t,FU$RS$MO+5EJ !Q$8$@B2HD ) H0{8[cCRHPe5c,y@B B:Mi 3ծұ/Ys xZp9qG2u5Yv-_`E/v%` @ RQDY8 7&ʻ Pj<J*IYzJT=* H*`:ƠzHya*`UEiuLAeq9' *dtxA# z9Xxe|[,^4\Ӣ+TG @2v!)0vu3F5[ 3 1"cWR)C%D1Q^"b,NDB(̀!$étjA CeΆdH3Ll 9##LEbrC)mp< TxEp%n 60*(%xnPF^e!N:HSSU"su2w 6~D{\JA .b/+#cCsA6c[ȅl M2o;) 4%iaCh"3%l;K hq`|b$88BuOlC xaèt=*! O*kC$!P &(!$ 1u' <[[V IsZIηAFs @zj $cFJ*]J Y6e.]^K <@0M~AJR+k ֑RDZaVB-Z;-zBNĚqi3Jx?($Bv^<#hRȑCVKA+` BKȖ "B/b4xvqhMUV )B]@*Lҁ ЉHB"4dEy v @%HH%]8=Axj RqU ^_G^@(o\#QHHbRZ^JEiłU0%B1q' AC DR0 HAY_"|#x$5u!f<fXlAgXb D~^򪸓(0¿N+tme›.o d J_I|<So`hQ\K|l0@QH !*WJ@ I@w`!puuu>N" H;`DLr2b P:xifaIaFqZH!IW E  Q䅖N>""Jd5@| :*/> [%g` h|e26H%H" ! |dB(`GB:_HSғAc,hiha[0Aޥ3 j{IKx@G "Xу` ؼd"Ù%/Fޘ+Pyv@ `)G(,ʄ҂Wu3y v?R>:4/:sM&E/G$@Q89*򤯊yA:BR)iPB<w>`A,J $0<&HB#A;@@2@@C/1Y'IS (y`%AFUIb`L.:|;8Hh)6i Q%UB窉R)8k.|t֛P`pbDluCk] ,Pq% !Nmѡytz @[-#Xhb~T 9T <Ձ'Ѣji0UB EҎ= Jz "`؂DށűD,[i@X!yŃ/.,(AC(jIAׇ`ԣBD,Hij&ZUU/XLO 9/p ɉaPkL!3R91 v;1\XE,\,X;Ò@pƊ' 9Ble5QA F1^>r!`Ụ FcI@BXkS!BE"QDr3Ɯ ӥ0YW !΢:3d9 2!%2+͇JU*@.DH!%2Ū#"|/@$  YW:vǙxQ$-8d඄Z[V KA5Bѐ4F0KSya1g%{yYO^xOf 9!vWIq'#ʂI .*,HP$B#AI{{aiamDC4կ_ 2Rx.$~8W! T]#Rg@I,!W bK@hFIE*d(AA2+7qdP3uĴ-qi N|&~:I"ZkH΀?u0PБr7 0Lt#@t`"#%!*$4zJ:j,Xuf)ñ !5f1j#IJ$h`Y$HuS R%@ɴ!Ԇ; `f/` 6 DUC02mL%X'i dT!bdL3ꎚGiADR*.MI T `ZؖIq@ {LHe[E "Jj(鎄e?Ɋopt 4ED`c@<إ@qiwʛq bHK0?T䦖LC`Ve:!H^^ u=1aI(QK2-w0wPH $‰`)R<W42@Du8YtGṑKE PpRŒ*sZCWF)}}&N`R? OUNOUv@H]$#-Rw mnw_L0rPn`quÜ?DF N$ C9(er;b4aݩˀ",H$C _b вF HB? H1Qe>1oOT/l  a0 Jp[\Z): l`+F<`)xJ<@2~`4ETbG`X]xwLВE?},KF3h,4 @ tJPЬJnQr[㒄 TW3"ɜz,Q-xZ aآBH-,h@H>ÔC{xcDW0 Xq$@Ďzr~A| B8Z60x0k`Od@G_΀0v r?ʑ!D#M1@ 8V?U>jG~bpPjDHX҂rt-N>@)=>WP%QE/FgFX 7XQdQG̜# ߋHTJ1 $# pHp·*aւi "DI*?7YYrX+@)D)I<ch#+06?,ӥ.C|DQ(3  U>׷+J)# ɼoW0|/KgN#|Qx)mEJ$nXcg&0 N5נ za5~5>5ßdkyPٲ$ Bp "= MV R5]AS܀e-QXi@MUҕJ(tZ`ii:EFӫNKԀXiKFbkTQ zpDd`@hO 7 >0 mPIa%H?T@zb`/05@, %_$|yBAgыG/81!srqRMPF=ӌa@hV"J-#|CH?+?@YAؠJґ _xᙃE6a-)!BD@e..,%@cާ MB(\ u\boE(x d9U bAƒ 2CJ!҈iD4-XWPIڳBE 2 gBvT>Q""]@B` paŐr!HJ#@[`cL~ADATB0$3![hԑH 1"u0`O=NA* t} J hS Ϩ 3 +xCNPe+E"T;MjT"ؠT|X *0BV(! h y+p= a RHe!:!AńVH +`DhPB*dҧ(MlZ%U䜒髤$cB2&HBH)$ L|U"Ml*lb`h(@Ő,JD)Ϗf,4TAjLHOjH)eň@CCBd (Cx&b`F~MP^AL#J@]%?J?BxI'ա $ -/&h+wLrDf o6eDJ&L? p07́3@ L)5 7ǂ;'a~NxD`!(.ғe骵Wo A@Rt߇`gPbd"4b) ,R ?V]U9 rF^F $@P [f&iVP8n͂(TIG"#B e)q& 8- A24[܀e,.++A51AM_[ۮu@#OlGa.R3M\ a0fV0&@Μ(A&5<sl&t@_)xI 9<,_>M.:: I@&4+C ,xi]4Н  hev!dx|8Qͅ`*02C( ::t>/Ҁ:!T Ȩ. Pi7 Qi0"tL4Q@$b(PQ44/ @ & 8cHAtІLO0O4 ε[`0/Z&R?h! qR$QLKY kPt}r VOc <O"ІXP(!S2Z8|#`HH`3Au5`U7:\""4d;HaX, E!J#|> Py@,r^0C4غPCp&~Pl)Y8zZZAU/ 4XB^ZGh*_(d+<`^$CyB!P& @lACAXnZ] *20Q$C )>E?R%7ҐF"UGJGZP ;/`ODo5&o˿bfDɄüw$_-11c@sЀh̟CC4Q4tDdqk0řH/-J&~dߴGgD?-$F"@15ZFz;J,(*ihkII $  h*hZ.iOP! $M^dd ZA rAJCDP:c? DD4Q$qeb=hf~ B\_5!* Nƕ QFVj#Lq.b*S,keBVjLĠ,~X%r1@J]cA' 5gV00ha X фAUP  @z@PT AUt@gn ė PKbH5Nh\P0/P 1eBmxxŌ!疞K1t**;Ÿf][? q S}w@4\^^^"0 ~G"XY YwM裓  yD%Bk/pl\yPf#$5k2@`N]Q":i)Tq.E~)h)P`2_ h I )ESSDt^BtZm gfFZb A~Ø|AEYP RJS$+ShH$FJ*D6D9X H2%J*T$t5HH",\ԠQGT-PK&s ,.@$"BfHFh %`?vCyCa `9H*i<_/t 쀲m4W~ 4H4i!Bۿ PSLzͽpsb@w K_2bT0֯e Yu@ PrЂ'=ATI `| 5 L%< 1$99$2%[ DLxJК0?"A9Dx@I'ࡀ'E DI K  $C =0_~q耞7 @-EVw` PPheh]oC BB#U4iQxM5mϋ^mH`=@=ba˕.} (QIV*uO%,Aw$𐡈 jA^ } \y^03D(P /+j4x,P\"P_}$AzE$Z@ ?IhicqCFcO3(" DP++oqϙ_g`$3D0f?M`UtK_ 8g0ץ42_}% YQ`R38$ 9eA ʡyA//) ];Т GVZv2EװRZ8RIqV9F 8B;9>3/'Ӈ8ŏ㔄Nf!lӺ*4PNXB4CqXrԨV<u8$A B,Gh`DD (*0d`>:tӆ G)MB  _<:YBk?{> $@% /6b)}uА@h1!I :+naS _T Aŋ(J C~S( QK& ' RA@xHS,9Yѩ.0~IEHOE| , Q2٠HMH)ӿ i(r\g=RAQ-Ezc&kC؅cPWG5QiU3水. dv~ ;.EĘ"jh@@D#j,HIK}QO5(\)Y,3 @Y ?cèfC_ \T_jOM 0P pРƈ@)+F1@*G>Ïڼ< @ hWDXҵ$sP"5~p6:S9ŗ2=U@P0y`Rrt}D&vxfb9. DBl/#X]ȢL* Mj9cM @(:5 B K Q(EV0hBC$)k^Z%"K~*pz]+0JKz׆Oa` %!"~/tM$E+׊ƀ ? v[NL%KTԨ`@n B#,X9xe1ve TńT&F!Ak$}oG0a", iO V AiP̂ _K `ʐi! A1! PBta &$(J-s`E4I'G g BV@PAiN FI) A/-;!)) X),VAD)UϔGQ82 (qdH$ gUaT U\}y@ܑV(HhK 0jy_?"xDa#HF1e+)YJ8P@3@B 0!b0DE ]:b?STS!dSRјSn"LU&+? *Sƅ45+CLFɡs%͘E/Dp2*&଑ #|s)S}^ P0$,<B> c,b]/ z@, A@0f4`Y-hRs G#@ P-Hjl 9BF{%)%e| lDeE&J*(thK,&I,0!J,"PḚ4)F5Tb y&ARXéD j҈f21bŒ(PB (PB$P$EĪUG2r1Պ++ i/+YE byJ9:r"^"J<`a*Ra8j3` #A!#J{dpR,'m.^NKn#T)*JSU/kX kP& Pòfg>4FR5 ([!dXI?1>B%yd#R,B~zb2~C)7cpȲ%ȨW0ufzxLrOS#$BPǍQRyP4K%mxٍ|']WIA%~Z`0S H$sCq(4)!TkDA )"`BW)הtD"Aę`1Myb@E+'U(j3A/!̘!^Z\y%",X PBF(Pc *BCĝkBLP Hc.}F91'&.Ll0sqL9_qE)BRH3^@򀎆J"x)J=6K'NOa(̀B"Hev0lㅒMs  `H0" @e!f 18z%Ad <˽U( @]yA-$@P(PT1XIQ-q,K1ybh*Q%jp EYX$h$RRX- ۓV (#ʉ{VÂ5 !DH[13/PKB3`^H8jb0BU!kFSJqg˥7PJCW^BT(,hZB?OdF7IWca_ IC"`b{ WRQ(T-2`VAi 䤗UD9b89*BU*:/^E"Y %EU\ ra>$$lxNbUo>F"qը.K`a0"U%cG<#V FI O%(hĀ >_K`_W>!4'e&1|d9J1jkH-ڳ̙Q%YFH%y%bJ @$" (!#z:aM ZC$[$^c*N QRk `P #&ȹC)@'!`L?ˆ@8 )~8 )e0@> .H@S&Ypx$CJSr89\6 HJ SFs1j#TVPJƱXBPŋ% r@I&U:k\(²x(C9>8.r4|yr,(Y,Uu{W# S SAE͙m+@&QUa p0 d{d$2gzZjqF>(\+QIQi@$`2-DH")u$L@"RGaK&8]cP$%T  (1Q?. q$T"`Z-ˬCpL-JH ʬAtҠ Vc+Z+p(1+v;A WO'A)DU`frdc5+DQ 0 =A(B18b238)IAm!:mbfr,R&(C¤b'hJ[!C5 IF 2a*RN × 1BwI#$W鏒+FEZ*D^1B5A Ԯd+8HN2qd' 0a %@"$K9^#JX ӎQ6dd B)Hm=e۰CO!t^*uM;L2e0^@`#*?P[+ Ӏ"U 3 0DC11WY\ekmHA HBE990hBzrG dJDqB6eFQ+#?=I_\O(" P`@ XjʊE%]e< I:k+ $(  fpnMD-2$ BR%LSGQHƮQ#UPZX)b_,EKa՚f(GYC"4 U%Qŋ!(PB A@Hh-(Ƥ̡YC*y9 `} 4TξwZa [1Y(CQF< >äiBA HV4!8ۋ0eUS~a("xB```̒8[E mRp`01VZ”T j q P*!T>иE*UP $2*H b ȠQ&XӦ1bGP,A$4)(Xב( \ߧ'Bᦘ)ĺdߧEY֚9l@! ʛ$ba%(X S d! (r= DrNAQZU!@I B- ! FW`J0 %B P(-W>Z[_ MPRiNb 0GR|D6=)rap cDŽ GPR-Dyx-U\V̄(b(%2ΆNĒ+Nl#HJ)8'/|4*J]G*X}D: ܬđ@efe}-_YL B 4(&d0H9LDc(4t4vPfdC K?vxVHm5_LO( L @ >C2 : '@MU Ž6q±LH$R `t($ca%A$RT` B<gPqTL+$hò yjE V.%0c1ϐCAUXŋ(PB % 2@(hIBT#Ɉ j 4`M\hR(T圿1LrVܪR1R[Ovtg B P@@QU\Rt 4Ef pℿ)N IlPq9?j9&Suu"!H ٣f. `9zkd01" O@@ F FQh2M0.)CTy4Xx jB JvF5(84$ ##@A@QL8VLZtwXt.!A iZ鋯"KZ5v J&;TgNb@ABngMZ% Go@`&CT`PlU;karx+A%HRJM@!PPiQ٬AN=Y 5MY~PHȭU3Jr5Yldaf#Nd?vt'g9+̼6)YjP# < 3Qm @E %B g{Xq'dUһx!;y[]lz$*8v Yo nqP`<'N u d܄~k1  8;N :"pѡAΟ"4$L y04 {PxVpB@ ( @MX YA h"婓ℂPxk#,D%"-h ?$ J$6[qƟ" Lc3D{x&6dHO+ #'*T p_8_B E$DGBJ`c^PSR"qÅC$B_^2N x… Da: a@dSLjr%M>ʡ JU) Ań0Yjɖ$PbPz h%j(IG\=CH6c0Aha, D#4"(1V1Ud]pY,K%l'd#HGXBD1bp:E"N$ӑ) Id_|'EQ"80СBPM`]\c8nOct'ܿħAH- 0 a2#f]eBP9-\O ys R4@Qȃ REI2TmRIj8d_@@@ @#]e TRr1BCt!j@g @3("T$I>AcA2H!C:u_¢D+,H/ !*#-*qd FUe+ dtY%dv2pvBLB8` ?+8'}.}[:!P0P 0(P@ A(TT[3ӋCE9^JQFyyUhB'+ !BVaoTpH(8H"9KNK#ALa@$ )UA4谅Ad )CPHh.dyU02P)Q $ =YF-q¥? 'iZ>cmM6c8)ϐXQ+}5%(UE,5(6fŊD FcB5cQFJI!y#Cy;/ B  D d~׷agXM# jZC&H=vM @  )adAj@_Pr #{cH h@惮QRADc o BjEH4$* E*`@PV|Z1b * ) A&@&C.k{? H,pDP6"tiDx ( (JJ840ˆDy.fs2PAR߮ѥoEB(X+?/A'G 0hʠ V HJ'@T!a4(x?l(r VI&Q6i 9 ̋ 8FE 64,Ak ѭE(% M~@ 1x6k0 mAaL7,1"`g G!SZFl u=\` ".MpByC g8?>8ϒrLI0&t]E2 !&`%A)KrgPPk< K%\f" :?LKLo4AV J2I+0) F!" ب AF?e׸e3"G3Ɋ@$/q$D$0^ ?%'= >B9HW!%!kp}C9*5@,F3YFB / ,T@+!X*V!\I4|)j/G(H00@ `# p !JHO Z=$)+1h`n`!$YpdtR~xM- !-r>'`:2P qh,FQ= :j8;0{||gj+ɒX8Auc" `:@= mҗn)4cTZaa00*,A J @7@@x @J Rivsh* G:q2b(Y|x̀` 4G5B(tgFa_J  ,DÙx4<*jC1j&`*rqx}@$j[5  AY??T6~OuJz0 ?D'P#;ٲ -BH ?ڦZ@ &HaI Oz*.1]Tk\x 0ʭtMKa.<ؠ!pXBBE5}F )Q3hx:難: DNA֎ 5KUG 3{1qj?xZ0eEptS2d#drX=) P rF#\aXB. T`nˉ1&$Ę"LI1&$Ĕ/>Q,FoX p0 O@CF] p !#8ar'R$$$XUkWO-HD~ 2e] ("!W zO{ܾ+)Y /@h%(=dА' HLR@h#S| J e/W< %"3j@ H"9U\%zCjo0 y( P(QXvj +N;[6N ALb&i.YȎXf1@Ih$ Bp J!j:f"mTTBEQP @` 2CB)B$"L~X`A&>A|6(P T=?dCKN,p_@RB_xYh 6d2Qh'B] @ Ѥxy/8Hj81V?y T )B0B0 #}ʐl#X8QZ^izgL(B}pHmгUޙB J8A^_ /Wr.@P,DC89Q ؘG nS' ?dZ t#\iָ4 ϭg:&)ACUDM b/اgDx8iHS @A B#Pwy0HG؝@QGȫXѡ9G*#1!z C t*w>`NA{~> 0tT94x/g@ĔޭU ui z׺ 7 r| 8UHh۹X 'k_pp!s.t"ОB*A_#bɄAA.,DidQQf9Q&FBfr8ù;>3,^K\E̯쭁hTA<U`@rV!mNeJZ$ŔE9%=j'u[ ޠxcKhH%~* !p >Yz91= PG@B.GŃkP4c̀l)%``!Z*[.ﮬ$8%C">!zUhR@:[K\8f /,Xb (P(YyrB`&4E$ϋ` dȂlRP~C?\*;RcB A"}oX<&8:=JJ`h!HְOIڤuaSHL|a#"6v@]oϏ:`@@E,bUA*QuDjxIIRB_  `jX@v#Z+$!A!𠰊bJ!.@ ZxRA]%~r@\W!@Tf|`tf+tmW~7MNnNO~Ƨ1Æ 1DQapg )UNSFFyLM`2X![+c0iF] )-]:?5jPmsVy: z^:H%mUSUOKt񲶢@ʕpevޤQKyt@Ax<.UD@J9c1b(5.*POp DQ *( ,Ԉ,If V.P "GOOo)[ P3#'QeN9/'A텄ÿ4qd$35X-0iSAH/,XbPh!!AW )% m'Fr OvO:@TGkqx|/Oÿ,$IH,C:B@!1$h>%Z_%? MNLOM.A }>t@]}X!^t:`ntg23Ƅ`Mޡ-@τf=@`6tA#ߜ2@>WA>W@8$PD@ q\|.> ~~?O;@wGtv/K@n0L0P y^~/? ~ G~_ 8]e ^H CQP@ffw_;7|>`5K a,K%} 6l,Y0adɅ X " QF $a 2! yrbx Aŋ(PBP' $((QJ4Ǡ:Ad22`'O$P((QE*s1X$@@@"<bABӾ_;7|>`5K a,K%} 6l,Y0adɅ X " QF $a 2! yrbx Aŋ(PBP' $((QJ4Ǡ:Ad22`'O$P((QE*s1X$@@@"<bABӾg62}X `kK bY,Y,YI`Z xZ Q0a0LPhSB~#:'MiTE]}Xh`@@@@/,X>@P(((QJTCAXtL@  AABR9ϩ !P +EV!!6H (i!(Yz?(UˌCJfA)JR Pd&܁ [Hmp#x.s0C[Wa@`d4(8H0)G14WkRd9qeEq(1&4~$PldqD$ ^Xb (PBPi %@ "z@!C[AO#aMbH/@L4"H5HC#,R ?) }o/=ZW/@ UU@A|/ꛄ4H$I&Qo 1a.CFS(tJ \YC` (0;/(_Θ9>%=U;u"D "໘@_@- <uZV1LxSj(rBCm.<s<<2[m L 8^ 9At16!-'N-ZuKBM%zb5=OenPJwdn@$, ##)6P1x``%= A6z>> 8]) d%ĈH O Dc1cŀ@/PS A Ch <Zp?WHu2 d@'5@ Q$9Y{F`!BC  ~ Pe? fP|ÃN 7iZ4|ؠ_~s@~~@8 \$jKQXg$@73 *|&"ŸRJve0ɟnY#TXkWZL%4 `EX5Ba:<~(P+{MT_'I/ 5ƔǨl1y@q/| +`@-l7@`30f14)M HRB$(T'& $q#A 2%-^p(rHF F^d(!cq?B0 4 9 9 *T4hAJR)JR%!"blqgz 0xG+vo|pcJ@cHB&O,zM p34ɖLd@* ='hV@ ?Ԅ olIO8xĿmx<[6ۥe0r&2+ޞN@&JQ@"pd'N 82pd  (^> >@BUY* @^Xb (P(t t(֐3*#& A/,X.E-Ѧ݆Gp7 FQa#ddg {?@$H-P@4ܯ>$FX*h >ɉer3kQ͞Y+cn  & @@@/ =HB#WB1cŀ:UQ 1!Lap (g9+9 (7Mk~|||trHR9\EY)< ;M=pPD ,tb"P@kɘŀ @Ac;R K@x6# AE@>qk`)lZ`>Z(&"?@ ,KoPj}IEQ) S@̇6@L`Ro8P:0iJJҘęZh@@=`3 d~ |Ц4)!I HRB ,~$ G A"[NP BtJ d;ZB2(0 [а XH'؀9o6 )\_ $nnocc Pb(1A Pa DD$$J1.UB " -`$1@Af D0FHTABw>@?+ַ,D07ލ@#\!-UyADb9V++)8([`t }:YxXB]a`E<OMnMq(^iiiiPҡCG:)JRTRC@@U`Yo@}FH PWVŸ@bg?dB!ᑦ0QrM;*$r Aa*: d&LhAC0fSE$:PE yRF?^qH õF_'%ٿgř\ 7t xq~"tX Rr'G((e[2H3_3&sXI #$+l009@ASpeGQ@*j$tPV/}hA5P$rbW_@dّE}XrjIP$ϠBŋ(PB AE(@4 ]*ǀX(vh I:Jv c!lT=XaȁN” $CܘWm4`3O4(*P 0 $4Gh"AˆI% BV֣==&j 4ǔ@} x;O  7o|Pxd.mGPXYU9@ "Y'Fhg+Wu3R K$oaHW2)-lV "fFR`: OPGN4ǦUlz)ߴC@3ޖz}@:ehQJU1c1`wQBzjFrs P!N[/l[  cBr>B1%ࢹ8qB(*Vs0.N^Y"<7Q̀@d`Y 0tçN5:/`G(}E)@?C.0~"\#D"Q"F֖iYyU i8C+D""".{OI)He$Tx‹ #j"+)C i i EEXfMy qZR3 aOЦ$)!I HRBP'p'8NOc(1A Pb6l`++aXVW9BS)0) R)JRK@E0a !C|o2ɖLddtYg,L@B>7(l F;f~(PK`qZR3 aOЦ$)!I HRBP'p'8NOc(1A Pb6l`++aXVW9BS)0) R)JRK@E0a !C|o2ɖLddtYg,L@B>7(l F;f~(PK`qZR3 aOЦ$)!I HRBP'p'8NOc(1A Pb6l`++aXVW9BS)0) R)JRK@E0a !C|o2ɖLddtYg,L@B>7(l F;f~(PK`qZR3 aOЦ$)!I HRBP'p'8NOc(1A Pb6l`++aXVW9BS)0) R)JRK@E0a !C|o2ɖLddtYg,L@B>7(l F;f~(PK`qZR3 aOЦ$)!I HRBP'p'8NOc(1A Pb6l`++aXVW9BS)0) R)JRK@E0a !C|o2ɖLddtYg,L@B>7(l F;f~(PK`qZR3 aOЦ$)!I HRBP'p'8NOc(1A Pb6l`++aXVW9BS)0) R)JRK@E0a !C|o2ɖLddtYg,L@B>7(l F;f~(PK`q ZR3 aOЦ$)!I HRBP'p'8NOc(1A Pb6l`++aXVW9BS)0) R)JRK@E0a !C|o2ɖLddtYg,L@B>7(l F;f~(PK`q ZR3 aOЦ$)!I HRBP'p'8NOc(1A Pb6l`++aXVW9BS)0) R)JRK@E0a !C|o2ɖLddtYg,L@B>7(l F;f~(PK`ʪ aY3 aOЦ$)1iLZr`'p'8NOc(1A PbbC>'>^ 0s+ b·:i0)S bOiiiDɮ)JRU*lB<cu@M>'2ɚLd` Űb(VE ),{x O``\`L@B>7(l F;f~(Pi@cG pjU}>t@].A |'8pRKAVf0#0BD`P0>.=1dz7dg 0Z#D$ ϨBIHѢ&H?A΂v4a $ F{ "D|yB+'!р X+-0".\.> q\|y ~~_/QP(((@ߟL(7BĐ*_T) xR@zɐR@7$% ^/?y^~}(  @yO'(р-Ӻu#H"2a"`瞄Ѓ߸ ̈` H &E&̆QP@kffw|M8 `6_w|q :`]# `TqB{' 0XOBh(7p7Pq塌@<Â0 `?a"bȒ>sxp,Čxjk<@`" =f1q`B 0  DD#r\BFƥ1s`R`+A[6  , ӧN:~>(p(1a;0͂g \@'Q/g6хHLXQ6:t+x)$DRZE-"  @$a`CT[" ߛQ+P?vDIZ;``  sa\A$-h'(@@"0@.6 BAB)Vs1c(B:$ZƸyD"=X-Eb!^Xb1T(ѧ7;Zr7Y~.hH~S08r0{u!ґ,JSWP B/'?SOC @c0s7,Vi?}ČcxzРm!V{s$PQCgI ' 8KH˜/eCѠ%IȠ]p(@o^ddQ)FIu +N$! Wر^"z9 ů (,b4a_CɱzQ@gg ^0(;0AL#C$p2!Hz%,dJ"QD%(DJ"IH^!D@|q@@~z<0 hj4&h\A+z]#YT"@Gi(,&(*6z47HY? 5F;} ۚ HAflSAʀ #G%`AO{%`G&aX_ /&yĈHEIP:tr???yϿ! X 6 zh\|^"Li T`X`!Rp,c*~@O858"ѿJ)aq-)I]2?KHPAA@ Vax1$;Hv`)="Wn?mC} k1*[-KV#xvaB$AVZKg,$\}рY _qoAvR ,_Xd٬$A)H[!D)Eo MBAH&=l1{,H}ZGX A/,Xb (P !!JmHX8 &m@tLM}_N! ."@?D t=y*n(aÀ5>>:t>PR"$  %?אy7ըl0!֨~2:E`*Tr@h_8vjAL)iZ$w Fpj KDZڰ4B; +U4З1,| }o(IG zu ) C9SZ0$lO(:@4E$IUJth$jvP$ O6mHDm h@4(*s1cFTC: $";A(^p>:Il2huhFf"2Q( J!ȀxF@aa"J֝(T0pT EBJԽ!KE~%1(Q @[+ |o1Tͯe#Bɬ p|L#H 1\ߠ~˃1`=s,2f-QqSG `z< >Ё ?sCZ w;H``sΩv.Tl{`v̗<)|P@@~8 f &G0~X݁7D>J:G&fm/&CZFڕ{4L0/-K% w_j0T(n7R5v0E{!ŴȔA!BD$=ȖD%(DI!B B#5YKB2c0I@XEe8JրVJW nA T,?{b>ivJ8MH|p_{/]{qC$ 0! dFJ.Y7ҀLOSu # ?@*-<>a# 'cg{~(@eTP^bTj*K5~k[_$ 1 1!kY2Aɓ Op#di `Z;r ڪ R_Y 4KA\"6 8%,i1N$-\|0C;P2"9K H  A Wӣ^4D`yKˣp|4a@'PbX!>|bQzھ}|~"LS~@'ЃP;D R%B1>,%(KS}x@`Q!^Xb @ͩ@H&ʸr&ZH*bMWӧe  *P㤱q =-*.FַI@y$H@b\gC@2=ݾHW_ߑ%)D0}`d a#ep!H)$P ;&9$"ԡۛF@Xu \E@E9}0i0|"}ŜGL8 @@*8歈`]V"H`@T!EE "PFtU8th!ys4XJ'JRiA_ӐHg9ctu'76PZiJu6(PR*СR٦D*+@9# LIb @zH$H@z`jL %jRo, ` .TAAҗ0`UK/n;3E@ٕ]ܴ !G4؜xHPDd@XU XUXUQP@ffw: өl}yc|g < 0(!_dWg Xl=XmS#Za0F!bzCܴ:"VR _#Rn ݤ fRBk$(Q B ?Hf@CE6Kf i8~AB( = LJ8%U;8hTPAlFcȀr]YBDT ,,#Pl+ tޑ&Y&,0IH !~c*& P Z_ "8 N ED{ PPB1$w-/vrC0P11N"(\؅)T jxIa$YP6y"1  k~ ðߡ_JmyNz7)-24G$(MȵCUAG~PH5@Fe0 a ڈf fH(KxƢhW@s6Qa?魹+λZ~aKrƋPE%bOiB2ʅLPԼFvJ>#]o*bEТKW%]:(QhAxPj$RP2 R+E)z,FX # ߎ~%@ X `'1k/  E78u(l`acJBj9!p`96H2+F|3DAB_zL?zvX[pya 8@Mu@)h^,;b8a@qa@t!€wct~X+^נ hc^i(:d#&Z C0z@P,|=U,9I 4#@J`cl@GF( J$<#O-LΒBʄd".NJd@sy0s'|"!/ev]131`L bo fhŤ@i%CR &: @Dt z 4|z,-BZ(?# nQFh4:Hh~`6}Y~_$jl/T!D\@Z(QMfQEyLL%F'?BBJh^ PTzxLj|.tpTSFVD D Ỵ0YWa3zP f&6hjj̠ ZP@ 8h\%"|L @BTI=T3RO.w !!B`OߴwN #șR L"0&J̈́WIR`pGk/?(}XXk L[=\TE\,!aq`IG b`}.vhO]'.IE}">tHO]'.IErJ(H!!$C$C$CH8H8H( p"@Y &n,f6gְšſ4t36`:`I ͨ\"f,FC3h#`xd R]]BGк>.t} ]BGк>.[Hs`$s`K )6Acd6Acd6@D^dgTa\Ԧj5P#A*gBXm|K c,я *Y?5*gjT@/_?|/_??@@{ rg rg r 7s }1} pt -=r]=rD=rD2f͛%5)39<;C9vR>;8p wd. <A PTĥ?%%1м `HddZ`c.(P>b9F3asZ=P2V_%~JWRe+)YJVR`@B"DL[(.a~cN.YoXa =`APXf:?+^ACf$YC& Cȑ/c0fJƎ#v(,"I5F1LxLxLh1cD `0 E# STdEeȇ@@=a pcŃ 0c NI A]h``_0!AO.kkQϗ`7cG2apӜWF8F@0QљNZh ,oHPh(t)0l@@ __ǹ*V/X PT222eKdY,K%6%<J!ӭXP( @h$}?+٤+ a)*  `J'X,_K^{.e̹e" `C+@2`!OV|G᜝8"E1*20D":#IJ3Z # 3+|4hC_ u8PitXDVD`"-44U7_jXj~rdsY c a0H$ A  B @!&e8B%A`!1F ]A$ C"LUX=WD)T \U136f̑R*Ea!<ˉ+W4$h/_ *8kK{.I$Ȇh.tHbw}T6vE}">t_X ?Pe e2*0m$@1~ %9+!%"E8G2 ~( _SSm)-$0P@W~(dNa4EA*©eB?9 2LC<BLAm t} ]B ddd>.FH6͈Sd9O33@o/U" PTܢ@u92ZBW 80  L+ _u( AB';@{ il3WX@UpyWP݀Wgf,_Ъ%*HpH@?? () (QP@ffw0]A?A%SjJt%ӘRJ`9:sINqgCY2ilqfCL'W2d9L<`+=DACCFz_@ :@~Vl6lANH9; D"ry Fvy34NG9Δ ,% OT@P )` a&~ VP`C#`OGJ@s@xQހ;rB@z:,XɁv(BpФ^y^~/ Ր..0 #(;LAC((u :<"?E@a|J  t(>}}%@Q5S=KN_jJ`REy!y!8H (c! (6!QP@ !ffwʨ\ :Gc W,"Lq‡}͘@)rv@"#rBnX# һ=R 0#@GWČ|"Aflw݌](&ˌ,0< AH' }ضť-!I HRBd"@? x% J'Q-"RǤyN@X8"`6#ȌQ)gZnߨ 'շ`ހ<bHH)MlZbӖ(1A Pa/BL# BEACB *A9#+an)JqL_3`E8p u? ;RbSWb 1)9?ѯCs?9@ Vh4%+]c<7* @_~WԳÌʹSj 2)TR! /|#؁)ڭ Kӎ Nָܲ F0EM} %$q.B &{I%)Bkh&@l8q @([ b.~ -p3sAgh,õjɾ60:āw&4(Wd6  '`!ߥ ~RS2]_e lؙfqfAL5"d.0lP!;|`(4Av6d2}~i."I UL^(1&4~$PldqD$ ^Xb (PBPg %@ "z@!C=e/,. ( QUc00r|ہB9 } 4(@ BbĠ@0GHE.a0(HҀ`!_Nɀ?$r?ƸH$ FnP,& 8SXzPUE:S" @G6:y$b};\Od S$04 .DğLQxg](uҫ8M|Q| F| r9Ss GRه\ 9At16!-'N-ZuKBM%zb5=OenPJwdn@$, ##)6P1x``%= A6z>> 8]) d%ĈH O DDc1cŀ@/PS A C8%!bI9B-b+G~H<<b<*9dUHKx'0?HΟ< c0L@<{E:tӃN,Yaybҝ`;wN|%-C#VOZax= $744T l%ή 1OkC\R~t?VEB4$KV5Ba:<~(P+{MT_'I/ 5ƔǨl1y@q/| +`@-l7@`30f14)M HRB$(R'& $q#A 2%-^p(rHF F^d@CAD:Pq)q##?@ N? *T4hB)JU*JZ *B\+/P  0`K $@$HZ #(1$J@"@hF:8Ҭ,dɜ"G!> Ҍ&@r@=^:Og>Jg%Q@"pd'N 82pd  (^> >@BUY+ @^Xb (P(t Tu]u R:5#R8@ @^X|rH_aF`yyߍ5F6qD0e!m44Qs 0BÏpgh$Hq$< >DAlQ?el082E:P %@@@/ =HB#YB1cŀ:Jb_~s((QE*sXp (x!G3╬i]1 $0'$"Ea&pm1Ճ檼Ahc{ '|00@0"AE@>qk`)lZ`>Z(&"?@ ,KoPj}IEQ) S@̇6@L`Ro8P:0iJJҘęZh@@=`3 d~ |Ц4)!I HRB ,~$ G A"[NP BtJ d;ZB2(0 [а XH'؀9o6 )\_ $nnocc Pb(1A Pa DD$$J1.UB " -`$1@Af D0FtUE_\gt?Kflp JU[U2bC8x@ѕ쁀*ɛ+Lg՚#sqx@iʠ5Y?e@ CM@snJ/dW8rrrT4iP΂)JRJ- X1Z*mh$`i0*_307O w9ȌLh} ha c_dI&wpg/1{w(,dɜfaɃ0SCTp )XYU9@ "Y'Fhg+Wu3R K$oaHW2)-lV "fFR`: OPGN4ǦUlz)ߴC@3ޖz}@:ehJU1c1`vъBzjFrs h?@G 3<  u#)G ΛNSnucCUi:];̀ ` ( <qZR3 aOЦ$)!I HRBP'p'8NOc(1A Pb6l`++aXVW9BS)0) R)JRK@E0a !C|o2ɖLddtYg,L@B>7(l F;f~(PK`qZR3 aOЦ$)!I HRBP'p'8NOc(1A Pb6l`++aXVW9BS)0) R)JRK@E0a !C|o2ɖLddtYg,L@B>7(l F;f~(PK`qZR3 aOЦ$)!I HRBP'p'8NOc(1A Pb6l`++aXVW9BS)0) R)JRK@E0a !C|o2ɖLddtYg,L@B>7(l F;f~(PK`qZR3 aOЦ$)!I HRBP'p'8NOc(1A Pb6l`++aXVW9BS)0) R)JRK@E0a !C|o2ɖLddtYg,L@B>7(l F;f~(PK`qZR3 aOЦ$)!I HRBP'p'8NOc(1A Pb6l`++aXVW9BS)0) R)JRK@E0a !C|o2ɖLddtYg,L@B>7(l F;f~(PK`qZR3 aOЦ$)!I HRBP'p'8NOc(1A Pb6l`++aXVW9BS)0) R)JRK@E0a !C|o2ɖLddtYg,L@B>7(l F;f~(PK`q ZR3 aOЦ$)!I HRBP'p'8NOc(1A Pb6l`++aXVW9BS)0) R)JRK@E0a !C|o2ɖLddtYg,L@B>7(l F;f~(PK`q ZR3 aOЦ$)!I HRBP'p'8NOc(1A Pb6l`++aXVW9BS)0) R)JRK@E0a !C|o2ɖLddtYg,L@B>7(l F;f~(PK`ʬ `\3 aOЦ%)1iLZ `'p'8NOc(1A NbbC>'>^ 0s+ b·9ik0)S bOiiiDɝ)JRU*lB<ct@M>'2ɚLd` Űb8Q)$T8@q` L@B>7(l F;f~(PiC#\B?D of;M}>t@].A | '8RA0FB+FJg9r#Ȍg"1H07 `F#o"k`g)IK2TR42Y U@ ~b^r Ą  ; w20b@ x`\.> q\| ud=G=^a,((FL+:%:Dt(]agf(? D@-l$#H`p^/?y^~(  ut?G?_₅  tt 4 ttА8@zd@z@8Ȕ22H & &QP@ffw|M8 `6_w|q :`]# `TqB{' 0XOBh(7p7Pq塌@<Â0 `?a"bȒ>sxp,Čxjk<@`" =f1q`B 0  DD#r\BFƥ1s`R`+A[6  , ӧN:~>(p(1a;0͂g \@'Q/g6хHLXQ6:t+x)$DRZE-"  @$a`CT[" ߛQ+P?vDIZ;``  sa\A$-h'(@@"0@.6 BAB)Vs1c(B:$ZƸyD"=X-Eb!^Xb1T(ѧ7;Zr7Y~.hH~S08r0nG4u!ґ,JSWP B/'?SOC ܠ?L4v?`s7굶;0KdT@ĐE`2Zh*NPa 8y ]jrJcĉRFr(|M ́< `:?'BGX=>iZ2C@VZ 567]gg9(d03dk( @c~V B#!BC,dK"QD%(DJ"QJ@"@B 7DKzRAgg8C%,6!_` I ?i(0&(*6l&ijoQ,ݟ Z)O]@'nh1"`$PebrB䇑tyYBM^"?O{ODy@dIr EqUӧOs~B X<6L"Ш:ł4Щ 2C9 )ir^lTB A)yMTXBF"h)֌͡2?K)g#"AA"&V HݓI4ʢq/"蟋u~?`rri#b&r@`OvaB$AVZKg,$\ˆ[YPl\P`y!ik OL5YY@2P"  `4#В#I4tAqJ>$@^Xb (PB#2 @74CtC(. EL.%L01sÎYt=y.iwXWVߟN7jD%  PhQ-6OӈP4DjW&AG` HCD4n^i`pEy w Fpj KDZڰP(K\1,{8q\ +V  >5IVT DRH8]TP؂) Am h@4(*s1cFTC: $]cdK1RI@HA1] Vām2~P#_d!ZWZOEVjUQŋ%S1.GF4|^K_/D8~.~%,G?͌c*j|C A@p|L#H 1\ߠ~˃1`=s,2f-QqSG `z< >Ё ?sCZ w;H``sΩv.Tl{`v̗<)|P@@~8 f &G0~X݁7D>J:G&fm/&CZFڕ{4L0/-K% w_j0T(n7R5v0E{!ŴȔA!BD$=ȖD%(DI!B B#5YKB2c0I@XEe8JրVJW nA T,?{b>ivJ8MH|p_{/]{qC$ 0! dFJ.Y7ҀLOSu # ?@*-<>a# 'cg{~(@eTP^bTj*K5~k[_$ 1 1!kY2Aɓ Op#di `Z;r ڪ R_Y 4KA\"6 8%,i1N$-\|0C;P2"9K H  A Wӣ^4D`yKˣp|4a@'PbX!>|bQzھ}|~"LS~@'ЃP;D R%B1>,%(KS}x@`Q!^Xb @ͩ@H&ʸr&ZH*bMWӧe  *P㤱q =-*.FַI@y$H@b\gC@2=ݾHW_ߑ%)D0}`d a#ep!H)$P ;&9$"ԡۛF@Xu \E@E9}0i0|"}ŜGL8 @@*8歈`]V"H`@T!EE "PFtU8th!ys4XJ'JRiA_ӐHg9ctu'76PZiJu6(PR*СR٦D*+@9# LIb @zH$H@z`jL %jRo, ` .TAAҗ0`UK/n;3E@ٕ]ܴ !G4؜xHPDd@z v IQP@`.ffw: өl}yc|g < 0(!_dWg Xl=XmS#Za0F!bzCܴ:"VR _#Rn ݤ fRBk$(Q B ?Hf@CE6Kf i8~AB( = LJ8%U;8hTPAlFcȀr]YBDT ,,#Pl+ tޑ&Y&,0IH !~c*& P Z_ "8 N ED{ PPB1$w-/vrC0P11N"(\؅)T jxIa$YP6y"1  k~ ðߡ_JmyNz7)-24G$(MȵCUAG~PH5@Fe0 a ڈf fH(KxƢhW@s6Qa?魹+λZ~aKrƋPE%bOiB2ʅLPԼFvJ>#]o*bEТKW%]:(QhAxPj$RP2 R+E)z,FX # ߎ~%@ X `'1k/  E78u(l`acJBj9!p`96H2+F|3DAB_zL?zvX[pya 8@Mu@)h^,;b8a@qa@t!€wct~X+^נ hc^i(:d#&Z C0z@P,|=U,9I 4#@J`cl@GF( J$<#O-LΒBʄd".NJd@sy0s'|"!/ev]131`L bo fhŤ@i%CR &: @Dt z 4|z,-BZ(?# nQFh4:Hh~`6}Y~_$jl/T!D\@Z(QMfQEyLL%F'?BBJh^ PTzxLj|.tpTSFVD D Ỵ0YWa3zP f&6hjj̠ ZP@ 8h\%"|L @BTI=T3RO.w !!B`OߴwN #șR L"0&J̈́WIR`pGk/?(}XXk L[=\TE\,!aq`IG b`f*8N`' ,D4d4ēADK"brR BA`K`!8 !P )CUHQ  PL\d, @DE% k "  PaB(*1J𜾖Jo "`N h  @(@bB&Pq*W   @$  #?g%`!,D+$&P@Q_0P" d hz $#P(F",1IUO a@hJ$A0(RBcd@! <0b!JZ aP"H)(ZRQ@,@, J( a "`@{&" S@A@P%Ce^G*,Wp PA @@$W `T",o%@PDJJIE~ͦ@H  % PDpP1(F*"0Hq`m #H/ #\QA$:@ F""WA @$  <0XY @А E b"P)! @( NV`0 O @ʍ 1(!L@;8p wd. <A PTĥ?%%1м3 K´w$xI2}"E)K!koFw@<PctUb1Nj0-@6Y2r`QkւH(x 3(` $H_`¤ Z}ߣ02$GV4r?^NrDh+4*n?F  ?zO( Qsކԏ%RtXP aB n M&7ɣ%ZQ A| "$Wi_Jbq"4c\0-JF@a" 5[ramy7cG2apӜWF8F@0QљNZh ,o B>L>%B'gx`d4RrT_e's@q2 - gS0E`c *U -?L 2Qrc,5 $?.\ %@|L =bbM!GG!z;u/B+AD )=k"+5efI <ÑJa5ZT I axWy7XǙ`ygLl8 8,b>f/Ӭ @P r9pCIVê >P]ԃ 8@D4D( &@i R %ZW\#9" V?CÑ@z2Ҥyg&l;Xik(z(%qu0dҵ -mq(f Lx&"EL0Jwo5$JB< CCa*%Cx>!`$T6qޠHp+C$X jXb1 t!x`EP P @NXτq&K >\w@hBmkx@d4DC! F,ᑨ@uGq"HŜ.I9'9Vs)X)KV{ YԬB-VJR^Z)b$`ykF#Qs'f*8iTQY+31/@ B$ (t-2,&r)T=~d s(B5u "XF@@ &,h-9n ;N/FC0! n|I6Pmb X~䓻׬<06,P]Z4yFĖQ>/1z&(?7qkj!A\! u>,x} ]?@ p怠>B#8g?Nn;5PF*j24 E!F  S砒(dI-HpZf Oˑ@R %"I|@Wzvv'aYEA%9)Cj@u:[@Pό%^ rcXLHWa"DJ# s 1 # Za0\2yGмLҤa(94$_~D!`@AA1 (ml0NG.V"r 9|@    J٠8E w`sir%(bO  h-t!@PТPAIB_D^~9{5&H_), l(P(@EJ_(x^?@)ЀL/" S:Ӻ ЙVz?P <<@|^B.B">DB _">D9P9@F2w)E`<S,:xLSry  RDD61Ο/dd| p'P(Q He*TWy?lL  `@fAHPpa@JA$ @M#@r&#H 8 a \0pP!EP~XMP  R   DP)(&P6j  0%94RNWU8P< # ł"$,S? P & t#" @b A$)YW;M$H @$0A` H@B $Bee "HA 0p㘂W섀AhB`xYAa`@@K ? ~ ZlC@dKNSLIA #{Vkr#<$ E DRR &HSHGJ .CT @C5+&g@ dNt7>Dax`(Z#X0K rr9=jCpEj)qw6`hAAY~ ,~>?%#&F Ye_B0"ojok5܅XJ,.KGG k@XtUqUh"uu6e t}[Ox N!h3? *~kAv  0 7#AbLdj Z.P F*P$N,"IY*rU&||\`GQh$ [?E+cJޗZ` AHDbBKbu"l 2 !r D(? "p@AC+ @pA oS4౺Kr%$ȈMpe5CD2 LN.b̥xWI,u;E;+3 cl7.P?G9XXpV$`@C1|$Ha"ce@ D.82vy0h@&"B8)22$!_>< \0) I ({̡tBJ))E 3K f䟈V?< >U%4R D0UG#U idO_ r$iX8ƦJ1!_VOɄBՙP镢$?DK`g* ,LPR1@ ΰ$WA!6L]/5Y"w'hq Y42&f>WFxyc3X `bd@`. X➱I2AV!R*s"?T C4B>jBR * r̈B(9. GQs0 ?qHF6)iS4 REM @D:C"ZGBqjn}N׵  Yh÷wr#quRm-+Li(N.z`ޮǞqU" .c\  j EP} <, ȆGP " DO$\ՊF9xJ_<m &Yvƣ ]GBm'ߵH@$: gZ"&P.A0 JN䡤Uy<@AA G&@)L`( M#A!^@*ocxgsvB01P @[ceۇK8 ·+@SU+.?L`dPh$$(STGtҨ;%gՂӑbQ#hܘ4܇$ HqTԐcW0R-H)_0!>1.R8=#2p`(C.8P(BB0 wP;\oJ!EbQ` =;`P |I&XJ*c jw+v _bSkH\;e0fUHF ptmElgHJ$RͧIMʌ AH?BzSڊ`EJ?ҢE<0'{MқsWh^p4R¤k2;L]VdxuTDh & :h\LN' Ax4V]oΪ)>֡uJP $d,$< @ʩ| $BUT! ifZ  5 %U(cE4Dˎlb}u\|f DPU//G*  @!_V2VJDVD$KL4().P"10!U ȇI+."6+o !AhGXt* ^y1{bb! P [o/yi* )їe#.#UE,CQFA2 AcTzQĀJݽ-L#AUuyF, "ȵibhE,b&*$ϠQ4Dr1%#A6*@!.٪z;&IkI{BWd Q`1'?HSWSeJL]cVnFY~g4i pq@$| W_#ِY / 9ZD N )cBB}J5ÀTx00HeBDXJ3A]L"3sv TDATIJ`T<N A \)Uy-R B> QTyy`Lj iFh/Y׵5ب/*,+j?}!YvrZಀ8^ K?6@@bhp(/@ rA +_J%N"f X=*k/d$*'D% eg8yA!M8 >"Lc- 5&^C6v?)5f~Qr\FOIJR? f`Qfhqv 4]NH#m R(jJtK10Oqp' @:C:@ BɡZKC+_2 DF ft..mA#I{נEt) PI@;%@cTE!Ē0"IS2S%Iʲ'pP*&UU[T}ꭁKxkY)/K V@0 COW_,d@P,Z=p%BA.n7i0aM6&R߰ e H D] 2)`r"QԆAUЄƂEhf+2XmFJ qG" ڗB'# ¿`(ϊhAG9!fZSOlT`x 1x7/A(l}>Sj<"J(u4yrjhw 8 0@4Ax&TM(1bD$PI?*(Y0@? 2;I{C!_ H~5 p KC 2lĿ;FO\!*pۼ!a!a@ +tfG0XҸQ b `(|piQ\$reA}LO7A yiz+}GxV.Dv!N> TY||"U Rm *3D%BF>%|7 Cjt4SX !]`&B[(mƠJ 4QK*0X&9k@8K`A T!ջ/ GU!.,T}oM j@FM&C-{BYH)4-'Ł"4R2jARCል$*E4@Go@"mD#?& kaڂq 34Hˬ1!ZWP_@u0HEG^~/? >\ܿ@  'ET!@})( .@ktEO /U\B]-[_q.w@,*(ȆBBD ,BPƄ@;J" (rj%8z)ZHzDEH$Da!*,Xb P'P 6L>D8*5 EIA =&";8ݒQ=ܴ yy F8$)@(*&jVr_U8L#-xTZAJ5b( 5BۄDڎ\rrWVi2)z0m9 J·"`}/+8[rF|v2E|yr#@) [ Qk} { ARwfAS䚇1@lo0I.Q4#0~k@{ 'Hx{C8G'"?@O )%4l \] j1ÜFU+dIycq7 4F<ypiӀ K6{}lIw@rހjo@6q_?@>|^zjjF`!M }R1$\Y膱Q'@ AYi0CnAȲ?pM,_!%'L(/48esIQPe0.[ 8dCdCqun.D^G^>Q""""^4:@sX-3Ӥ0\GHj@AkNO(LB|/ QY -!DMqKB^i%`0XGi{(ɂq*@ C%D (4"0F)QHDL%8JA1(NE( `4{'"@$@" pT IVE D@ `ʂ 8=JWI0Ծ_IAvkyDVtp9,*QANR6ck?*]k BU5/ J (@1u7"Se1(2 ?T4T %IEqa5B5@WI`hBpziU>N((Zmi ($h<>4&$@M Eq䋔@n% @wxdrAnw"L}C[.?T@d?;y&J "{Glɍ1 tqU&h  AzBlI`҈C-%Hj`0L(D8L.""L0DHwHbK )UL!HRJA0~<@bW3 CV$QibTd r] 3HtK5 Fm=?r׵" A}k?}AP1$@PF@ .N?< ȿ =2Na7x5%8 d%`m՗-!p=H @ ^+u6WMWQBt|"tT@w 5'yep0p i>4PÙ% h&%A@DthA,A`2 b. BAJ*ʆP!@aR=% B4jjC @9+a XEa?`UѭM/ۀI:M`\6SW4MUҡj} ȽXw-@l X@bHۣLF`D!#4NViOF_*= 6`y 崑ğ(vB@(4aEკƸC 4=|x}o06bbE|G@ONa\ bTw09TGC&r5y!?W)G1~yx8A tÿ_!# ݺ #'HEgukwӊ%21ːte;_~!jA <8<`$@TT*i(Ѧ$*98SE+<}z Jj2t U">|XrC:1C.!1O( \ A* 1Oy2Qa@~li/ XTr9ZKb,/^ )kK#AZ;H)/F?,_ᄏ& kbDN‰ * 4  pG5TYpX:A8B9C(08lGh(tPiQGXU%3CiLjz|TI4`R9 xNh%v' A%n''mNM""K͢FŘTNTp_̶3#@fzHT "(mfL-9[*@EnS J79I'gyA8q $=JG`5 Py W^]C0""6lo1 <ޟ)!T!S|?[[?!YW)2V4#2fj`y!W( ^y7XƟ҄\Bsz<4$\hhBiF(?~,aٌk7a2$NnnV/*n{. קn(1ӏN h;UҤ7>a/]P" t 9 *Puʯb4"~DBG+@r頊J(X0ȸAZԤ * d@GK8f9!2iC J=J,.ѠP ps?PX( Ě-Jvm J _iQF&Tk UB8A55a)FkB [BXB!WPⲁF5_i_KU@)V/t T@tR`}X \ iA"{8G_V*Ydup:$F8T~NH e2t9N%@XCk ?Pu/3 PQH@G(bHTTt&!M@km^?^Z! N2@#NPG՚ٞ<' C CƄkhr? ds*QA1ńxk+9 $^ Pb @ER =2BU(%B?U  f@'0P0-k/ #n>!!J S< 7=(_a׀EY dbtrFZV*tPf ; *rRJ zaԪ`[8<\'@!&QG}@*u"AR_/ф+>Ki>0*M2 ?`A*PhG1A >a@(w_,#B?p?:-*!4?BU'` p  np@10㳊# +#3(B!:I? - gn0]AL5q%.LA?t, G1h+s:+`,3IjnZT T8ŕj}2)yA,%p nt c8(D3>RPDR+Ȁ!wm:oB?JTBxU$ -U H('HX/06F(@lwJ/SMP;F4%W!+_"K5HB|n0Bd4@-%ŝ@V/#C 3|.1NjY O?/Pſ1@Bda8 ( a캃eJZ #,dj0!gB9@Jb,7 @|0@44Q@0:@:&*1D 0Ui@!AkQ Ah6HGҪ׀ף69ePO0O!!-,WHՙ %)@FҋOWl|C!@,u4qC @#=R+T2/ d hψDY52Y(n "b@(0Dxz 7SE`B@}D/Hh `r*V Wؿh AZJh@+T2&h8NY F?ɴ) ]* { |?@}M=  #7gfbF^W`O*Ur1xZ o(_ʔxٛD0(N?xn@dxJA(G N~( 2PtrJiJw+8C;M5/ ^\D Zhy6*z#E R+R8>/TF`!u>I٨ @R- iShz 'LG $0!=5HY P]UE G=QL4*|Q}?&P$7@ d+6vh~ ҡV\X%hRGz|gaRGf #Pax5P->S^~ ,%,I00"'B,M%AoRR L#2C%JP:Av(` vB ꥽[,},$K$0 P$I I# @db#@@0`@8yFʅ*#%@ 0!p PPh Sp;f095xн,g1'*i?` y ~&ǜ074iMH]FQ,+kKɆUAu ԼV/Ӹr < r cYwBa !Hު%P`:WHEt\D04zd%ਥGITtdQ)j%/f X$pL?ː?y>y(h^.^  B1 hM2#a&$M( fG <+|x>Pj?tuPJȃ nviKQu4PWgŪ#G e em1## "!d(J(\(U( /|$*P+ .+@`@Xbn "y`AԃqI %(r 6' eɢS1@A_%HILydKcxL%p(0g$Ix)"lT\w@xzIs e8 #Ǒ(NE@K $ p 2{ ~\ªLLA"ixM|`w5&2B|bl ԫliWN>?[&cf'i;~PT菩R{@՛GĹe1]޲q./!DS@K]V9p:YQAAěG.y4(@(dʲ#%gJ%#(II:`}CƁfX2d#'#72!3DhK8~t9Yzf'-/1$\cUGP?d;D*Ni3frc< AZBG vbc\t貰gAqp9z3 D Uzv*Z*0LH6U5-+_GG `9L1P m `=tAjLR0kZ0!ThVBY<` 90#T{#dEuUzȀhr@-:X8Iqˀ^ cE G;L{(RE09,Kdٟz`¶P"i%D "+&QzC Ϗ(Fh!_m }TIɶA?$!jB&Xsa;BaA$5 {p4rR%'Tp6re{ ?GP$P6,1"HycL!AptrH˄Q P@aWd]D@#,N! `z#M3 !%"`UiBhT"z=;P_r/s8}V(.q r- *2A $44$D#1"_Xn_[hS^<A +"UQA@ HAZ AI]Vkx_0;y_E xRGΏȡSMX4S'HxZcё4e=Ze'`2@L5?#W \Jh0.ֿS0]Jp%݂Vf &E)"ŎTb| :!"RAF]lSUFS}90$ψBbmg)Py` $Ht&!E@؂f攣V{cu4^rY8g3d:jzD!Rk@Y7"H5BI*P&Lģ@/;,E-52ME0$8$0t˖4Sʀ12IPIڹOYlHY01*]gP! Teoǣ@Ffp9$a1k/SB9)6/%A.B\|p2)RQBPz)]b-wHJ]> snI!2?5P0ትhGtV\TZ1ʔBG] qسCI!a# A(sQlrTQ N ⌭pRt Q|=g#QP1z L ԯ (Ag(BA$ECQFXHԁf QuZOViVN$XFhе$TJyC($h d)J Q(` Iya y|*'Q@$Hՠb2NO"G+ǦD$8D(|A 2}Bgr@HpPR%g0 *.*K8 VC΢'IL-B ?)JC_T$G`,EusވRArb+Abٜ#@ґ !1о:j*E,qA8@Q+"iO;ÈS (ϘqO)ka_C]QvME8Dij4WWԇ,&,)^85#*Q. 14?HE1H,DxD$"p pT( . P$u8z?ʬt Y+0-GW##(گ##4"$@R+Jj@/_h,ʿSZm#q!KE$k]KL%JaNފHF׾B#j'cH*K<" )Cg ~H& Ps ,">CLm!"I м\Eix @p`0-(/AyA QEC rÃK``a(@ `'TtG*%B|t63C! 8$,Šϥ΁&C9?Qy.=.3y (|z/Gp}@-E`BQv]QDZXI:'֑~/ʑye'Oుazō]EBON a)<\!@$X. \/?!#x^,B AiXx|d~P?(7c(\|zPoFy@  #@T8/5#"4P"(@(@! D!B F !@8n^@,J:C3ׇDQC*hS? @M(Pz!Z(O^@Y4 ^,)Ԍ^\@vF7 =L@/6dQ?gB"\A  "-PJ0GԎÇ`CA/ zi 'VP5(r,@(L XdsQ@c3`wDY aA~+p@@#E` @ "5I@*QB sFV@ Hvl N,晬F-W # 4 ddd1#Nj-&`5G'M!i*  %4'PB#)D!_爇& @ ah _0p?4 A0aK'!((AoHs搘Q%w6 K#L?\a=N94uJ@ )3APLU|$ .6(?ade 2* Fbt8@<@P5B(\U/3(})?ojTt=׌I]E\\DSA{,D[(B@T!Kf0&1?s vN jH"'etÓQxVиG@BYg53 9 Y#& 14UZ< ՠ@ hI - IB> ]y,L~0T:6m CJ0$xJ]@Xպ+g`a<n*IYBH (qܑA0 q/z5+Ɣve2`ʗ`gEA9EZҋ$5CN-@ BV4 M7(%_QE W$ P=  @2?aHgL@# "L~G(W4HNə~*#$+<V?M@@`4\B-,d/(i$iZ X@Bt``  $ D^I@< RN $tx`%@ Ҁ4n5@/VQHY]@| Ӂ*0NH DEFȀ }!b(iÕTf/hd Ac(-I`x!I Qn>!!D0D8 H¤/ ,xMP$.-X-(RtE@RdK1 :a&!* %,gDuN~r 9UɕծE_ܧ`AJʑH\9W~`W_W(]`Q^潏 |1g>Ph>" *,(Ddɓ&ij t/$DCxΎ{tl{8@\B8R>oeriD:F`<"LͰqQ-qH?i, 3a؆cEH !H)ȴ(H (Hadc8d T"1貊 T"1X1踆*Q #@"Dddd0 %!!""Ai^t@?\.(?HhDP5:1޽(u$R`Ϭ'DJ)}a,$zr:if&*+0B1tkeXB#?F@(FTJ)@EAja'#GYL?!UT6= 4<d@Dbwa s&?@?5|P`D`" Rw$r ! Zn!h h^$t%B] A^ KC"A[J3:٠Ba{ `S%h1Ά{E9Р#: gBиЩAjt  8>hh$Xdx!Zh|<<]>.JiC`LDM^&^)oen uj| oX~N( !&184b,;W#=0c{8^M )f0^ bq&~(m"Ɉirb+ 12QJTBPA* B QRHm 0%(i)쀇ݏUGڱGfsS>P[/W+W-#ZCA:9@fBET>HQ# '2mpPJ")i@7!aCGo󞧳@т]i d\V@ R]0; Zh8&H$80Z ' Q6hUYДf2" ̐P,+@`B0d"Hi UJT @Pd Ex:GyA,`K ^sii-]Sba wu'!Px82'! p,GBwIJ)Q [ɑ@P4ӆD DqwpӢvSEw{Ԍ>"y!-79u9prr" ', =@+䣳$A"ʢ 8s \bƏb`q&N3ɈxAP @b!\3J Ck@P) Q/XU`R_46EVf 2F0D8yp @&B2PtP)ChI9$BVTF34px4@T"y!jppQ  `1$kh5 dj(ŀ/TQ sH@BÜ&hs 5 sh<S44S8f(U3h>ī~2r ZPA!H 0)@ZHyV `B$NB"jR#v (!0@h(D? APP '9Hx!xEV,5F0.!@F8!Pp*` [nCD$ ()ӯ"D Wc-*(b FBA'ZYiSpATpt JD(*!PqB$z.DOD{"dmE&#N]?\)2@Ր|(ϒ'(b(,CQgL_2?HD ʠ8&\C 4jf $AĜހj>%J@6s* z92 $= X)K0XF G% qB%W))פ!(qHVJBY4)sd@E@$6)k@kiD|`7FHH t4AZzGH8@h%A  ] 2.0P!fBH)aBPY <4hk)O}XP8ro` A/QEb$GJΔ$K(HpIEt17EI($`؁ɓ/亊K`@(_h>~.J8%0LңBEwaSWB H_<'E{#,pTˈ@KUHi@vS*wfۊ#;` ^耢V)"p4b҃ˁUUY !ƀ @@Ph(&q=" l!Dq)&׿hno((! V$m ``hh&aNo)(gK̄K`(88)A:?JߣgKmW8e7LttŔ]PNeVkGq40 Bϖ&%bz^Y`U1'AE $\ko:(ք MI B{aDk++-TEe1=A 1 $賈i0*!\$`@D@K~Y"!c#PJ*u&w)B:wa(<ĺ(("[ᒐ_Ĕ)" 0-A EDPX*.#ʠ수`4(>5@Y#D⇞8etyHPp$a&R@<)_hZ H ;C xwHeH>h+: :\\ bЂ5NÆ-#/ ]d)jBlI|aGЂ>DT@,ϐT[?ang{b#ةA+ ? MED%NO`RM_,Ru30+wbCqL>+"tK74HU* D`FRPz#"yn3_q)U zJr`/0_J`+3X$?T &" Q:3/d@խ  `$@slGT BR$$ pjF (Zo$hzՠ_q Z " UGj4w$3|ܸU~=MSUtlXY Rlh'ȕ9Tv5gs%owNdbKh /*8=$OPGH0o`?|NRn~e* +k ]9fu%ҪYsH kNS'[1^s+Ve0UG X@0(:zDN@`<j5B. q~9Y: Pr@ќb ? nF91 M~""M@1 y,!APF/5 j}>}J# @-EcCڐ3t5{9p`PHh3@@p@$|vF|P x!L q $ kB$PA 4n _>C]A 6GZ%^AXaad 8hy*V( PM&J? .(=A@! o\=րS`{!urgpP+PIhPӅR-786$d? m`#&J g%ʕ\%|hAt x/ɐ_ $@$ p2ʁ  0B^>}` @DO x,4A/EЀ 08!-18hhC((!K  x`x ʧ83)@ @~H4h Ѐ  Ph(V`@4((@D"rR~}@@T )R`@$    @@ p pʑ _TAP, @cv`A|AN8•zK*KLg.{*VhT\H8A."<'$N%Sp@! KnCU X QA$ygZc@`Ba"-$*(@I0,h)KCY $28_op,}𚻪r0 cJCo maC(ҏ]lh<NhA= =9P `i|ifP@ME9"/3,($Z trꃔH<)XVdAfAwkɹ XqӇ~7 \I÷=C PO˓m f{5ZqІ'?w"C͙g'uDP]6VD }ʖ'EA )`2N4 MJa/L H` aWG  b??<2P8/GAY,8Q*KB2$}c4(E -Uȳdk9ꣃM̀<#(Q|rk,Y i/ :P ^ؓxvz( X<8ڋ7P!mNjnFp/PJn>n;a! fJ&Nd u@E,2h$@<} h41 ٣ /&a6#iM3QX*Gz0t EIRd@FNĊ$g32$ ̇P% V@ J%SN\M Dا*1+s Z+Hd$$IiU&5/v^4Wqje8M4l<Ksr@-K #Y?O~K4+P?hH X ̌Ļ(e6`4Z5AHJ?p PA^#`  jEN@G# be lXf02Y0C}b0B5F?,_ Aʀ$0(XaznDXF@b7#QU'`bMaG.xM'4 ][f4Ca8eJXV"s P"2ެԠxE3d(TajAZFN_)aIG(". >aCm)VX@;ZQjLSKOlUfڿH%Qg91기bTHT*2PF'0 v@,Y-@4Y2 ( 0=~@ͦ-@ @B?~T#I+!JPVN`1DM񭊲 z0P8IY @ӂiuJ[OA`dVBxy)"&ʊA%%c+XBF^O\+a4JQ"&&&RV)1@P}o VRβt@"'Ϧ,dmXhU).4v6ܸ |` C8+ZNnLM(DgM`Rش1V@t -JP`2xFh-آ)CB,y. BoȮ64R89S"I +1BPuSO L XAC 2K-)uw %/9Lf|̺jAIdTAu1 x`2`J  hc+(wLy8,bcJ-& \9*ܠS @ KIPG Aʬ`iDW"TaP h1h,Ql8zAYT5OQ {C:-R-GK4" i5JԬfGp %BB0 $z"ބt8 /qIKHh &$A%(hJ4@zND}VL4X 4k@xJɎ@I*5A:@b &P`yl)8q\L !:Plr_V!G~A[UbRH@cLR( (A  BrQ(BX$BHzic }Mq@9v~Qr!W)s<)@}I)u A #C?pF46{"*N0`s`Y9"Z sFt*LP1QS?xfℨ鑁iJ]QJS!Cy_ hʒ6xΚِVN](*ր+,nfT25 N̕*mc ݒ .@a1 i'^ %!B)X,.=0'x&68 }55oDJ2\ SU SZ !`yZMo$KQ|(刁kpdHP= QFź[R#I1(3>YU.E(ԦX!'\JP )GfBővqGQx&l)PQ4ڔufG>z9}tUi"epa5o!^8J/Zl3EEIȵzE |D9&B.`]hw@~$>,Zk^KP!FX9ʀՎDQn}$l *+KV46@5H7@4E4@/@R z]h -hOx  EU ,I X+HQт>Bp)#Hr-=0!g&# y]xb$ W$ #"tB(%ԪJ: WEPUH*J-QKJBHH)D5Dq2*&P@`?:E? fX$@ ̍ P\*hĉ .zC!`U*/T!J@?P]O+Ny2i' ?-$#O+I la@AH9@J 3rzF(P9d=Β 0*5=":]!u #>l/ wbTzH@XQa N"TLI@3D0RXbuo(U!`l*^"@` Y|Wh[XW{ ,p`p<?t01O!Zp0t%AÃM (d0ʆb(ب1G0GQV$pD$< H Az!HA=H@m@DkњЀA:!M*&*&<4b %Hi!0()OEAޅt)-P$,?]V9@ ɬ"%Y+1`TYA jVc ý ~ Q WD!H݊0JX)F G_ZF\ l ?,h0<"e]EF,l$xc< &e0pGWz89 393JOl t r w!rgK&{OW@?@?A=ByrLXNš ؀@A jUG<0e .r ((0/y?ǒ4dA ($(@"8OA@rx7Ar t$耦)v( CxMF O) 4[0@"!T,0:@GH i$%p   TfgbYo4t#q,@[3 h0(W((p @60p$琹qs !4_@0.#P) jKB aAe=$P0,ŵ"D0Ʌ(0M) Z :ȡ`,Ga醡! p$6krD@]. a?#C4$F ]e0"t`,_?8ħNN"  Q,M@_qzG-)ąT2O#%X!ن(\ey87 ^PJWM1ඎ$ t %T QT%@Р6 (  .m+HT:? &:+?W?1( 'Mp;\Zaw =nQGQͳZd(XAr0>meOpA;U8~k  )BrxGK6~lxHJ(E11@tEDIpZ9T!%I_!%P ȘQڣԡ 2 #5Wf1eD xS0`@6w_`ҕ@xV(^mHH0EM-ApuX=#SLX~сZ( /6TĴ^/u H$ Et'-,K0Mf(L%Yƕp6@8Adx/DP ڐ\B#M`sp ,_tBIm BӨmodpoQYaQ/&hJx4 2LWlHa;7(2NiAxB0 1hxABPbѵxꌥ+@fUG 8pZ 1 I`0!! AU 4N.L瀔w^V[t@Y z$ dBMBEԲsw;'}{XrnmGEahG r} !" uQEǴ-&n4O*_b-UcH(דGsBS4f0#R,ՌIʈO)EZ=X2 HAH "A :Ta\zMP GEB;@h 4iWpeoz Q5tpBȏ ĄRд%Ҡ-kF%7`xJ (c UhEHD;s`S:̅2"ؼMGs<0( %ɿZfm5(H0NU[ p6qMꀹX=##dz* ` #1D!@3F@P'Ad^~/B  K ZQBEP A@Дz_d"9t1htBN(@@ۃ PUhrR/E -5ߨ R>A(H7lBW6H߁-C< O~2> JCW0x8ܵ^zC.s3XAfh0 ?I@F)`v(ZLS>@ "\_TO& ?xI*|*_* wdXE^f˱`MT}@D5bToCAК2V"Ǵ*JI@6=p BJ&0\"ha DD Ea:Xy@.\b4P hCtx`#xFb(S pSl $cPQ1XqDRo 'sJ` y<|`,X<')e"oGJ9Ƈ P>FM (@( g@PPr-G.W]@z EQ@&U+@m db!-4"+o#DI8 %ePf_!Bl0 QO?Z? :!r9gArdO@PHP H.+% )$"" LpNp&E!@b@ b(yoBO\Ipb5!A(!k!eT4N (m aj" tpΙچ4 7@(; !T >#C%G"p0+p݊jpb"Ms"T%J cW:8YDŔO V%`H $ **a&S]BYOy+OP[OG`*> A1OSjHX O 1'7BcbM!~t1PdT ` D+d!TB$6<#}lr^Db/`eJGBp7RzP%/ 4`0Fh"8?44y$ xa`>2Wr';~V W!\r +.5vJ$,Ǘ͘8U!p!еpѡܡH-V,1k %@/,  (4EbN`PxS'W+H$LFwmhB^D?H#0ra"9l["Q]6}NmEW FD!,9do!$h&CBX ~(<J8lQDŽ$xi ?@2GhGڡrBB^(0`݀K@%#Q*?>PP0>#H _ BPB?'JP?=A[e@@Ɍ1]jA]آ%XIÉ $1__ J 4{Çaa@F@rsYz/"𨭃͡j3S A[a7'&Q0K?(G˗/XL":KЈntGj'dF9JI<W:^tOR(@Y5ha GhC^h- @¢,6 Y  ХAhg8D1{VS_L`RIIC4&P&ȠQrP@Vo}Hbt1+!,g 4j#QYd1} p,; _`7РʇD (ԟH@P_K #)%! kzif~[ACQFX)QF+A4*]}Dvq Hq$Hao@`8Y5h >oFhu$0X=$UCR! tpUQ{(Py8@\ U?}i  ԛt(b1#/ ϪtȠ=Rj(v`@2 Y` uX@N<@2E14@x:2^ZЍ V#E+F" zqq% CF.F.&*gD0]bX?( (IL ,$a1Z8"чP1"ZAQ,ߔHao Y]#ʜ(, O%AzCtڅ Kȓpr"Qq8e B4(Z1hj%F`%i(Kk3Q?Վ! xDʝca(x)%uBe A੹l%9QD o!ܸ |b 2\|l7 @ A UH!JRa ȆɆ1!n4SnʐJAEZh?0ae 4w0 ',>fZ#-Q@  @io@!yu3E)_Gӱ@pʎgd?Cg o!۲ab!O䁀DB   Pa1P! dh/A 0<tBROH+GY(PU5@GF^nnn_B\ J8Q]Rb+#q BdQпN??@OM #!~Hdn /DtE  Aky X.JLR hPH2 8pTP$BCah.P裃1ZaG-I@kO{ f)@G0@%5|HJ@Y."#H0q(brȍ !! Ѩ$"Qac$i*!@3u$POףeRBTGk:=lc\!dAʗj5w@ b4D:)U 6*ҟJke,H^A Q*qԏkMdBfuaJ42\s>A~5&/˖'1zR %HhD~6x),=c!=-߷$i}Wr >BJdcQ@Dk"n!!}iBW@M E22)JP`eL@訡)5!_pݏA,]9%Dε9gX1&ʘ:fRB;,)  !R!I@PQTV  tVy1W u$myxm$4础Ej(S@F,j\Yh +C!XNȮVr%kN? o8:B2bﮥKMdJ1F+Rtus"0@@AEj PbBF*J#Ɖ/NZ~|9w( "%BPG (ZƀE. dRpA^@ y4P^R%<)JP`l&} $(+:A o$"հAH,q/0FTP< u4b e)(s5ĸGƙ#HNͧ<1{'̩zpoEWa P+ .',wV`Asi5P&d"\J˼|eE£&s?!&XcP3` ݩ)!'H!(j4V |lG) ;ĖJF/(M=[)F GLTb}icEcC0 "K RbP>V4yDN0SWFK%b1i0p9tv AB9@*Q?(U8r!x"F@AHݒ &XON4ij4@gF"(Vanj)0̸c@aJ+ ec  AN(3/2)`Uˮ_i,'ȭ*遛0\)`1Yr;)4z};C )!$!S]\s}) w}@H|sْ8YXB!_XCOv t0B4HЪv  `&>xw! |hfp\4bH$"R,++ŶxO^x[ɨ\hj~Pa†Q?#.C\-#?4Hb )?lם8I{aToHFNrZ >8jk r4}:~ue=&>dcfJ{@Jg1-@]M@Mjh .4)@M X5ZіR.B L.&!@Le9 E}/CpCcHAE OiqBQ2y*?HI8*%1,$H  JQZK1͏g X3Fl<\sF E BUN;FGX "@00i"60q(^,>H6ؓXЌWL:[3נT 0i!dI $4CI%RbBD4>yU:L $  @d٘ P` ʲ H-*BAHtIIREP @@ @C3R Aq@%TȀBl@#$ThQ0U(!` ~8 8hnAh4Ka@!soN $ʻL0,nD$hbRD8nK` Ɵ T„ r p8ZQyٙPn@$!KQQ΄P 3Ğ@UTcz"A4HjȲkx @UPˈMwJam.PvW99@d(%{+P@9 r'$(Ġ#DR)81 u) BTHPk&[3j@L mEQI*F0 _0DR*&i'@3g1p QTCD@nAT2&4ZB(B Ɇ@ȳMX"2 ) ,cb{sIVI Ae>|X T!tO@l$`ť PhT H`|/FȣNFOóvv;;;;;;;;;;vvS:uO ~=@A A PH" Wy"@$I0x#(%(}P0V ht['zwl(4@NECJ8w"f~4b(0 /?}f~C@tANY Pj0!@t&ܠ ?]=PPQ@$5:@%BUYs1( EPw]@ꀈ<P.I*T) Td(BN tδfħ'S"(q!d@0~@<!@0E ' )K'a0H$L ؀ '!b} >`x0Q1+Z?|+2MHJ wZT 5@u $G - h! e&%Eh8QJ8Xi AW^a.YCZ:-%R Jx9w!WTА0FU, jb3!@,?ؚülM:Fg)0A:_FPS oHR1Ixu|*HC$K#`%S S ‚0kӱ#LQB'NA,`bUq>Zu䀞#)!X4Aж(=J h (hw~%DJV0|$^}  @="0CH b % D3E Ғ3X9 ?.WBXO[JYb!_zu Yqr@A|Fa_TRBWW'nC60mQ>U\C>1G7hiTk+ "Z)ptS 08b paq zĮ橘Љ~@cgs':'e콗2\q&$k$ ""iNJdswM E}4GJH"V%מEF-YںFF Qs5K15 ,UXPdti f>o2He68Y.5Т f8&*ۍ@h44Qoj5FQ̀?@HX" 8-l$k&IN]$EE^\X8BW!EOGͯ Xc&0{П.IJFDZhl D6#Kgu*pg"hNmEum#@0$r WzUf렆VG` =@$٦tUU- AwCuJ(Hi!S- (Z*h)Q j RVI|4(%Jo2SNt%U@ (.]D`UO'E䜓bLI1%ϒbLILc Q|20`1:%!dQՉ1R%?n1+x<.IQ w:LƔUx׉E|)Jro, BJR,`!Al@Pp[ dbA iV(Ђs(BD'm' &Ij3`C@P !Be]?)Cŋ R @E&C Q LЖ^! `2 |jdjM&81ɀu#TWP P@$acjzɋU ,Dɍb@B1e:FTyť* i @D/I`Ig^VJ!H 7G  `ԅi ~:#Hĵ (& ?>JhC?-,^G?Ner?DDHOһEfVm[p9c@(PI#PBFG̒VE"|\xL -A-̀?mخͧo?yCy @bbG!)Ԁp.Ftֹ#?( d|+_dv.m2$)^ M )w+ s?ZSHANhih=]PG&E!74s/1"A<@M / LUP?Ŝo(Di^IN j2nlPFL4`EBAV*1PQ)Z.i$di .sD?.z@YV P FԕKbgiw :`TҖULΆA=\ F0 $!V$[?WW2;1ii">fX\!"'Jp;X2 b*20("%'͒ ]AP( J$h%v.-(@4@`T) !0@RAiQIE1ꠢU}8䘓"f\˙s.D̹"ǀpA!B J j$Nv(b PW!R*Paj(%5Aί/p8>+O@^` ĭO, ~BO!GzX< dXh^ b! `U͋99`~i!܆O3dZ2#̞ Qɂ!I chGBUv]dF1EQ:p9Nt& nZPKB\iB:P$(EtPfABdRipj5Qj4 |@DH(6Eİ$a֠/@Q-RĠ$ɈKR@xR !$cR1KMv (LgL) C;=3 up9P=P9f24T P< P Fn`PF(A~^7 P ijkCDQ:`G%1"[oۧOn=ZyV0P `!@B#Q)$T_Pq~7oRx@SwU-7i=b`~8 xINpH(}Z@_BX ea!Z‡5ea)ap4EpP P-ZOhK??$H+)PC YQhQC07NNGASp,\ $2Pd 288`0<&'c?` 0$7TL@Zv$ʢ364bX Dh~S,ިQA:Cj9K%(Iv ]> C - A'􁢭CZ G a 3P_{:׀{-7GSaC(ĖdqSnꇒQ >: Rf6 zp@8,t;=|>ᲃ&C H\S`a Ŋ@A4nZOl°&ɻz<2$V)C'ʏ@>.X9#0%"GK>֡7Q_Q[PDLBCEQT~MO" Q$ [" tA\,n2ZoY`C( PLQD P|*e0dFAq10`IB ZW1@N@TëG q<~ ;Ljp*OD  Dz$#aɹIPn4qJÒ6lF1DJ $<@!$W(CtQӦ}N;YNvv݇m;q / (~!L e!@Dٖ>RDO`1B0FI $IM}TS%&"uȇ o)_4Y Qh j?K"H*=9&0B0D2Mk^Y M>`App0B D Jip XATuF8)&u+;,VBbT*A /ɧ'u=#ǜD OڨQDŽ""|ET?'W |P($,WT41}9Gc6}'t^I9&$ė= PEs' J4AE EXdZpP-]5+A‚"zS_~tU_P_yWGf8[$?ېFNUVpؒ)'ψ@ G!PB*M= Xt"̨FIB"I/O/r: ,<#0F"@@HDKHpTXA!qu@a0 Cp= xL$@ 1x`} LϤ$+eZ:0̠V((cRR_xP)Ad e?D@2 F7&F"R H+T6)RT_l0[PNh . h!l RhKD>=;H6 4H @(MRk@5@5R!x^_YnSۧOn={t 3'8E`a$m;" x^N'" "Ax|fYl'Gwާz@@v,B1 ?y@j aA .8a(С3HaAEOj|pƦ/lbUzC#,6nJ h!&] k`&Q < I}d"͸J(A@ Vj p r!\%Ϡ U1c@LP#1M B@ F(sųZD91Hc6 "cQ *}A]`Gr.y<WԆu)邟G|!Hz"nlF7(@d/62b1pQAm@-PE+yK:`B_0L$ A@$ 0 TЦ qUUx44 yyb ~adByy0 `b\-=Z_0@ arQ?XJ7= pbp>dFhdJ@-{_D?4 1,hH/@`FA~4ѿ ͌Yl`Ў 0 (XGl4h}c`/y~B|.B/!`rC\m{=g ACRDG(Q]N p$(E'^=eΖ>XLC (d TA 1EPPJ  ,i9N@J5D[e bZdIUą - $jW@@ CHXգB4ϨlS\LpçOA4#jR',q +QwXLG^F 8GbJxa*Ta,C$CXAb!(ȎgȆ>]&0ġF(J4yh2q@@ A Q< 2h:A4_?\|HG7oT;x =tD AP#Bx#,*1?>D$\@?(Eʡjq~ii ;R5[E%ɓ^ht9p%v9j 0&$")l CM^K<ւf(K a#}`Q KG# &q?q MRU@)}feFU<㙃z=/N@H&2CXB LZn}0+d Nе-X`y'kn`i iNmو˘d5<(0X 0BnqPDMm<Ԁ:ҙwg-eA'h|53zY GYOf Z[h‰$D"/GP Ӂݭ%u×ŋ8 T_ΒE yv\} (A@൤7Q_&%aCD&,* ϔ{G / ق:It{ <1Ų?003U;䐏WȀ/1(ruT,0,HE@EBIDЪ!e;;F|ȥx-5$C}EābU@M`S/fAǩУ4PdR ٫*rd1R\xlaGU 7`2 * n9\ҽh('vC]8 C4|<(=5,,!я8ۃǫO:ҧ&:|nNdVUկuץD&ߋxCʕ hA4t0.ҫZ&3Z(dHVhvI J9 @0jPJZ0Pq. QAWG-ZPWֹ X C(GSJj,R":BqBjG(<:dT %%u#)CteKA]V-@MCw9($6h"(AVX>jҙ!/׻mg4`gJYa}kNgz^Dy8Vh K؄9y_kol$p_?q 2G$` @8F!'Np2<` S| _YZ, ONFt@I^m>@yKr5N!ˤHAtĜesI1X[~c \8C{H@JrfB%*Wo"is&@P i ]j EZR&vOCa)Ĭ^Q[J$+! BcJA T_l43O>8\\f/A%8 @>BrvxP q[0>b&P}?9,/]PLFs@[c֫F?|,a#m12q*H5 @@@gN:`>CO t0΀ v/7@] OZ +T0*VR?KL[ T> CXӘ/pz4q$4F$ Q_";H= [y$̎[}xͧ N=`3h ,x N W38ʜ d `D(H~ Ӱ ߰8Ѡ,5iYYL@R#ZEj@ ͭ0>B@zdS Q(? !*{ +\J@8g<$U*JjН 4 bCT @:l *0.5kG I)K IڔM|"|[fWZij]dd rk/` a(wb S( $__ v3 #;wlݳ}zxZtXh F5L%?'&ߏbf 1+ 4|$`Qq>Kʽ`@Dyw<@9TPVܶ@v@u DS[P  b0 4B%9 d }[[_0 8 <jAGAHև`3_`^]Ÿ0` A0)@(c33 +d!gqZ ު`˟/`~haG EG3#oݑ-Gp©FX*Q>:Nc` 7_ !E/@%)^9J,h~&Z9}T1ÑqTPȪl>"Ap`Th D%E)vV@7dH #DCpHz! C$Q@ QBB(Hj.wf>IMRYڨ@B A/EB"FF ABɈSVw/@@ LW|zm m6Ͷw;wlݳG`΀At.iwNr`"+JB7E 9$HS@_`9»cCp0|@(  )J1cAB)P]]*R-@?_WTAGQ"I䕝 (@=\| @P((8.tiIDyA09/zDt,BfATX. 2`T!K6cl6;;wd9eq% $8 Y@a ‰H Q#%Ʊ )#% &JN:tNmBk ^` FT/!Q"B/7@ RDRC(( 0  ̆DkJ~p܌@~G$ PPE*9\X(N;08N K ۂw B Rώ 19lZ2TAR K4pJ?ILZeH1|'(P )0EizX vV%PhM,d yydH6`bn\@\L@  Tg(NƈP Y YXQP@`=ffw@lY`cL !($v ѯ>ˀ,Wf Hx-PfIc`aɍ.*@ So+-Z@>QA B 0@SWhJ9hn]c0@:1re`Q%tyu-g r w*0,Ei4#I#3 +1%ϫۡ2m |q׈窸1]y\x>3@24`&dJ00AĒ*4m d '<X+ǔHr򢯎~麀sc o;*~rc,JOV@1%(zZd #9rFv}jmMlZb"Ûbl2ts `T _@B?7;, @[((%z;:>?)&^ٱ[HrݦޫsBw?cAsVl@ЉKqN~AP&H- K,Cy BD[*OP 4gӴMKjSaUV4XSd7 OA;38ydi Axڅ.4t 6\>hΧc#,s0٤fMg4JJ-@BIr`["N是|@ъ3cH'@4M%J@T+ME(Bh$UÀX= TA F5h:@(JCh 29C(-QB9 T3 +,bsE5"@Ev&J@u}+ZZ;j9VM8QA@`C8< ']Mw䓣g. `I4"Šӱ~A"tV#\#g:ޭoUHKkr@S3QD Zdba)_A"թ+_(l|>"R4<(+j@ |"L ̀5gx3SlF )$DHsX Ύ%b@ jF )dPzEBԤyL Qި@, <"@uŹ5 R'%L$(Aq(y&(Í JjOE 7$؛g`pƣ#S%KU,tkB)Bj R_,|TT;h23dLnnd$=\E g$Z RTHxODRRQ#F @Q- !5bBCni9"4B[SqaB(>YANЇ-jrG , R_DT%T_|;ڇa}mh0XdAl^D'V.*jm]k톘%"\ $Dj}mu4(s-W(!NI(@_ausF.D+4@"Pi A$Q!`R,8YhKzvRh|+iG:b1ZVIL 7- S!ŴtiI\N}$j)Q4 @P!!AH$SX@!UR:|HVbꤊJ`@C8}SOu]dxpsci* I0ʢ apHex JUSb> R4Vh"#@% PGhij6EI 6*d3D H09gձs 5G(bQӪm񣅑J(wʐa#* $:nx^n m @lH̞R1آMʻ9JʩNZ/p Ⱥ$F Z RaZG,!9U(Bp UH2U6b!E+2.wVHHK!Խ "`cOx #f@!I("\$\A ҴP>=P -P#|$C?"ڿr %CS:5{)"jaE'gA(JHTh=Ia \VN"SZ[/!P@(@ Ddn,7I$Y.i- +rdBe@O"R)ƾXǍhuS5əPt7y :3 vڗyCؐ|C]n"ʠ)(=@I(q ')`$J‹+$5 ' t`4 (Qԉ]'ħ]4V`9R"#*ZE2o |Al *y? yvF@(OC $ # ްy΀H 4Ėt=>$ýBlP44A=B A?,zm% 1!K~^?,۴Ʈ<g !Ä!K̅C+`J?@TPf8}i7OPS?(!8 )}# @ /\f ǺD$jw &m =0 d2 (z⅔ @"3F y:!2%)@(Q( " 0I  *\>L B-$)@":}GF t ";4P'#b@gqL,=kjy!6XAIcf8.0Bpf}n ` C퀈ǺAv4)g}j2[ѳ) 9K?V`s9aH8؞ ]gŚtWG CAHl,0(1薒(FR7M/+Z/=&%5lFZ5+$\vL@˭µXi_?#UAd@xxM?(Ap>`5@fr{SÂ˞$^Dp zxR||䌋OZ$($0X8 ;^OR Ƙ ET? M_JT !HQRNHhDZPVEN?Z{:GzqPH9,I&Dc 2@ ;Zz{R_b!XDH\_帏vu,o@d 6ހr31a!TOabC$#d送!>(xjz|0:"tX҃)*0 G"i`HGDIN cK`$x1|jb+e)Bp_B>EAAR4Tq(AZH"qJ 4@)g (} (Pk(?U ce P%hQrSAL. @0AI 8 ^Z!xncߟ  ;on 4'^<B@x,*0 s!PZwԕAY-lV@Q3=T4> O ˅aIY 0QC Cp YT pUipPkKlXWi۸p>Q"5\blŒyQ0B j^2HT,A`{7ZԠ|x/)] P/ YTyu-6a$C rD$= ` !(\πA{@*(C@+JH, X+J-h(z4P}A |9I!*$xЕ'E47aN9UA)`e{ɁÙB#w1, TCbrAOP}""4_0ut%,&c@s "8hCttX $z^!MH<@:Xč06R"N(GM$@QAOM:MBw<@mAd(rH|Y!@ z"tC)Cל!ey bbIU%*10 (\ T#?- 3PǗ  <@9^BO<EmD?p`Dsb ; !yZNL  *a eFzQb1@? PX&tfР2+ F 9==p7B vJcU Pm A0&Ry0?h2$ w ># ]:GiyB*~vqO!B? {͏x#( ج fU +aOth4-gIFL?.`G W 0U PBi@Q?K"cՐ'n"Ys<"sF+|\+Wwv2?j@+IyP$5g *@#;"2Ec€#K@Wc##^K}⠎~ J'Zx s@%@ z< (^6p zBH.(Pt P@s(dɤLCH΄-Z@Q`J|#BqHMB}9w(P]N^Ǣ( XC"F'Q!PAgy-UFٹB0 nJ#K)|LԘ,_@5RuƘ+1ql\JA6g=m؉T1",Hb@Bt~NPA/!"HLL@$D8D6A T@=@h +$5Hj+A -DǓGHjj5@Q'p9G\Hb A8hZ7B MW~$SQ}p@R)!mE߷+< ˀ"E#G1 tW9 0s#@%FaKH8 qDh-"ar$(nzHPZ`_K.FD H3rdBzrl@LVdwL<H&A &"aFdQrI>Uо~`գ e ZR0PLyƒ) 3@ zDO$B$I$៝A?E#@PJ6MO!ܚmJ .  KLc ~FG b\IJ Ze?K[j1x @ \*dcv`?@h€¨ᰆss0ŀ@Q iG~1Q(h) cqcGԎ$b!~(A5Lm8@i !)ñr  t?@./@t\`Jev/!sho ­B$%ЦP*ų_`,PVӾ[)aZH4X@Z `q 7HGxPm q_61l яhF(la}ckhl7K4>EW 5!x8z4mbxM 5E+! F'#Cj!!!!0PQ  (aa/7߄aKxSc)3a~SȌS̸@ b{X#}~O@i3z@V)FR֘i!tM=:Q G1tCH``4`%O:-v Hk3O*?$@B~H44 sP)D~C"P(c`ؠ2#,0F\%(fvx݉0km*"Q?ϓim0s>U:H/\LA 2 7~f7 8L@ߐ !<^B #t  +;XQy"NXZ(4Y;<P$p<ѪVj6!1oq@" 0Rb/ |b/6} O" % p 2ȏ}BSx*(0ZS9@`B-,+e\@;zp&nZЎB0# NXjAB¨-CCRzѭ ,y Y1R TD r hHP +6)O^IUy܍@(Q,ς(*00Z h4P7(8`$.&AHL Y3ЋGa~C J& m?)˄!T"1yk"k:q)#BҤ0`p+F`BX1=&!Hej  0xyL1E*IH&2I̒DTQ0?%QPJáb= EG]>> > N+P } {ާU" IQ5"+|P7X)k$h̅CAxXK„Pq'd<ՌR|{wSܨ4tpC:TT Dտ7ʺ WS\ 3p@hoтfT ;XzaDF;Vl`0e W Ѕƞ%IY^dYhSh4T"J*XU*B(.M$(hY HXM!#AFC(hƌ~p*n(Ez.Ұ0A׮A[" %<MHH~1}`h:z8 !z$LJWR@Mn G.zZ\J@ Z=PGZIK@ HA4ABbLF_o>MS% lrwUA%1B ?r~ 1Cp^Sɉ&z2H@Aϲ}o EwNp5+QQA#XIQ-/ Hvˆ@HAp&"yihLր%7ʀT?F 44Q[ LD5tBX`S-Ԫ(HBP5>H=+0 @UD?C q+PADFF>9b |(@xXTiT~ЌL:5/:dޱ rDFN0Ę04 FRO .rK"̑"Im߆ժcTbB*$JV~M uY 'VD*2T,&CXbN 26y\"Z (S2g YwU4x,(- CE"xnEE62gA&KJ228kPa&@VR`T ӇK(,UO ԋ:8>RVf S~4*/D 41(M2_MAL3?#G8c@-iJ+-_r8Cɴ % t &4ǖ!y wU\K|%$B/#ȡp($haQ!YKrrBQ U_4 @`E eg@ d %R0X4v$$CPN=xX yc)EGhPH$2TJ$I4@ )T9"r(q  :AH4@He8 PRR@3S) Q(#E! PG, ("C x; Pϑ,@@mBzpGw@ػqK7.1,1бh "9V@0)"/`@Oe  p~jQ2CGˆhq@5(TqZ/4 J0փl?FH!C 8v3*. Zuߤ6A~RzPE_*}$;1HB7:xlgƀ 6@ci(ųĉ \ &H&2^:^8rI )pUp?/\ 'Iih0󁯨wtjPCCQ2%!!?efbR`*Ԛ""j_bʄ2 ZaS?4+L 0 c#YJ 4&A6)vQ8g'eYvF|-H8CǺ~0@t9GEJDiǠ&78F}Ҡ G `Bl#BހQGi#D#Nq J#bgjqJP 6^CB* mX;2@5@d4b$Sހӿ̉ o`Q:aQq A91$[3["َH ŤQV?0`I h8 J%~Y(&$&7}hCZUP*?h7‘ƺ! Cx$#t"y.AEX:&n$8V1#5`F⹡@m9A7+@A) ̀<id">69S`&2օƦt&PE,B)(RB^4P^TUnO5ͱ"cɳ&ҐAS:J:FnNP† Xd@ (OIY WP_QMAjTBv UJU#=p98=ގ‰ `n!hܛB] _`;cgPWQG$0@@@E*ǔe)"4RyybŋThti@]%)d#*@((80$PH )IU]\A$*Nky,@=d"N W_?S X :D HO[Ǜ>0 qp\hLbCŃhI2*y ܰ,A`$ #@Ag] *<I-x0DrK!<""+.@p!;NdT @h,JΩKyYS@8V2R?P8IPCV5fPCU]Q[|+?lN?iȧ4'8` S?݄`cvNLQ 0q EgNF\JJ G0v#IE;QLJ( pWq; #| hxBTFD 5aO˜;(bPDBMb %r* ir_s: aK.VN")Pj14B$*HQЛPJU@6J"A l[()@(*::P$@_WBQ/vłn]h;G GFV P&x̙\1?)i  HI1GQ!]JPZ@5/ABl ^OBL/!.s^p,Fj=! {9(@!"ňJ)BnRR`2KCYVP{Eh#-cڢX(9b0>-A ?N!`o~ v偯R1QBKAV%WbTR1bxQ' X#!{,DDT1#šL @]EVo!U7&\~%&r6< )1v JC JZ#w䬠 !ι!+a/y^svohB5ED]9~%Q*2̕Qk30U/P$ V b_}VR`D? W%:,aETrZ" S Ta VJ 1E$BE"  1c@0DQQ(Q&AgY@ehb JgӘBOJ0R֤BQaD (1$a84V  :$H1"A`z,GP(}BxnIb7ؕ *X1S-8Ua7 sr+QJئLh냸ҁ6"5 pE֔$ Z(Êr-C=JDcD-!]0!ij^,+s]AcjGBD&ƏP/E}** b$dr9? ~c U V#%⨧ (q#G HYL-yz_OY,#:b{MP傺ȌF@| 0KH vFԆ0#uPRVhduGQ )UC]C{4BA"ʌ4(bX>L)"]9I‡*v<HeATbTx $QJ1Ϝ+˦F+X⥋^|ʀQ|pv=*eXqk ¢^0I/ԬH8 @"4q@щ'FJo|2"JJdJ[oKH^ыnW( "."iE;_($]-RrP@eT5 24C#P Mg@]HdW ԖS\U,y+h-d~0 @5U[PA h #CQ4H@DOi`B娇{$D$-*< .Vؘ|J ?m]f>:Eo/uD+u%po1zR(qt^C,`1 SHp&~l SJ*12hIr_N?CmQ@(­#eUۺ0̞S`9נ TWV4s]8LۣKpNXXw1$ s_lq(ӮɈ#N`gN+r88‚I4ߜJq!WDR;ƔaH@W|a[TbGOš`o(,Bkp,3zeaQl H~cx$3 oUɤa ~I9g*Q w}a8`}'^*Hf@ }>P< a6"&D5. Y ňAՊ!8IUAX4="bS~Y~; FD($U#̆(AJb UJ(pM`UH'EKPAzXc ,[?s 9 STj)"b֍\0iRтC 9H,e(@2 zLퟞpL`TlE=i6*%a0d aX00*˃Cf dO#%Xpc 6M**V}_MiirAQQu01(`sCqD$r0 !Z-AL`hh@F2+R8zxu_^$C|?$ 5I2˔K#!iK2g$ CQp&B @\PTWb'ʈ (- $Gz! =` 2pc?L[z ȑ~ 0x##ɐ|x9p6@,WXt藈 To :=? H$= N PqL@K\VEh$1eF "5(A "8;HIa0(״X]vp"Az=@he/d_Cl\R8e -paO(CR ̘ s'px : W$|?S/a  ^Â)!@+0h0ʰSkEBjB? }~y|*! V" E" EBkBEr(gN!SSyKG4Fn%8d_Pj ̈ yPEr4K3hKwMI?Ѹ5'p7 [9sP]9˷ |Ȱ`W[>Q@B*@+>c ju,6x `,@2k$iOHz )U )6G0õ'Vm#|? 7/-ST.Ly! &Y!f>!,9ڕ?Šƛ(ߍ0TH5A4ap G1,w_8yh'nE,`TuIQ|0d0|Pgǀ' 1R)E HH UP &> " yNF `!$RHE*|n!!!!!Ogm!Z \UA & Gʨ$ht"J+9m>X k 1[LSO@( +P"u&$FJ[`@YL,m#  Y`1r9YpwLZ>sAk3C,2`$i  @ t)H5">VN^BDAAA1 z AH P tqf/G:tT=/~n A]rY VI !Ei D.˿B ߏ5@$S7av@I1.z9/T\p, r'qsT))MDq j"~H0{$629wf$l @+`3 ,|XK,!G1G`1siCCP.TChCJ} 45uqꖐ3Y-$ X a+y AHd $|zzgaJ Fʪ]BA'd< Hjd9A fHB"` A ɥw(@XSǢϒ+FD Dt]H$B>X( 'XO@ PD@> =C1,>g ^\ @4F%<ҘԬDFbB餰P"0P!pShJr!RƸu]X0! q @ťN?hqR? ,bK<$P `X@aL` "HZh~ŵ8x8aL | D8 \ F/  "D3Fxe$UꨔhNd (: 9it(@v@*GQR_AIeN,ד J"fx$:!R@g K|0CAA_ P` FupBWA R U0H|GHQ% +'Sۄ=G&@?6K;o&ri@ص1_xQ@\Ɵ(7SX#0l} B 0!H,8ARޟBdHYpZa‚(\ػ0 @w(?$ /f6Ux @' C< D8B\5 W,x( z&'  R@0R SQLL3l2LOz CAĥ (dR?4s֡I] EhA„3"w;ŠdqR,b0WJZ(o =i#6exFXB k4 +'D1(n~'5D$X5pGtH& [ Fb@" 918B#P/?O!styW#xcP!gUf{-0ä"$G(DLDt.Z@¯_gȋQJ#HVy D&ށ8i2bάgM' 4zBz]M& $hpe~&GALiD)xR6@} 8 H1r \$IvQm;*zC 9 0TB( @$ dc FC!XEz^:ـNG-kgL23C*M 쎏o7Ԑ\h ׿ YVu!\@`X !O;dIAYCC@U'܋ (Ae4RB42*@1PP84!ļ.Q1Vz82$R  ~%TE! -U@HZFӗu3ZBA6XM,CKR/Bh4AM_0aZBz ƨά9(:MQLVs%hЖFX}芇 t!)dCMyt A *|X7cU?*VU@nV^j(h;taU?‡ٰ! F]0^V8 6!bݤE? )H<(NfH` plB=!"?"" ܀/ILh8v JH05 - ly(BĠ` e(@`*$W`)v mMZ% ŒGSG b@.OhMO f] -*썢 $jl sGh ނ\w=]@4@`|C/ G)AL? >_X3h4C: h %L0( Q713vupTUD3j؂!kb "ǐ(k7S *[XA'5K<289;3)Wα MF.<!KZ*ҳsX $V$*Q*ViD3(2CDrh $BKA5 }<_)^ b+CЁuU!ږFj yc1%n=$U%D;ZD4!4D(eOa@bFEȔ`l& mg^!TUE#3P-~сtAypAJUNuG\? * Z2Qw0S[BPq20l\cZ%b$(B AB%"le GP9 GZd/(J!Iq*KT!^yu9+O5SS.|*;_@шU R&TA 1Zc$!ǜb0 [$Q+W $A(9JB (.*!J8 1DL8,y 4 6Q!2ȎDK􍆔(BBgI q%(X"3M!#Q `Fp@l(4+ B@h`)ԃHE HxA tl%䌡ePDc)JЌ҈H4UAlv0TVrkG[!|I@Yܤ傴iQv=.#TaDDvjMjR1@K* d!J` X(VJo!60%QL*;3d\i'dNM-UBP&*# &TFP_CaC W CU"()?6=1=\ʱFQI2lӝ&Zcϋ;Pч$HsUT~4 !(Py +4Y-?BET, yiP骴FPa3Z%(B}꾑XaJڕkl2V It~^|9$Q!O`H>3@P"AG0(A*j٦ b6A#L5 AՀdT)GTG8j!&aF@2xX@ʤ :B JT)A`ht|T $b@"X,,$|8 **,%HB S( Sa>O _* h%l*??bO1$ : #/t 5_~B C`f/FH-D#2HEX}o?lS0? (jд$b [A# FT^D_@Q:5$CB©J8]𩀬M$MAE xQÒ2G>O< ,d4 $nV;bd4G8',GNJހ@Ë ^@Oo;179v#\)$$ mGa40WPp0Qwq_ Q.\y* %VX`l> \0`#ДN^i|r_,9V?'i@21eTicF#E(wQ Ezғs33 "!UuR#?@@`~@^#l CUAR *=$M(Aj/#Gt%90@D2(JT 8cTZ4 B=˦Ut;Y!x\QW.CVnTkSc Z N@f$؀ 8,H8TPtRcX(! ŐñRdαQ<)/.W)r $/U;B"nDU (2 ,G#%R!! @+:~@0N!G51pQŒ(A" U]c`1O98}@ `yHZ5JAn8 B(V#$2 !vQ @DXDdz@DJ{)S%c)@rp)<+ʵoג Tu tVL:WtT j-1x  "b;0R0Q b(`Ӕ"z  {CEXI),R?|ULBaBF+LxgG"P`8i-(K|ٔUH_o36(}6FX D> ":Rz 'jh@iHǤPR]OEt sy$6bXb *C&5 $2Ux&tQRRrnAhRY!$p\A%AtXqv`c-5(zd,:O J hH?@* &#Aĩ-4q:!c4bJCRrzWtHV!"ԩ!{*($fA̕.RV:@ %A@QJ! dX;01 S|Xpv/З[k/.c`8qINGS,dZ2^yDɧ^j9clr@( $BD`i+B% pr @t4 o4S%beykx_q e. CG\0 D@8Pm z $  p&/[)1(H @QX/GHKD: C.-TRD! &D2(9Qa4#$4R`lLBM]$"B/ׯh!ICR.lĵ8^Uz9pqɔM Q"2,ZHʢg-ZlF^ ::nNYWI7}o`X!iZtP8.t! EP<@٠DAC(T UIH?A-Zb4<ʡCa&)vH˽nPM=Cnl-r9v0><ApD@E 0$@DRVegh X CNXDxn)f#"R .\$*axD 89ژ o>*UhYv$ 3Ì`]U0$ GNi*,R⃐W)JXPV H} :ꪔקŦ!]&h!:bB#STo7‰ n bk˚HT$3D T pQbTe GHţDL`D "!DaűL Kh`) @M4IQR HE,$PzH $q@ R 2(fáT (FhN Zu箜!r/ 6z<]hzRs ,̆DFOX`lg`2o(HC QkXkH6PdT@LB^ LGU%3K+N ^lS0U0]h(=q6@h!PѤ,(QTB$Ic@E -(@46ȝ .@ @68">a! @tX"gԛH bEA*P2IEADL+83$i @s24P8!XFfu_O]zu:zJrjP4V<<ބt_.$OG 5WX*4\WTU`h1Zf”5jCٴ3CHRyj܇u P/iDf˭qͫz Pw1eM%R/%vKfUt"r|Q h&p!s@!@4C0F!LL١爃l̼hlB!# ☂ D|'A>@o  B!X/j@5%FJ"S;%"4gdb`z)A`{),xEg`MBдV.@BhUQ,Hi@4q#5en@B/  @A?>hx-D단ҏ'FUA!K0r$'RT#aWW؇d D!I@oHt̂G!pK8A-b"MDGzEʿ04Sz&(L=@JVq R%^bH'hSV h (T2$@6 !Dh\*Q %aR4R0B\@JfEV!"qhĂqNх ui/@EŊ$4ՏTh{ge,dH.Gx#1R)R,G5 Iy+E5s(kb9։stw=l%K5 ի[@G6l:(h qA@FJBzQ1"pHLrCFLD:r% aHkLe$W>`6SBxGxY_R\& `)`@'QKMcAZF[y&]ɻ7)i SBjV(v-+XK[ֶJՁȯ1( fA@Pjj : >R*쿢" R5Ȼ:8B|A+x:#gQ!_˶Q(]QU/ԋ$'ΓPpj%kݣn i%h ŢZ|8 z=F[ MEEg-B9GpX@QK|kXK?i-H*4 H( HE   JBj[@4,"EXȭfQ"B4Tu7!|Th"$ F'.:~ RvPl W?}U':.ԟG˯CgѸ2uxpiٰ)@Q- pb71P! ء=c0(wGpǟ ? !"#IX)Й-5vH6.Nxk Q6bRR1x1ꕉ~EuB@C C4 WAY{_$S4` (Ռ: Wzބ [BV)gdaZc2K[ ōAk5pejҥT$hF'ձc%ȹyd%P]*!ꔨ{DžQ-P0M2 I(3r(0Wp61-y9ʻ]pE/{> aD_f.=0i=7i˓k=')~&襡v]"HJ B^iR+B9DBH'(mQvdB(JiLst)s47`,yp%1EYQE=V#5.D`(ʢ\V^K AХX9DV=^A `B<hf;{FA7 d# !bfkX!bQӰY"A$(‚X!L4j*V4@P!HA$IPb $BAdiĊw.SCXhI %h!YQc0(Qd1嫑!nÆFƄƣ@i|j$*e$F$ QceMPO$V@h~($~;xavĐ/fBGQ"g3C؛& H<C8N 8 ,@ @8Ro` 8үcHWͤ<0sV|f(4.&0h@58`IA G!u0= E (2 Aai :PZ~]5߈5^`qgZT-p5Y1Rח-SFKN/}9 >)zr `=ӁM0fw t B&!@!P`o1mPaW bq* , %LD"%lK`,ߜ@" Z@ ( %J"UsUDPoV1*™SHQ_A&ϥHc f P~8dvs1_kOislAif `N J@T҅%銟 )2n&/HRz$Șcm"z44hbd .* b*K r!Sg $#$uKʲ\Ir K⑎5ƛ`F1'^q8,(D%A`iI ST Py -@RZ/W&3 RH%@LT!M:QZ:$&(bB A@5q$I7UͼDYckQK =7 "B<D$k+"+W5ﰿW#raC?S1,4(%rg BSB;lC@e^i>&yn`23@vA\Zgr QV7@@?Br-YJ 2 } (NU@ h]6]>@0H:-MFLe- GJ@^~F@A 8d$=&N-?JLD!D`/@hqvR@8?*`5}jcH($v 5SQ E*>H@vAbp'| aABpnA%B(-j (%!@YWB P@Pm*I@["Z`}L ''l@4P|EIvRPp#DIg95R4 0(.U==E8J?P~9 4Kǥ]3 a!$:śzJ_$nC ӰB rd=J`7  FADA`aF#BZ#,kt*Ki|@k.qFh% CZ$upi\m4 bAG}F$t @6L5|!-ڿ#5撃w^I}jR!.TWdrna8K)*6X/ ĢGDXTb#d@B NXS q"zBaQ8zɤ(@)Hyā2!036 d+A@]9!H":cV݃U]s4+ 1 ǐ-8Ât@Ll)o?!QNL]cW q0)q4yyr n4%N*俯o@Mm =4;ZlQK-k[Y fZGhqb0C@$ 2(ș> /t0 K 0`I*`gKiTE t0y8BE9*8CL4:IXH@Ҍ  " zH3Jh}ر8sTFJ_* m[YHAHAeAD!HN@Щ h̀ W:+F)H`;UG221@JR1JKkm7Pf|.t́5 |M Жztp9@h&4(F}F(V@SA4N.&4SRIƃ$GB tH!A%B4,JRmX@V,X*0:@4f T BBzQ -@d@UAdn"BR@ZD6LQ@DjD*DJ@X= O"CcI2`5P\AOAy35P &-(J:@ JC*`$xP'Z7?PA@͟S@PYAD(˽6@;D6(OA Hjȁ @$@LZ 9HH;XFg y!2 L FH0Kv0)/ .(15T5G X{0?60 A;,bA .G| j'@ &j ©:@ (6}OhH @ q *K]Hӽd2_H#XU$whۑr 6 W@qVtX0G$DEAJ;bZD(B JF0  Tp %k݄W I2FnQ\AG D4k=!d|CuC#Aq8AkI(;9$&Ld،Nu#Rb~HYW"+&@W3D$$A.4 V" l1 q;jq V&39#fF$+{T8Ŋ R1/)yÊBT"TR8; W=rZ2GXb(5kWaiDVF$*;ƊƊV.*p!GPp&>¡(@ҘHbG(.o4(0"}cF!Р;L|),H! NKxd CyS@\ǠJgP CA$.-t"߯$e6 be#a*2IZnKfTDqȦxjÆ^-Y.% )IhGD"X*8G bXE!*btwVMc̱|X.$av" ;Ic^[䱚2: U%d J$cAi,Y*UX#n?-ң8E(QM7:_ؚ*Ğc4\qt̕XZ8\#F 3(Ni-ax Q+FPEֆ1t4N/K &vc? 2Q\쉄2@T!djFH p yvA`"S+ȆR}JNzBH0@ h䂃A vfb4x~Fq 2z4U '0!ȡ.%ƒ+ABժ@\h# ,?{˓7%g)HKf#H1,#mׅ4FC!Y- f߆I&"eC1@@a 1ɐ!baC5X3h}xFd# scp\AR#@ zUO w]܄j?\4v'9A2&/ѢE& f9]r#ʻ m $rZ5"m (a(b dPx<#Y:y#IU*c ") Q4k hr44 QH,ye4\/ @LV`(,Q M!\BdJPPAխKr 8w@HRCHc% Ak1ubpa`Nc5Ueu;JgV&hΚBHt$B)PMqG*00QJ(H1(@iDAB)K򎘬V(2WKraZCiU4B+*Ie br%$l3 2D) .v] lU h e4k4Y@0,A厂_@HSJP5̾]ӤE`B "UJ1kM  jhREDXTQ1BcZ$PBϐk9czR4ϐSjYXH,I!2#S88DF K0%A+BFJ\y`$CbA &P@xT-/]BI%5 #4#TH,ADDTє.jo٢P&J`(qYp6L"t|}aPdt#J  ERU"uqRc;\Pŋ1-^tcJP*4Pfj F9բQC(ҖV0Frg^~GhTBH ;GWhE 1` ](I (] o}DۄĢ$Wz>RD7#X8"O9hf7܇7R$bQ _ (8`()xP F Py(!1@hZB+X  )]""Sv+A(^?׮"y\$yy $|#&""B1mtݖB ji.1kJ.H'Lϛ0D@8#lA UB)qT@x @!PРGnXd:1?(q]S8Caok Z+jc!b@rE@e&-R*M :H4&v0DH@7!\n tPjtE#XHŪ:ӻ;v|wrDtj|6烋5ԫreDNS@lL褪  E? PЫRh,1@M)2B@4Ji %&FQlv)Q M6x ֘o'<#ջ搢:\%+E6%-QD~g r;Tb9ʫaAqO#1*Un%;K"U& 2P4^nXɁQ`  E & i6E:+/,tt:: BE7/HxgpBsjyqYܘL;mVÔCL(@91G@?KVmntt  m 5S3SP`Kju Ÿ@ H J}h* GHC/.F 4{(,IHKɩa^C^֕ϖ+G+ B W_B 1F(ٝbyW D c=]M0a9"+N N,EFY9iHR?g 2| *ФUu#'`r`<D<@5BAp/@b\[ d7usxt-nPsh`6ߧ]>A􅨜 H" 2b""Ł2e$Ġm-UK)1DQR3a5-jDHWngZnj!V#p#D)C/:_VҦeǓq1* (B28C AdtH^UPeRq+LAtd) FS-XZ<9.4Z'0Mӫ 0 Ab(*S jƎ@EaU$@ ꔡRoS`t"PJ2@(: CSIHvE 1A,Kv5 -Av-U\ *hUuu< q%(AC(-CСar1BgC1A(>@ACEqӒa qrAJͧ]Z8Sġ(`:t  @ hĜLAp!uZ$_0HPpd(%/jR@sqS1$D+HvFh1MMV(@8\QnƊW9QG:?X0  @ D>3G308A䴯E|P((%AR朣x&7 9rqST%G]*K$;zQ$ nA"EQR, QP6@kAq'py"!ŽA! ]:&l,.@CJzT<&DJ(P@(t%!!p~% 4B~H5C(a@VS[ _ BAIUF |s`eNY(,AYܢ˜NTR? lC+1R  ,BΕb! ej[ZՂHB({MC^ hv.VeAT'ٓts]S3KDfjX  ( rׯ_UI"D կ ,xoP{lqMd7|i@rgI"܎~׫*wkB:1hXij3: ?<UTœ @J-(A LZ&U!m-5+hwZCB1f w|/H\b;H. )Pp qCI%#Jc!ZR%E*tB_8p(ICLda@6KR4bX2JB:P+MV:HVJ` $@BsHZ05W7R% GVxis8!,G$$]=.1"`>I  i,i,AXKF ԉI``j@h4AHYbaVaJ<̑F@$_4@qopq4+IΨN{qBĂ 05pM7LW3~FsF(HľqXQ#ԴC9%qꊬaňl!gJBVKT1F}LqР x>:!#_XZH!_5@#?7@̓ [lexޠ]@Bh(e-/U8ԌORI( (Z:"7UbAZ@ 5@i]q#+ !nk9NCoCU0A`DŽEs+&D*:Ox31tVWB (WHPXhQY+C.pHK#߀,15_k:,%~_ 2N% VqBlT[r jB\ ZT!POK-mAWxHe"!Py EdơG4 L\R@ ?6P<h/LFMT r $=]vmʿӂ`<6O,A$A X@b4B%|S3D; g86 E PIj J>#CWI+ 1S@.a(,?d>U~OѼk40 (07)XH!*^@z&L!K7(^PfꁠR[8T)cD+3,$Q)!ֿȐK*:EHA!C*Q* nsbLr*AT&_ 2@nNrbBK%0_̫zz",=-*sq3<2S™"ÁӨiWk2i >oPmG ;C ?{ P`PFל, 5.M\ȝI-؋E[ϊ 5Oa  ʣ,\PÄ(H]B  _$@FBvF,qmH ,w@N(B1PI]Pvv!} :A$D݁(@ J`q(- H X J@q*2JUS%LT xdg!B AA I!: !^H\9wP˒-?1H;GѣbG6"/y !u(x(\W K_pqBwgR@jewAƔ,N,%U;@fѐ(EE(a`F\ hfD(OC/a}~hy¥K*3:2bQ L8CՒKGi+ G B]/hg")N)!h+[HdAaV- LH AĖ |1B:_rU[p-(xdZ`d~Rd|AHJ,cO(4 _i<K2{|&!KG_BsЩRKP,Hur bLA pд0Y-$ =@=pPQ\jZX2? 9 1 R'O@QJx2%7[uJAftqDE5'PL%kU"{w N\(hgvXjhBe$4~<0!o rQ OQYn $zHpRd $yr)% B J:B>T399gPCVЂ-  K|K`Lh@P0VY9k# If@ @R+ r^HfW\),NPv+ "c F;F|tɜP. 53šasT$dE$bk`Cr!PA aJ|%KVzT9+#E+A]h6U)p8b;H;lHNB+Ph dbgeⴄ]|F!}81dA0> /B贚9ljPay@-ez$ IFZҢzd[ 3sT$ʷdU,QM]XJEV<OH,"L^i@5V$8<4TdR(( Mq^H(JDA(y 7hA@A UJ Pb  PH Ti(*2$[UV !_.+D/h+4Q5.w ='_Zr/<"#gF<\iUs1+HM9Acя==lñ(MVPgjV)p}bs|@>  (k[KGy'E&J)d`[I-PgEIxJd,JCG/kkߝME*3U5 }/ OP^V((6L4!@r:THaEPhm 4cBZEe0ĭ(=PCA@:_MA0h5ttւ+RQ+ڵTpGxT|N C DACAxP6~*ј"|XpEx8R'!c9Ad"wDڰooojʆI#h@a)zy" ("dG$y^#ULzjJ2oB 3#M 0ބQ. AA;JHf!zag*TM!grHHT>zN$B8A*荬 "!TPE%$4}(@#Nl +K}JDɹ]_ 09O °"`Dr V{":W†do )>zDO@v]= Z]i", UN)hqY"!/bbM1LQ܁-1 "2&R"05BA^(\R Bݿ{e7 v(fRd)>$ WzHM+fR"0,5)gEY`DIEOX㲌< 80R zN>q%q i,?G c_ e7e_Q\xU3D";׮P .t)!STsrD%Bc(aiAn$% rBP p"1aI:5/)XƣP,U]j,JnӤYQ}/R H9F<!,"\1 ҍkh 0*< khx`S1DM jП/< "!o Q3$ Ogg#H- G 8WL JJD&Է򎽂gJ 2RWQX``)G"b+m춈E &48@d`L:GQLmj[\~0YǑm@p)J"wئ̺ǐ1ȄbJ:yjgPPVգEwI-(J}4+ʝNLRHD%)E/s  *ϳj5*d] hDd1, %w".pW $Jj0 @i тF" ƯҚ)'dy Ў?LT!~:$hJB4bЎ@j*sadV0*DR刅Hb`t^}X'@gExwwt45w*@I52T0#.(Ѧ` GJ="r-.&EC~FjJ@ 1ZP9bRC#R0͋HWDӒbbƚ:4)V QQZ(]t)5i7!Tbxtlx T.jrPǓ[, (g&[$2PҌхDsdhhU?ɐ8*q>Fux]x% \##p.MMO Q*܇deA"Sn)\Y̼26%Ghf =\щCO+(#̐NÙQ)>iV(Un|A6RMbhn>[^*,!&bW4 1^8#za1B 3`pV-* `\s}B9dfL#1xZ ga !'(O"46"m|/@:JAA7Jd'b!^Z@0R$@Xg  -YY ~ZEiV<4 5 'UZH!Bi*y0kkCʇXe5wHȌf.,|+ơ+|-2P̋&%H"Kk2pfkp 17wZ @` ):D% XRDְ(JM)Lf38fxgN8+JD%(ybDc¶BҪjMP ),$e0S`%А&m-7$<{jz9-bY-YR0is7˘+ h50YZ?Y"T-~ _:_7#fb  IxG"K(' !`e(E'JFOv Nf}CE $PKQPjzщa $ $bD8qkG?(@@MYx&`c0 ߨ9wC'yIp֠+K L? F4 BY Y $_2H rp?‚zC@#8@@D @9N” '`c@P -XAd$vUAj~F$!nw.r, Hw:L#_Yf!;f!(h$$ QphPe)"4V !&}ɂJ.rZI0'j*JR m+G!֊ R(\>QLiE܀HI.  L 5bq Q*̌~))$S ~h= _&@(wdX0T1H R Y@cD@M'+J @]@TM:P`tPaH2DIeQNPЊWʱ^<Q`S[JWPX#j$-~ q&D(a$q li0 b #ǰ EkVP:zHaGP 1P{YlwhEW4 = AܐJ@CE_Lb q M4 r`MSJ7,@ C4P 44k GRX,1^  b H$% TŌݫ6~'嬒X U,'UJp> EB4#acc$Pm PA*ІMj!BH[\BZ#hz mD%CE rSs Hge0+H~b=_ޑkqY TU;<`_zD9$QAOJX"NPyAp*DG͈[F+`D/Mz1m}fAD p[KU _%1EKgKL$ytJbhZcO) ;HǠc~'.YI;B0ΎVp*+ZtɪqDEtѢ;@c @]HZ+,jPP7L("PhG&;$,tz` !Q:IvxIy@j09U R R h%A R Ph BFH6 3B4C֎,6 Qj(j3IumkF\O*Lb.B>*wuHYMJU?i )Ef$2L$j1 dcH\ $KxYi9 HɦfS ?ՠh)Ҕ;+  ӫSBDLQ>DO" \qH 7D Ăj]9wvBh}B`B.F>E FWț $)JdQ ?ԥ@<8T7WԿ'Z݉̚Jdk%2IjL"H۬ES@y:@`(yEJH_S0P*KP 8t" -+Y\AOAQY'GqZl6_[P,[,zm !Rf `@ r ʦy@,HXE"$ &ӁŔ$. ddY J$GƠ b=l |  ,kXFS0̌3cTjc;1W#F%hH"C.(q!00Ae40ILJ$XKJq#L):HOUβ- Pa&!z8jcHbHΘ Odsg㌔Tw&,(IOw`4KreH5 zi:JGF(2HV QZu? Bp@ʡ ]0A&~ )&;G/T1 :P(Lf{&L2s¥ҏ ,&uEtB|jѦHi1N5P1$5gh3##$}=@MR]x]V PCKxGP![nvh/,FD"]g{:!G 2PKby !CJ 41Y0!T *1`+*g$` ,<$D?wo<(Q@ G 0dm2i b0c uڠ'Ggh 3U F  @4ED1Xiԯ I,4Y͐E_44ZI?А*,1 R,XDҥnl<:lW <( !d$P'4Ag~eZ^ʣ[,i1$Ua%B5ADo:O< &xV.N9HA]N`l6 ~`jnx_ n=[S/hTR`&j))RP% X/~(q6_B@ hbzu*$ Hb ]XL"3@Abή*|fؓ@.Q;T@ϰ `!_`p64Q^tjd (LP0'l"SkG%{ U @?Y`H ( ,0  APe }~ d,J* q8k֊b&-24Ap`q)i@6qvJ2\SA BzYQ "B#ajCtajCtBԆ RD-Hm!!*@wA_B:_nL<-Ps,t~KVY:THQ@4@nj鳠~>? ʀ#4Bi> c]? vR?ҝH'tˤvC1Vs2c?G%e, r\ÀI,D@@aP`U hAZ3B2Jv 7#!_<0JYox`ࠠ ,dC/^"\^ ,!nC0(AƎ[g`$ %@hHOr19 AO~F@8`Ü,Q ^`Ţh )}8J $ QiQ#A_E~ Q$ P%GC %! _zH )j} 4\-7|j)_O31~]4 ?ӳE(4~NwMGlKcDY NaVuߧhHLEs`(Dt JQ/.4kӅ$A~c>_,$kP!Qr 1ZzF,oG`6w @ Hd H$^1 *=!D0E'HDrICw"n*c[qB?oV K/$P[JH/݌a=ʀ傅0`#s $EK  Be?VۀP,Pc0F~C0 R"(x#Cn"&b%$T %=?2$($[Pb I XhP>8+0=!!C J= }em+ +ϰwG"W@%RkeF˘΅ :bӄPSix)%GװE`p(q:C@rl?@/{pAB]($ٌ:.HP,3dxHه`Fi`%FqBI05p8r,HGDpZ3+#ѠS" jNG_L+O*1 7䣋-\("=`& ^ ]p0^% t!3v@e/ij!d@QSJ!Za0ڌA54`Mo 6F#I.K  L*.HJTONL ^6@r? FV4 P!QPGD}|.4_pz~B(BJ(E3|W'g2?0 G8_B쓜4B?|@:!' 3ViH e"Yv%DUHkvG^H+@( k_f"*A<P&,a!An &xjAk" Jgv$BC֩&ݣ֑2Ȳ 9<, 9oHQ/bhLFrrp{pW;F O@ 6MH98w ?' Wm!Bt0? dA*^\*q-Mq#7pP}!LUfbim?1%#T_i<R Ѱ4 P֐@ @dSk(,8%HȢ@zѡF.,$aK yB@PUt4RF#`jT2 +` #)P(& !^yP|Hx BRz&}ӧU$Hրh01M6Z/ZGꀖg6q48Bk?E}D5S @E)26B|1Zމ:~T)%JH=/A^:Uj԰OzY"?}p:{ "tr~3A #t1X"zQVCH<S<- YD0L~uXrui EbN/jHmOI0((`$ H PmA O[AX, i53/E@,FDY0O)ɍ K.Q!B !!JaS)߂b lAFԔ@ /f A0$K|fEbҟ, I {'A A rvF g@ HUǑMH т ˍw8`vE^FȐ1/i(:j 18`$LQՅPQ+(EbaN&S(GXE=ɍh\vEY s<|@}4XUyHGCnyT%q$w4I@A24QĦ6TZ t %ڀ- ;eurh=rP)ɠa I JJ!BAh"?͂t|BbYVhtR4Jd!X|- &Mm@ eQ !X-B<i*>A(?!K%O dԼZ@d:߇]sx@a ᱉E3 | c@soS$Ul1Wa(6a @dx)6*I<g!'Za4o VJW=Fk}Xl($ADJN#`ELaotJY7@1lHDp y3z e(k_'gʇaY&(\(+LkQ!Ƴ0J(BD 00Z!N TywLubW-\u\9[Me(Y1TF֦.V0LN9BykO(ATH#AjoN) v $ Od`_uFQJ:u qHOYyQi肝^]`S2TbGR@Tt޵8xC,D8JDF>HQ'?i0^8O.(!Bj0էrg)W#t9P30LY>HMQM=EO6z$4P%WY(i!1k.0h6Lr$Ve3W𡮰c.1jm$bɀl8p }!rgFQ`$agQeM5K}#« B е+ ŏ!Uu,LBN`в P"h"A !8n!JZ mv(䡑̹fF砶x7iHW$!F#lhLkH[Z%DBHBWGXV?e,Eb> b KNLEǕ,;I#Q@J++fs+ΌƦ@-ЎNV%%:$LㅊPv~j1T*bU\Tf))qKa=@ /o(p#( qcb@701]7)c\8@RB-<! _ P ¡yZ>|= xS3BPfi0h PH`Pb-` $FxHT`j42!xd^:/ *:@TTXt]Nq K*ȡ(Q$2,FPX@Ih @V L!E@;F P&@6< V<:x3-@P\"Aˀjɝ@"qd,S4B@kTmP->SEiʯk^R 5$"#kSdB4팸"CzAŪQ-x*%9P( lAH d] ܠE/7E ~.%; T!@rBd\iE)^B )A e0mV^NJiU? )~ `4HbA$c)H3kw P+S@u1w h$@ PDl7VxErBԏ/hnA@ { ߒ4}/ ]xOq!Di@8B %  D@1K($1^AJgg)ߠ [ A@[ `Ly/ #D xt+ӣ1&+Xb(;Av+E+U{0(pu`(`<+&Br fph$8:Fhr4p3@DЀPܦڎZAJ=Fhp#z ЧKl3?RK2(x&"& K9h6NMPhE $}P(JRIq*f:(PH1D{rP1J +S" PZ ^kNB E# TaƫB(e1LD?D1We|ZI@\ᒡꑟBܠ *ˌH`(C򊉂S@bÕh[(M, 5|u҂=1f_1wR+@/uh O9(,&z3;^"hY)QF#G|+!k p@DUe2c ANRQ MK Ii1Q I0&WJg"&գT  'V)*,!A=?4@-܈`_Ԫ!yȂufAoX$l-J,+c>w&zQK@(tCb!OIGQ( `2 sHSt' `sׄ`aG&Ң~GUӚl?Nk0MXjM24)G Heˬ wVdPNGш\.Yc\r:LF i,'~ j9ƳEe%li($ p( qj E'Ql2R\Ik{ejCJNjY$?P|w!? 4Ru6>C)GnFh"(L䑥DT0s8 }YFI)/.3S3b" X (1#E ,BA1p& =c;eN Ú8˖|Q|0p}/N1UtCw{ .B{&b56Q{0y 5 `A%5ΐ%)DHA#r2>۠ DkUA{-h.ցX{ׇ &r U D :BcA(fx.Ri+M]`ygXuI5-s?H9D"b%YȠ  K9@ji(AM%2,W#֜4Ult|#?E<9?E]>S@+By-l Bk_RD+zcB> r8}x3oIH]<=CKh pbX<%*BLt1KCCm>=HDo'~\M$ P ޮKwsڰSH+ &M(ZY tK^YvDхR) /"]( wC 6ؖ9۵;dʆvs3 2"!bDŽ2@SaBt J$IR:Dڱpe"£!!x)G4sf B+"Tgd2+H RM?Ő(B?`hp+" 8~1"g<ɠand3҅Thx8y1d>&~ba 0G̖ <(L#Bt[y0W[|^J̟ZC\Y#INO"PV^x&"!,$=i?3-s>CCqTxRI'qq**Q"hP`ŤsbH o^FaLS-~b d>Oz!X )$[T#%bzf2Y4& }̹4>&EKDOtCYCJ_(caL %9H жW9x ; 'lO'gǁQ(& kr}aI0j5eB Q &2С $E{PuU,`up[\RV!E!MdoZ"=2Q auJv´GE13ȣ [?̵Rz3ȤNizE=٭d*~NHKuWW Fb+4 I22BC: BS0:-OL9\!-4`bj)e#Kke]HIc$]|*+u,l7%J%1%pOSĬ%#ۼj[BzbZnJT0@  HrF! scȚbXJ\ yX}Vej8Yd*? ]esn.&wePTSp;}!n[pAkkQ&*_"A; ]B!,j3$DcI(RolS@4N1C.FIP {P z0 hSK3CE!Cơ?:?ai5<@ XnɊ !k4 *rFRJ @4Qū:¡RJ(꠲y%ED$dǘiJQΰ8i*2 IhPxQJ$ +J8(QGDFA 9T5 IQE'!Z)H,%;@P4;谦`kBr<)r%AQu1 ?la҂"!aIJGZt֓C^gf.`ٜ˝ VYx?-$%dT$?iDb8 =3 ȃ!à K% \0 tw11b!r|(:CRd'$C'} ɰQVNnY$pP2qȷ*$D]Io( E]`Swh_՘huaO:v`Är B} [ !!jY٧;Qᔚb3E-*_D܉AEPt@yE3 `$vJVeQH_U⶛?»R%]wh %/.,P1I[ %R%Q*r5ВZ瞿_>)u[DԱyvE"{0DG8#D!b?,fR ֙?\vsu͜v0ʏ$D "MY#P/-IE8VAS2v%*3)S!5.G1FZ)!Z{OFy' IQ0'f՚%@0B F+*a 25#(ZJ-J24H$͂)@ BiFqe&J{}0,tׅ0MhP  )hJycPojbUň Fm1l};%+K"ZfcA('hiEIf,"--a$!OQCBn'H[=u"ŲE)Yd{4Io@{o| 26 Z旄fS$Z ˢUM24ތW`.Kq)68i2 `, PB  A,h?usXnU8C$wCiƎPyIVӨR)|pG[敓FO{Lc#%Kq&%A:,DZ!"/c( nm SW|pzisjT*jQ7f)AcYA!踖U;Ul\>2JQ`AzZO(yp>>;1+'k7$Hs< -O\ :$㕮t{㌼QVIn L EJ5l( BD, XK1#TXBQBSUHQga,ո f|&8:ejԊ ÙJ8Q!@2@x[E"R@m$JBѥUgPKQ$`v*Χ#"TU0`AMj\9D!VsbxΊK, K֌ *0a EZtQ⃋p;ST J3ȏ!PX`%ҩ,` ?6?9,&X$B?c1h#bPG=O!iXE$ =ƿAJܞ8.S)(QԎ0x(d2#}<-jŪTMbp'c“! 0XԼ:P餠!ap c./&#'V/D ^mzb!\)e/oN)RC8tpȂ8S ɉ@o'(L`]oE`*Rc@HZ+p5J)bH$H %E]|d@ؘ%cz a օ"x)da^}Dw3ȋd!sN&n͙`m*殷2pW_DI8 Y6癈pxJ,M/3qKN'a~ǫ2!6 (`9# 6_!">r-‹Q Zڅ"35ɤX&1{g))̣"}6)o> =gP-g i#` xeI5 zG* )QqOKGC3eɗedڐC $$lj  5.:(-==)s`s棡 (|ײrp +rgQ;IR[ffF(f?j"yMryhּtM;.L{͑Hc =*Q$RP9|I, b\v+s6 =,;Fw{NCf.*#1m#s&ֹIM& ՚ 0) #CJɡ<J*R5:@b!6z `Y.,4l)D1E,җP. h U X5fP+E!JBU%D!f$D!8ATW!jC$ fp!F<^!UAf<b)*T/iQhc'B_FWE|%{KrzPd+^u֎H;Lֆ"EZF#aXf_]tLU1h! ^":N/WsrFLHbLVtP0:* tTCBQs2ϊBƏ_VJ$!UJT& +> ZdڒDϘp>ZR q 5!mLbʨ, ??cELbJ ,4&WB P:eL9Hf`a1'Tf ـ" q,R8ȕKԓ$ %Hg$ZLS6mR'2JN$b SuA#iPx3R!C!;XBAV= Vz ٠PCf`$Ha*5SG Kp (} e|>@q!r<8 8ONe!5t,FU$RS$MO+5EJ !Q$8$@B2HD ) H0{8[cCRHPe5c,y@B B:Mi 3ծұ/Ys xZp9qG2u5Yv-_`E/v%` @ RQDY8 7&ʻ Pj<J*IYzJT=* H*`:ƠzHya*`UEiuLAeq9' *dtxA# z9Xxe|[,^4\Ӣ+TG @2v!)0vu3F5[ 3 1"cWR)C%D1Q^"b,NDB(̀!$étjA CeΆdH3Ll 9##LEbrC)mp< TxEp%n 60*(%xnPF^e!N:HSSU"su2w 6~D{\JA .b/+#cCsA6c[ȅl M2o;) 4%iaCh"3%l;K hq`|b$88BuOlC xaèt=*! O*kC$!P &(!$ 1u' <[[V IsZIηAFs @zj $cFJ*]J Y6e.]^K <@0M~AJR+k ֑RDZaVB-Z;-zBNĚqi3Jx?($Bv^<#hRȑCVKA+` BKȖ "B/b4xvqhMUV )B]@*Lҁ ЉHB"4dEy v @%HH%]8=Axj RqU ^_G^@(o\#QHHbRZ^JEiłU0%B1q' AC DR0 HAY_"|#x$5u!f<fXlAgXb D~^򪸓(0¿N+tme›.o d J_I|<So`hQ\K|l0@QH !*WJ@ I@w`!puuu>N" H;`DLr2b P:xifaIaFqZH!IW E  Q䅖N>""Jd5@| :*/> [%g` h|e26H%H" ! |dB(`GB:_HSғAc,hiha[0Aޥ3 j{IKx@G "Xу` ؼd"Ù%/Fޘ+Pyv@ `)G(,ʄ҂Wu3y v?R>:4/:sM&E/G$@Q89*򤯊yA:BR)iPB<w>`A,J $0<&HB#A;@@2@@C/1Y'IS (y`%AFUIb`L.:|;8Hh)6i Q%UB窉R)8k.|t֛P`pbDluCk] ,Pq% !Nmѡytz @[-#Xhb~T 9T <Ձ'Ѣji0UB EҎ= Jz "`؂DށűD,[i@X!yŃ/.,(AC(jIAׇ`ԣBD,Hij&ZUU/XLO 9/p ɉaPkL!3R91 v;1\XE,\,X;Ò@pƊ' 9Ble5QA F1^>r!`Ụ FcI@BXkS!BE"QDr3Ɯ ӥ0YW !΢:3d9 2!%2+͇JU*@.DH!%2Ū#"|/@$  YW:vǙxQ$-8d඄Z[V KA5Bѐ4F0KSya1g%{yYO^xOf 9!vWIq'#ʂI .*,HP$B#AI{{aiamDC4կ_ 2Rx.$~8W! T]#Rg@I,!W bK@hFIE*d(AA2+7qdP3uĴ-qi N|&~:I"ZkH΀?u0PБr7 0Lt#@t`"#%!*$4zJ:j,Xuf)ñ !5f1j#IJ$h`Y$HuS R%@ɴ!Ԇ; `f/` 6 DUC02mL%X'i dT!bdL3ꎚGiADR*.MI T `ZؖIq@ {LHe[E "Jj(鎄e?Ɋopt 4ED`c@<إ@qiwʛq bHK0?T䦖LC`Ve:!H^^ u=1aI(QK2-w0wPH $‰`)R<W42@Du8YtGṑKE PpRŒ*sZCWF)}}&N`R? OUNOUv@H]$#-Rw mnw_L0rPn`quÜ?DF N$ C9(er;b4aݩˀ",H$C _b вF HB? H1Qe>1oOT/l  a0 Jp[\Z): l`+F<`)xJ<@2~`4ETbG`X]xwLВE?},KF3h,4 @ tJPЬJnQr[㒄 TW3"ɜz,Q-xZ aآBH-,h@H>ÔC{xcDW0 Xq$@Ďzr~A| B8Z60x0k`Od@G_΀0v r?ʑ!D#M1@ 8V?U>jG~bpPjDHX҂rt-N>@)=>WP%QE/FgFX 7XQdQG̜# ߋHTJ1 $# pHp·*aւi "DI*?7YYrX+@)D)I<ch#+06?,ӥ.C|DQ(3  U>׷+J)# ɼoW0|/KgN#|Qx)mEJ$nXcg&0 N5נ za5~5>5ßdkyPٲ$ Bp "= MV R5]AS܀e-QXi@MUҕJ(tZ`ii:EFӫNKԀXiKFbkTQ zpDd`@hO 7 >0 mPIa%H?T@zb`/05@, %_$|yBAgыG/81!srqRMPF=ӌa@hV"J-#|CH?+?@YAؠJґ _xᙃE6a-)!BD@e..,%@cާ MB(\ u\boE(x d9U bAƒ 2CJ!҈iD4-XWPIڳBE 2 gBvT>Q""]@B` paŐr!HJ#@[`cL~ADATB0$3![hԑH 1"u0`O=NA* t} J hS Ϩ 3 +xCNPe+E"T;MjT"ؠT|X *0BV(! h y+p= a RHe!:!AńVH +`DhPB*dҧ(MlZ%U䜒髤$cB2&HBH)$ L|U"Ml*lb`h(@Ő,JD)Ϗf,4TAjLHOjH)eň@CCBd (Cx&b`F~MP^AL#J@]%?J?BxI'ա $ -/&h+wLrDf o6eDJ&L? p07́3@ L)5 7ǂ;'a~NxD`!(.ғe骵Wo A@Rt߇`gPbd"4b) ,R ?V]U9 rF^F $@P [f&iVP8n͂(TIG"#B e)q& 8- A24[܀e,.++A51AM_[ۮu@#OlGa.R3M\ a0fV0&@Μ(A&5<sl&t@_)xI 9<,_>M.:: I@&4+C ,xi]4Н  hev!dx|8Qͅ`*02C( ::t>/Ҁ:!T Ȩ. Pi7 Qi0"tL4Q@$b(PQ44/ @ & 8cHAtІLO0O4 ε[`0/Z&R?h! qR$QLKY kPt}r VOc <O"ІXP(!S2Z8|#`HH`3Au5`U7:\""4d;HaX, E!J#|> Py@,r^0C4غPCp&~Pl)Y8zZZAU/ 4XB^ZGh*_(d+<`^$CyB!P& @lACAXnZ] *20Q$C )>E?R%7ҐF"UGJGZP ;/`ODo5&o˿bfDɄüw$_-11c@sЀh̟CC4Q4tDdqk0řH/-J&~dߴGgD?-$F"@15ZFz;J,(*ihkII $  h*hZ.iOP! $M^dd ZA rAJCDP:c? DD4Q$qeb=hf~ B\_5!* Nƕ QFVj#Lq.b*S,keBVjLĠ,~X%r1@J]cA' 5gV00ha X фAUP  @z@PT AUt@gn ė PKbH5Nh\P0/P 1eBmxxŌ!疞K1t**;Ÿf][? q S}w@4\^^^"0 ~G"XY YwM裓  yD%Bk/pl\yPf#$5k2@`N]Q":i)Tq.E~)h)P`2_ h I )ESSDt^BtZm gfFZb A~Ø|AEYP RJS$+ShH$FJ*D6D9X H2%J*T$t5HH",\ԠQGT-PK&s ,.@$"BfHFh %`?vCyCa `9H*i<_/t 쀲m4W~ 4H4i!Bۿ PSLzͽpsb@w K_2bT0֯e Yu@ PrЂ'=ATI `| 5 L%< 1$99$2%[ DLxJК0?"A9Dx@I'ࡀ'E DI K  $C =0_~q耞7 @-EVw` PPheh]oC BB#U4iQxM5mϋ^mH`=@=ba˕.} (QIV*uO%,Aw$𐡈 jA^ } \y^03D(P /+j4x,P\"P_}$AzE$Z@ ?IhicqCFcO3(" DP++oqϙ_g`$3D0f?M`UtK_ 8g0ץ42_}% YQ`R38$ 9eA ʡyA//) ];Т GVZv2EװRZ8RIqV9F 8B;9>3/'Ӈ8ŏ㔄Nf!lӺ*4PNXB4CqXrԨV<u8$A B,Gh`DD (*0d`>:tӆ G)MB  _<:YBk?{> $@% /6b)}uА@h1!I :+naS _T Aŋ(J C~S( QK& ' RA@xHS,9Yѩ.0~IEHOE| , Q2٠HMH)ӿ i(r\g=RAQ-Ezc&kC؅cPWG5QiU3水. dv~ ;.EĘ"jh@@D#j,HIK}QO5(\)Y,3 @Y ?cèfC_ \T_jOM 0P pРƈ@)+F1@*G>Ïڼ< @ hWDXҵ$sP"5~p6:S9ŗ2=U@P0y`Rrt}D&vxfb9. DBl/#X]ȢL* Mj9cM @(:5 B K Q(EV0hBC$)k^Z%"K~*pz]+0JKz׆Oa` %!"~/tM$E+׊ƀ ? v[NL%KTԨ`@n B#,X9xe1ve TńT&F!Ak$}oG0a", iO V AiP̂ _K `ʐi! A1! PBta &$(J-s`E4I'G g BV@PAiN FI) A/-;!)) X),VAD)UϔGQ82 (qdH$ gUaT U\}y@ܑV(HhK 0jy_?"xDa#HF1e+)YJ8P@3@B 0!b0DE ]:b?STS!dSRјSn"LU&+? *Sƅ45+CLFɡs%͘E/Dp2*&଑ #|s)S}^ P0$,<B> c,b]/ z@, A@0f4`Y-hRs G#@ P-Hjl 9BF{%)%e| lDeE&J*(thK,&I,0!J,"PḚ4)F5Tb y&ARXéD j҈f21bŒ(PB (PB$P$EĪUG2r1Պ++ i/+YE byJ9:r"^"J<`a*Ra8j3` #A!#J{dpR,'m.^NKn#T)*JSU/kX kP& Pòfg>4FR5 ([!dXI?1>B%yd#R,B~zb2~C)7cpȲ%ȨW0ufzxLrOS#$BPǍQRyP4K%mxٍ|']WIA%~Z`0S H$sCq(4)!TkDA )"`BW)הtD"Aę`1Myb@E+'U(j3A/!̘!^Z\y%",X PBF(Pc *BCĝkBLP Hc.}F91'&.Ll0sqL9_qE)BRH3^@򀎆J"x)J=6K'NOa(̀B"Hev0lㅒMs  `H0" @e!f 18z%Ad <˽U( @]yA-$@P(PT1XIQ-q,K1ybh*Q%jp EYX$h$RRX- ۓV (#ʉ{VÂ5 !DH[13/PKB3`^H8jb0BU!kFSJqg˥7PJCW^BT(,hZB?OdF7IWca_ IC"`b{ WRQ(T-2`VAi 䤗UD9b89*BU*:/^E"Y %EU\ ra>$$lxNbUo>F"qը.K`a0"U%cG<#V FI O%(hĀ >_K`_W>!4'e&1|d9J1jkH-ڳ̙Q%YFH%y%bJ @$" (!#z:aM ZC$[$^c*N QRk `P #&ȹC)@'!`L?ˆ@8 )~8 )e0@> .H@S&Ypx$CJSr89\6 HJ SFs1j#TVPJƱXBPŋ% r@I&U:k\(²x(C9>8.r4|yr,(Y,Uu{W# S SAE͙m+@&QUa p0 d{d$2gzZjqF>(\+QIQi@$`2-DH")u$L@"RGaK&8]cP$%T  (1Q?. q$T"`Z-ˬCpL-JH ʬAtҠ Vc+Z+p(1+v;A WO'A)DU`frdc5+DQ 0 =A(B18b238)IAm!:mbfr,R&(C¤b'hJ[!C5 IF 2a*RN × 1BwI#$W鏒+FEZ*D^1B5A Ԯd+8HN2qd' 0a %@"$K9^#JX ӎQ6dd B)Hm=e۰CO!t^*uM;L2e0^@`#*?P[+ Ӏ"U 3 0DC11WY\ekmHA HBE990hBzrG dJDqB6eFQ+#?=I_\O(" P`@ XjʊE%]e< I:k+ $(  fpnMD-2$ BR%LSGQHƮQ#UPZX)b_,EKa՚f(GYC"4 U%Qŋ!(PB A@Hh-(Ƥ̡YC*y9 `} 4TξwZa [1Y(CQF< >äiBA HV4!8ۋ0eUS~a("xB```̒8[E mRp`01VZ”T j q P*!T>иE*UP $2*H b ȠQ&XӦ1bGP,A$4)(Xב( \ߧ'Bᦘ)ĺdߧEY֚9l@! ʛ$ba%(X S d! (r= DrNAQZU!@I B- ! FW`J0 %B P(-W>Z[_ MPRiNb 0GR|D6=)rap cDŽ GPR-Dyx-U\V̄(b(%2ΆNĒ+Nl#HJ)8'/|4*J]G*X}D: ܬđ@efe}-_YL B 4(&d0H9LDc(4t4vPfdC K?vxVHm5_LO( L @ >C2 : '@MU Ž6q±LH$R `t($ca%A$RT` B<gPqTL+$hò yjE V.%0c1ϐCAUXŋ(PB % 2@(hIBT#Ɉ j 4`M\hR(T圿1LrVܪR1R[Ovtg B P@@QU\Rt 4Ef pℿ)N IlPq9?j9&Suu"!H ٣f. `9zkd01" O@@ F FQh2M0.)CTy4Xx jB JvF5(84$ ##@A@QL8VLZtwXt.!A iZ鋯"KZ5v J&;TgNb@ABngMZ% Go@`&CT`PlU;karx+A%HRJM@!PPiQ٬AN=Y 5MY~PHȭU3Jr5Yldaf#Nd?vt'g9+̼6)YjP# < 3Qm @E %B g{Xq'dUһx!;y[]lz$*8v Yo nqP`<'N u d܄~k1  8;N :"pѡAΟ"4$L y04 {PxVpB@ ( @MX YA h"婓ℂPxk#,D%"-h ?$ J$6[qƟ" Lc3D{x&6dHO+ #'*T p_8_B E$DGBJ`c^PSR"qÅC$B_^2N x… Da: a@dSLjr%M>ʡ JU) Ań0Yjɖ$PbPz h%j(IG\=CH6c0Aha, D#4"(1V1Ud]pY,K%l'd#HGXBD1bp:E"N$ӑ) Id_|'EQ"80СBPM`]\c8nOct'ܿħAH- 0 a2#f]eBP9-\O ys R4@Qȃ REI2TmRIj8d_@@@ @#]e TRr1BCt!j@g @3("T$I>AcA2H!C:u_¢D+,H/ !*#-*qd FUe+ dtY%dv2pvBLB8` ?+8'}.}[:!P0P 0(P@ A(TT[3ӋCE9^JQFyyUhB'+ !BVaoTpH(8H"9KNK#ALa@$ )UA4谅Ad )CPHh.dyU02P)Q $ =YF-q¥? 'iZ>cmM6c8)ϐXQ+}5%(UE,5(6fŊD FcB5cQFJI!y#Cy;/ B  D d~׷agXM# jZC&H=vM @  )adAj@_Pr #{cH h@惮QRADc o BjEH4$* E*`@PV|Z1b * ) A&@&C.k{? H,pDP6"tiDx ( (JJ840ˆDy.fs2PAR߮ѥoEB(X+?/A'G 0hʠ V HJ'@T!a4(x?l(r VI&Q6i 9 ̋ 8FE 64,Ak ѭE(% M~@ 1x6k0 mAaL7,1"`g G!SZFl u=\` ".MpByC g8?>8ϒrLI0&t]E2 !&`%A)KrgPPk< K%\f" :?LKLo4AV J2I+0) F!" ب AF?e׸e3"G3Ɋ@$/q$D$0^ ?%'= >B9HW!%!kp}C9*5@,F3YFB / ,T@+!X*V!\I4|)j/G(H00@ `# p !JHO Z=$)+1h`n`!$YpdtR~xM- !-r>'`:2P qh,FQ= :j8;0{||gj+ɒX8Auc" `:@= mҗn)4cTZaa00*,A J @7@@x @J Rivsh* G:q2b(Y|x̀` 4G5B(tgFa_J  ,DÙx4<*jC1j&`*rqx}@$j[5  AY??T6~OuJz0 ?D'P#;ٲ -BH ?ڦZ@ &HaI Oz*.1]Tk\x 0ʭtMKa.<ؠ!pXBBE5}F )Q3hx:難: DNA֎ 5KUG 3{1qj?xZ0eEptS2d#drX=) P rF#\aXB. T`nˉ1&$Ę"LI1&$Ĕ/>Q,FoX p0 O@CF] p !#8ar'R$$$XUkWO-HD~ 2e] ("!W zO{ܾ+)Y /@h%(=dА' HLR@h#S| J e/W< %"3j@ H"9U\%zCjo0 y( P(QXvj +N;[6N ALb&i.YȎXf1@Ih$ Bp J!j:f"mTTBEQP @` 2CB)B$"L~X`A&>A|6(P T=?dCKN,p_@RB_xYh 6d2Qh'B] @ Ѥxy/8Hj81V?y T )B0B0 #}ʐl#X8QZ^izgL(B}pHmгUޙB J8A^_ /Wr.@P,DC89Q ؘG nS' ?sxp,Čxjk<@`" =f1q`B 0  DD#r\BFƥ1s`R`+A[6  , ӧN:~>(p(1a;0͂g \@'Q/g6хHLXQ6:t+x)$DRZE-"  @$a`CT[" ߛQ+P?vDIZ;``  sa\A$-h'(@@"0@.6 BAB)Vs1c(B:$ZƸyD"=X-Eb!^Xb1T(ѧ7;Zr7Y~.hH~S08r0T _?҇\.T 0@)"oȜ'H]C i^6 !51E_](R(e _^ FS T7kx2QP &8<b C DȖD$ 2` m(iK?ajM`F `bU4s ?G"@ %JpHf@!xQ\7@4 gL +S&Mx怟?~`. $1hPR^ŀ$bOHo?[Td 0`n `.d( !KP&H hQ$]KE$HF8I%XY I$55AI%:p-w ($4 x^~/-!t ĂJ  y|@ A#)z@WUm-}2<(Z\IBC'^ k[vA Mǣi )LZ ̇0T&Rx 0%;I!؁$t p\|., 4pN %(P\> W R9;GҨj*rD %qp jT0(7/ ;Z%O@M3! uhʈ@#%|2Ce}<0 @`=pdpd}}6 6/g6/:QP@ffwN [!X@1H9WLHoZ_ / T $OȒ_O.W̜C" $AwA6T)P30 p: F'٩P$E7 q^!bTlI'xjPS(@M 3(-te0J|55fϤN .ښYz=g~ gp vT BBsH ̠$]w  &p" @BB,Tagx'*L(SB^4 "w0(4# 2d?#$r#Jv^ic 0} gMۈA$V  8A"E'"ƹpQ"@< "`p--05;gŅvpjVF[)hl$U_hM8B8p4. H$(]RBkkPS`HQ*a(PSҩ'zE@L0~ Ԃ%{@h44i9 LoE :ހ#@7Aj 8 Yi*Z4u4)iZHDUҐ!䂁JC)Yk!F CE L|JN!q_AHA{a19 pIF!YG QE/x&*U"M4;e ($*Qh8e%sNT?F>"PAB*O!rPX] BG~PH5@Fe0 a ڈf fH(KxƢhW@s6Qa?魹+λZ~aKrƋPE%bOiB2ʅLPԼFvJ>#]o*bEТKW%]:(QhAxPj$RP2 R+E)z,FX # ߎ~%@ X `'1k/  E78u(l`acJBj9!p`96H2+F|3DAB_zL?zvX[pya 8@Mu@)h^,;b8a@qa@t!€wct~X+^נ hc^i(:d#&Z C0z@P,|=U,9I 4#@J`cl@GF( J$<#O-LΒBʄd".NJd@sy0s'|"!/ev]131`L bo fhŤ@i%CR &: @Dt z 4|z,-BZ(?# nQFh4:Hh~`6}Y~_$jl/T!D\@Z(QMfQEyLL%F'?BBJh^ PTzxLj|.tpTSFVD D Ỵ0YWa3zP f&6hjj̠ ZP@ 8h\%"|L @BTI=T3RO.w !!B`OߴwN #șR L"0&J̈́WIR`pGk/?(}XXk L[=\TE\,!aq`IG b`}.vhO]'.IE}">tHO]'.IErJ(H!!$C$C$CH8H8H( p"@Y &n,f6gְšſ4t36`:`I ͨ\"f,FC3h#`xd R]]BGк>.t} ]BGк>.[Hs`$s`K )6Acd6Acd6@D^dgTa\Ԧj5P#A*gBXm|K c,я *Y?5*gjT@/_?|/_??@@{ rg rg r 7s }1} pt -=r]=rD=rD2f͛%5)39<;C9vR>;8p wd. <A PTĥ?%%1м `HddZ`c.(P>b9F3asZ=P2V_%~JWRe+)YJVR`@B"DL[(.a~cN.YoXa =`APXf:?+^ACf$YC& Cȑ/c0fJƎ#v(,"I5F1LxLxLh1cD `0 E# STdEeȇ@@=a pcŃ 0c NI A]h``_0!AO.kkQϗ`7cG2apӜWF8F@0QљNZh ,oHPh(t)0l@@ __ǹ*V/X PT222eKdY,K%6%<J!ӭXP( @h$}?+٤+ a)*  `J'X,_K^{.e̹e" `C+@2`!OV|G᜝8"E1*20D":#IJ3Z # 3+|4hC_ u8PitXDVD`"-44U7_jXj~rdsY c a0H$ A  B @!&e8B%A`!1F ]A$ C"LUX=WD)T \U136f̑R*Ea!<ˉ+W4$h/_ *8kK{.I$Ȇh.tHbw}T6vE}">t_X ?Pe e2*0m$@1~ %9+!%"E8G2 ~( _SSm)-$0P@W~(dNa4EA*©eB?9 2LC<BLAm t} ]B ddd>.FH6͈Sd9O33@o/U" PTܢ@u92ZBW 80  L+ _u( AB';@{ il3WX@UpyWP݀Wgf,_Ъ%*HpH@y!y!8H (c!y(6!QP@ !ffwʨ\ :Gc W,"Lq‡}͘@)rv@"#rBnX# һ=R 0#@GWČ|"Aflw݌](&ˌ,0< AH' }ضť-!I HRBd"@? x% J'Q-"RǤyN@X8"`6#ȌQ)gZnߨ 'շ`ހ<bHH)MlZbӖ(1A Pa/BL# BEACB *A9#+an)JqL_3`E8p u? ;RbSWb 1)9?ѯCs?9@ Vh4%+]c<7* @_~WԳÌʹSj 2)TR! /|#؁)ڭ Kӎ Nָܲ F0EM} %$q.B &{I%)Bkh&@l8q @([ b.~ -p3sAgh,õjɾ60:āw&4(Wd6  '`!ߥ ~RS2]_e lؙfqfAL5"d.0lP!;|`(4Av6d2}~i."I UL^(1&4~$PldqD$ ^Xb (PBPg %@ "z@!C=e/,. ( QUc00r|ہB9 } 4(@ BbĠ@0GHE.a0(HҀ`!_Nɀ?$r?ƸH$ FnP,& 8SXzPUE:S" @G6:y$b};\Od S$04 .DğLQxg](uҫ8M|Q| F| r9Ss GRه\ 9At16!-'N-ZuKBM%zb5=OenPJwdn@$, ##)6P1x``%= A6z>> 8]) d%ĈH O DDc1cŀ@/PS A C8%!bI9B-b+G~H<<b<*9dUHKx'0?HΟ< c0L@<{E:tӃN,Yaybҝ`;wN|%-C#VOZax= $744T l%ή 1OkC\R~t?VEB4$KV5Ba:<~(P+{MT_'I/ 5ƔǨl1y@q/| +`@-l7@`30f14)M HRB$(R'& $q#A 2%-^p(rHF F^d@CAD:Pq)q##?@ N? *T4hB)JU*JZ *B\+/P  0`K $@$HZ #(1$J@"@hF:8Ҭ,dɜ"G!> Ҍ&@r@=^:Og>Jg%Q@"pd'N 82pd  (^> >@BUY+ @^Xb (P(t Tu]u R:5#R8@ @^X|rH_aF`yyߍ5F6qD0e!m44Qs 0BÏpgh$Hq$< >DAlQ?el082E:P %@@@/ =HB#YB1cŀ:Jb_~s((QE*sXp (x!G3╬i]1 $0'$"Ea&pm1Ճ檼Ahc{ '|00@0"AE@>qk`)lZ`>Z(&"?@ ,KoPj}IEQ) S@̇6@L`Ro8P:0iJJҘęZh@@=`3 d~ |Ц4)!I HRB ,~$ G A"[NP BtJ d;ZB2(0 [а XH'؀9o6 )\_ $nnocc Pb(1A Pa DD$$J1.UB " -`$1@Af D0FtUE_\gt?Kflp JU[U2bC8x@ѕ쁀*ɛ+Lg՚#sqx@iʠ5Y?e@ CM@snJ/dW8rrrT4iP΂)JRJ- X1Z*mh$`i0*_307O w9ȌLh} ha c_dI&wpg/1{w(,dɜfaɃ0SCTp )XYU9@ "Y'Fhg+Wu3R K$oaHW2)-lV "fFR`: OPGN4ǦUlz)ߴC@3ޖz}@:ehJU1c1`vъBzjFrs h?@G 3<  u#)G ΛNSnucCUi:];̀ ` ( <qZR3 aOЦ$)!I HRBP'p'8NOc(1A Pb6l`++aXVW9BS)0) R)JRK@E0a !C|o2ɖLddtYg,L@B>7(l F;f~(PK`qZR3 aOЦ$)!I HRBP'p'8NOc(1A Pb6l`++aXVW9BS)0) R)JRK@E0a !C|o2ɖLddtYg,L@B>7(l F;f~(PK`qZR3 aOЦ$)!I HRBP'p'8NOc(1A Pb6l`++aXVW9BS)0) R)JRK@E0a !C|o2ɖLddtYg,L@B>7(l F;f~(PK`qZR3 aOЦ$)!I HRBP'p'8NOc(1A Pb6l`++aXVW9BS)0) R)JRK@E0a !C|o2ɖLddtYg,L@B>7(l F;f~(PK`qZR3 aOЦ$)!I HRBP'p'8NOc(1A Pb6l`++aXVW9BS)0) R)JRK@E0a !C|o2ɖLddtYg,L@B>7(l F;f~(PK`qZR3 aOЦ$)!I HRBP'p'8NOc(1A Pb6l`++aXVW9BS)0) R)JRK@E0a !C|o2ɖLddtYg,L@B>7(l F;f~(PK`q ZR3 aOЦ$)!I HRBP'p'8NOc(1A Pb6l`++aXVW9BS)0) R)JRK@E0a !C|o2ɖLddtYg,L@B>7(l F;f~(PK`q ZR3 aOЦ$)!I HRBP'p'8NOc(1A Pb6l`++aXVW9BS)0) R)JRK@E0a !C|o2ɖLddtYg,L@B>7(l F;f~(PK`ʬ `\3 aOЦ%)1iLZ `'p'8NOc(1A NbbC>'>^ 0s+ b·9ik0)S bOiiiDɝ)JRU*lB<ct@M>'2ɚLd` Űb8Q)$T8@q` L@B>7(l F;f~(PiC#\B?D of;M}>t@].A | '8RA0FB+FJg9r#Ȍg"1H07 `F#o"k`g)IK2TR42Y U@ ~b^r Ą  ; w20b@ x`\.> q\| ud=G=^a,((FL+:%:Dt(]agf(? D@-l$#H`p^/?y^~(  ut?G?_₅  tt 4 ttА8@zd@z@8Ȕ6 6( 6(QP@ffw:h. XC:͐ K%',;p5hRo7)@ 6~XHA8027!H IȄ2 Ѽ1P Cx OGte} zD2PX74h?Wz\~@qAHN'-$&*5QXhH[-ӑ,cX{#3 x%7j ji)^ "7F@կ pIrE.@Gi %C4T*@=~@n K,dKX$)(FH( g (R PI`y 4!tJ| ih%3BPzr ţO`CCEHhG_d8\Ww,mJ)> ̙DB0, `f !'z Pf i  G+b@IҰ qBh7{~$+0f3c2Ya d8CS%u DVGATrw:tŌ4Nu@Bp$)"pt#7 r&@TӿPIbL* ] ބ`KrXs Rd7#tsʂ XB;g|L&'zHC蠨 ZhL*gaUSG0P9`ڝeiZ`A`t  SAA)W䋢i LTt/HEHJ~IQXe hRt` )h@/ } !Dyb%D&fU-8~2!Ȁ 4U|IF@DĞqd$$ A &,@pJyJj b P @(Cq`S6iePfDe$$0q+T% (Pe&R|1@S( (C_y; |H!E$%30gጻ0z2ԙQҳs~q-oC1 +,cV:P{hh~Nifb.*,IMϡ^L_" pF,A:Рt_3:|aYoC($<С~ ((B>*zTP=K@Cɱ,> ۴P%()< baS%F?/@J1iؠ_P@ dѮ#>;0(K=ѤڤPGH2Cw7 !Apd5eBQ_[EϞ(<B |T0 2%!Ժb> >) bP s)gzcA@w/Eh7<0iUk@ͫ)? ٩oHR*P@!ӁjCE*8t Wbtkyд zJFZa^MkIxPPH  ̸QP@@ffw`biPNyI(QcXM ,`B PhQc 1X"zLd&zLd=&2=&2 OII'BgAc!3c 11DLq3z%,dK"QD%(DI9&PBHTR*EH"{u:Xcu~'|Ojz"<$RJP F{(O`%I= '>IOSc PbD"@@"BL 2D$I ]!l1-׌$*0 4`hf]v=dP"@$ƈ!,<a܀cB@<$42Q`86P 4~AHBA$($BHPI !A$($K,Xb (J#1`R@&h5JFJeaS}+EhLٳ D}pDچPr%@b8,P8ƀ/@rhPJ4&ҀPJi@M( 4&9jf1bXb @)F+zzlM nopH 5Ds2wpPPpPa6Pa6Pa6P` 087@@1 @!^dK"YȔD%(% "@H$$$OhTR*EH"U:Xcu:Xcp'p8'8 D"@BL 2D$I$дZ;Kqqd.i|@ B#,XB1b@2 d!kL @((QJ9c5ŋ(P( l a˫;88@@1 @!^dK"YȔD%(% "@H$,,_83(e 2PC(e ؐȖD%(DJ"QD%(DH#ppNp''ʡ2PC8 I16bhщ&>>i^" P'@ B#,XB1b@2 d!kL @((QJ9c5ŋ(P( l a˫\7871 @AB!K,dK"YD%$X gpe 2PC(e ȖD%(DJ"QD%(DJ"@ p8'8F(e 2PVblىF&M4^<&!xXD 2t۴xN@ B#,XB1b@2 d!kL @((QJ9c5ŋ(P( l a˫ ʦQ~)2bw@ H_4cy."1,/4FǒH|@#ay?Hy 1 f0^ic2D:F fP^hGsQy; 5 j3/4@#f(^hGr2BHu&1$/4G#BHjy$/4Ec2H- (%X%Ǣ^dK"YȔD%(DJ"Q'5g(&"d Tp(@\@DV~C$Tpş.9$0) "H.y@iWGzX]$%.Vޮ`)̀ڴ cq'G{ci k0o3&?8c Pb `0ӹgS q *a_@ O4A ݣYۄC K8eoyN\z"`D4Ѡ:gzڥ^L`(pj:h[ !xʂ&B (hgz=HYARPhJ(IZ&V&PC(reX/,Xb0`CV)hzaxN6:$,0/DΙ'; f3^"QA" Q<KШ}$@=r@ zvs1=PBA *''B#QXBϏAs $!w 9'CN7$8PTFkem+t(QMG}`Q2J@A!rU"Ȇ9_@OsMOj2_%m ( + Y(ⁿ%@Y%Tg] Q3 AA.p6XwH_ O|7Ĉ@l ` bTAC hHC\C U1p42gyٔ(0 LCbTqvMIN#EA~-F?AB)V@}=.(Q h0@! JU҅Yss ag].K%2r i:5!DIGTԛ9K&d@"@ ^Xb A)?t4|`1գRӖ xF`_ 4(Bo"?<*@C? ,Q ^bI0Pp @YH!`؟ǐ1@X?_*r[cp`A5k@HGDxo" xH7Ar>0H1Pz*Q(Ô8к#O?gQCԨ;$ v_!FTK$ߑD,Av!ŋ(Pe0Ft`Tcu̲` @p"$$adBޅ,BB+GA8GѾD"B(~ HHyH1bUAM@B:<4 `ꯨRShe/x&t+]T<X!`TbB~H?a|P-Lt8%AH0QOI"Yr?+|ɢ@ OY Q8_$[l5˔ #R%?]VSJxPI>AL $i HA @3¬1.EL$`YUpg $=  c--~,Z`?LtPW; P?كBE ,/O0PVH8?14^>hccK,I@@L H1H(!xx`ƅ (h-EB)9CwQ'B/c@?]b$0?` <4$26~K6"OjuI)Ho*ɵ2_&@, p1 @sd1 rB Gz?SCJH0iF4*.] 22+HM$( Qce}O27]+ pyd !H=!;";hB| (Q8penu^1wn`r E?eTh @/f 72c ͈4<"Q@FGbvDˤAH H)I Jff/~ 2Q8҃x @PHBvtGһ-y!jJ  B#I@#PP?JR/qAA"!(HpE/jC 4"x '@F!"-1mڛ»pP(F]`P't.Y "q4A@4Bh ICp\|z::{sjA5:PP4( PQJ*vP)P P?CIʯ5"^.8Mo+cbĥyx,#AyS (4!n|p&XH$am!h`$&+N `rV5H9@I%^ K2nL 2 P? i$¼@#U=o"8"DW  W׀19&i @o< Q(l #o@q_!  ?TBTJy8R* H$DHK@e/]4*)LC|iP.PZ r 0M"O PF"V@0<R(-Luu(Ñ&X2IP"Ox`Ol0a-S?٪iMқjr4W 86 0l~fx Xao"a@3x@H,8sH&\֌+?"X6HRDoGIRC)P>H+D.T/ W #L5@[NOܿ;v[x,,< .{pD hA'IP[ ?C\UP\I=Hj3\>6pvަ)E. Fԁv~nw=`AkbxTѼ_&;:beTPJ``N0# 3@LبDFD'S! _^R+_@odBNѤWA:f|3>G"gT)ƠH(( d DFB *ҀE F@BZF"E&9 K>V/;Ȼ` bG$ D =5vRJ(jnS"Ѓ7d  Ⱦa׋b HXG4}H6 P]Z9J"BxK"#,H)B`\ZyQJ]I#I$# FS>]>UspB&P"^qA @hDS(ShOQ+@m?14?x1&"?Ch@B,FTGpT DvT&=HO#)#xMG\Vo@AXƧ,e#ʼn(+0Oh܀ @%1 C@>^ė#^W&1y1z1Et"zLd&zLd5&25&2 MII&ƂfƁRcA3Rc@11DԘLԘ"jLh&jLh5&45&4 MII&ƂfƁRcA3Rc@Bh@ @0|Y`g ,I|A $' D I}@@$p' 8  Gz(֎ʒ3hip5E9R@/D`;p @Qp  @ M BHPQ!Ha!Ha D4f&j3PFja&-@%%%%%@((:( 2( 2ȺPO6mh6#`LmA Pð Hv ad,  ,  ,  w!o1#^bFčy5"5"5"5DkE!Dd!wWV,9#''O(ϻp^J<;&lGRfJUxьr%+)[VRj`p )~xdčy"5"5"5DkIq@+̧goE|uq O]:#ߏ4R|  $IDM7((r9ObٕuTQ+B!a*]tb@,0Ȁ;ZB^>HR%oFlDMz1dx4>;#Q/1S%)!r#cH?tIB!'Ԍ)1*|?F5|>!j"{ 0P <;SEό(( ~xۢ܈F7"iS?lԃjB#P!,Jc (I# ZLNbEPn IWe@ӑE!6X}*2K(\H( zG|K 1>jt?4 5)ࠈ~p($@"hE1k 1;@Al6zU4((xyQl+`Fh=LP9h|AQ,Zk^UBy,Od!Q Џ." 4'@ $ $}}KJu]8.>..|]I7(^AF)Pt"|#zuIqT@*?#K@`\q7+0oc {xa@&MPQsJ2 R~\ddC (A#CB@xXXN@P! D$*K ,^B(A D@@A\8  @X3qߜʷlYKpR& DT R H%MIV;l%ff̎, $ @fR0.6`8H37_ B (@ C,XB -_d^Kf(M%,~פ+~4ST#잲C0-+QPac ?12ƞ IGXY2n !02 . ,$r @#ـJ("6\Sр"r[ hpDX0yFfIOn~ueDf@nj  I;x@?B +iQQ򐩥r Gc@PD{5(F ?`Wh:P@`Fi0N_ꀿqbݽVժ(hi\@=2D$ZI+r@enbB !HU!].C/ pP$D@!~p@( vrzGH!# .'ѫ-[ Z 34If(0W8@lT ꀙ)l$l D!x& WE**z-]:*<Rpjpjdx;N. x&nj t ^2@F~$zHXNaA:~ <4Iź6KG=4d,頌@a]Ґ`ܠ:V0F0BTa ? AQgFH < A?*QHR!?CO<( (O&'B 'L IBE q3#!1;$ЏЂ  Rql?Դ89MF,NhX&` 818|HH&$#e28>@44? դ`b@l zl"?-5A?EB-Q3 p H?EԈ"ABJ0`B Qp;z4 Q͐m ßP|Fw&+mH"Z#c'9}Ϡ!:afTR@<d1&S\]G"ֻ ј" -w?$' `mp@Z?Xs/=8M?B!T]O]>("( AYFDd4# q4Jr2d K.+8RSvqPM,J݂iNG B8)hlYE'^|Q8#Xʟw@OI'&[䈂$ɃBR@v0HH <tWE"҂EK@/`wo˄->Y|( H#BN #` L@ ,> Q _p">(; љ `@s@@ <@7<;QG0#"JC-D F"?e?12B#  ""H $>3@b,FA$@ˇ 73cXa〵V,;]( ?0a@H2zBS0rA7:G '`,`q@MgXzڇY ~P`8}Bdl0:qa d{8 "& %.nU~/ވJ{PFT#!5,ħ|EVDZ= ҉LtF0a85RA@Vg FwEd間,Bu)a*3HJ3>;7$7%5)/Qc ($B {`d7 0p$PJ4BѧbSo,Ea$,E`\N&09>,|X|uQƍqYƀA "e4Ml]>@k9`wA0n40)@SH!M !4k@8/HC $0# i@Q e QʀCry* 6=$ 8A>#ϟ>.|\K@Mvh64@,&ye r@,  ,  ,  ʧFAcYi@`IYD*8  06,!ٵ"A!$5HkHkHkXט[HkHkXטט! +S"D[Gw_ۼ @__m<tN>ee9╨=,hDFy'HE кfD(P4r<"u<ĆD z z m DH~b]`!e`"w,\JZTT|].K%@(1c,$B b uH, w;Ϳn:\K E@ ED&ܚ:e@#8DS( ,f%=R$t.c#/dP<kaYyuc %a)e̤$Is|P`F1bnG.@CzP*`OȸH4.qJ`@8Dg?'`xU*Sm~ɑ{ g̽A?,',^%MؗlQ>k 8UwPDʁD?vT L) !Ֆ@5O@_kCҀ%3|U KPGp: 2p`<i5p $28azx`rj2I?bqb= )Ɨ-P0 |__?|/~ j /D/ @/+Ew)T3-}_9#|࿘6H9l, ҍ1Q!JPtѐ9z`Wcl4ȍ !mڄhp㦏P` +8@Y  #!{ORquk4*(]U%n@ [<` !t]O]>t.ES|B!!ϑQ H Ht BYqn-^PnP0mć):H zbGSԮ2av^"g0CH' 'l aWqo0ݓޙp`Sc"; x݆` z< L˻0`DXX36 L蘀6 @Gc,Kaga#bO  T z?GBC{0=b-6T4P;qC ~r  b5 ߨ`,~ _!E5A_!̀WH~  ~DG`.Àa D!e#-@"qg7ti] &XQDTHTIBʉsExAPH4L8 &6 X$1Z EseF*j>@|X>|>{R}%@|l>@FDp?`  + ;N;D/0MhC(/ R(E1+2 p]*JIwAyb{d=/ ҇Ê *_&@/g^!3ooRwaFle@.r[3ls@И؈؈؈|. q\|.> £ }@%ހ6O245APx.TDŞ.@+hs敐_ "܅tbe@C^@1)] Wzu$ L ]s@ `00o :bnpttDʰ'A5M191zi1E4"ZLh&ZLh-&4-&4 KII%ƂeƁcA2c@i1i1DL"ZLh&ZLh-&4-&4 KII%ƂeƁcA2c@B B}X$' A"}>HH`HH`HH`HH >HH`$$O$$O`lj1f5L3X k၃ L:P +Ҁ8 ul(+gqD0 º@A<#Ϗ<,xXGALr*2Pڻ|#&퉡/w_RVAPm5J _h:&yA{' 0x`8,  ,  ,  1͠Jp#)M~\E5J_ @i[F3nwrKz%v+KFE܅_-T9{KXN "30$xC!Hkh!Q!Q!C^C^C[DĆD z,!ơ҇46lT+bzG-h3Sf!ņAh @ʠ~zbpER:hZZ.́ Lh @A'th4i$5$ DB@u|KxϓNZޝes :?bӐ>DV   A (PBI?j5Fl, UJx0vOy96#f mվG+@,^1UX[J!7 AP,!CF S@N; JQA^6cBwK'` /]"B5Qw6\F $DXL !LbGW1į0(Ef!˻ AF RR!Cċ d9IA,nf7a-W?ZDxH0ZDTe @Qa - hդiv?ɒ[?r#lPa1s3&c'0B7{)HPt1bד^q 5b` `Ġ$Nd 2I8f8``!-տ};8DA :oϔ!-PI{9900`w(H@GnR@}$q``XS3b]-m){ESp::CTC Jt[Jծu&)<|Q̢]d:H m@[6]ΊZ} *BR(.>..|\f"G.>\M P$1(F j# DFjңNᮯay,4r`s8@%0)8$*8EBa2L)(cKEH@T/B"AacDžj F!P$#SC"!PsjVh$Aг~'PށvC$J5 SA%}G_E x) h<3Mj Aܯ^VH儉 yybŋ(PBnFQj5FQN`s E_P=J6qiKh'@`.yR .!rp !Qr@:ÇČؒ~~7BHK$l{O˚ n@`܏bbe:p1==__F`gOT%5+0:Nd_` )E ZRg<#pP ~mݼ,Zh` DSCQ DELtHb("RFM S-(ixHp'$FO*x hCCl m m0=Xuxʦ+:.AN5F D]k tA5 D]k tA5 D]k tA5 D]k yB<4~7`llB<0E!`G;G.>h ߲jJUpk Q NY>f^ 9J t/IpxVY 2!Yz;1hJlp&6yDZ, T@0|p (IU" G^,E&8J`)~&G&!H(@t !&Q@aoDzG} cN q H@葁1BH oN '`_?|/K dlr >PO &>LT` i&U nN)V@+( ,`:Da" QK-8[@9 8ŀb-df"DP{/:, -2((CП (QĥP!0]B)A ?PzA\ASBZ SecP!FʱE:M191zi1E4"ZLh&ZLh-&4-&4 KII%ƂeƁcA2c@i1i1DL"ZLh&ZLh-&4-&4 KII&ƂfƁRcA3Rc@B @BB}X$' C"}>Hȟ`Hȟ`HرaņXpD>q65vFj.@ * aU/!`)ap!M  i)Wp$A<#ϏHC $0"jS(\e#*2} c];Ӂw_NVAM5 @ M4|Lc:=up,  ,  ,  6@?5(kHkIq@+ԢbG+ԑ_|sXHu@1p?U6M$t^1:*~/&Eg% Մ o@Oasx`AFMQC^E z$5$5$HR2Pxw!m:Lʼ OsEb'/+'-:/^r󗫅] )KS:h 8A `Cs* ,]s8j,ZEEd$#on>N:p?|bצ #(ZGD"#f3T׳LMq7|Z8+iWxB!@c,#СȫYa,"B;YO$:9RO |41,1Uڠc` LVFE?W OWwG5" lQ'SҘn'0W9̗ Oڋ?BXPՇ6VAh3f< xDBe:* _)JCu9I^\Ґ;4yG-8K c 5@wv˶j/oYI@@e(#/)!/GHPG /Pt$J/A@ Sndbn  'CPT{'$@Ri+ X KIwK3T0P0 < "- b Ay$4&J!t F?dfȍ5v'ݢD /B?"(`N 8²\(YbsJ@ݼ 4  -_$(,&5"o%@I+ SeDMkʰB>^VʼnZz*S4M (0yߤ F@H>UUТvS(T|\\BdRj`t%!+LІi4y%6T4!C2D@*J (_HSOM*1<"e'*P*sB'٨yW63i\ŀsk甼E"F/#Q6.7T$#ZP?xJjPjf2]f T(GTz蘴CD8FӛoÖsq4G]Fh|7#2#K VJ A#B%]_gQQԂqF,#$DTTfhR#odYP 4}@9R08sk;EXVj#2=@ 1bNܹr_:Dm6c#Dp[gq GRQ$5 "E#!CUB邷OH3?PfLGi?‰(cNM QTR"S/0ú;1cL`?ë8jBJ.{"|=rqQ GKZ{#['#_3 m#t7"XKˍ[! (4s=WT_#nt#PxV4o@w; >$+lv #SnDD1nP|hM:YN99ODaitT5<@ "(\0$ NH?8j``g~#TcXff c",ʜ:eJ9'Tf=ʚ C*yhK e! Uulhy@W)R}TPhaE ȝ#GKd YtYKJӋ(OABOtH 4ʨQ/@ W>rH0ݡ?N4T^OT: DBQ,b d!@WIJH-E 1BkXQ`rQF1<*2d͞Y1 WD !(i-Ƒ@ E5cC a+,DPhR)fsր,GGRB?j!l됔V/gLʾ~nN5(D]ktQ5F(E]ktQHgOp-) hhK|HɠK#Yk"dP &.htHlզQ#XhTC e z($b39G$K|>aiDpA'X~SJ !@H@H` +S($hFZ)1 v1mUœ&)(/r@JJ8- C>GJMpi'rKhQR(( 4Cl $)@8 DG''.L{dp6H7'ހC.V1b (Bp^/0/?y/?*QRtLV@dRE 0Q"B%8 !VN&=T"jLh5&45&4 MII&ƂfƁRcA3Rc@11DԘLԘ"jLh&jLh5&45&4 MII&ƂfƁRcA3Rc@11!hQmKbGA#}@$p' 8(>I O3 D|@>14u1 4K3_*7K_]7 i~'Cmy3z'9lGy30v'A )N"8C $0C $0E@Q B5H6#DDDA>@( 2('66h@+AbgYYa;Hv ad$ ,  ,  ,  ʧ4@?$-(kPט111b+J%y/ "W4= F\ۻl=G̞wO{*DIOuDfUv8P$34a28`£"Lg$M$5$kHטטטֱ11b-jJhIݟZ'^>QXug$jȌ@ nx$'0,6B?#FbacxTC'0س\j|+1e,h`@`CP1{?SE?a𘉏!ޅ@ 0z@d` J0YIJ059pA2brZG {(J >hmX}O`&a ?"JnI$nH@T>!+}BwzCߕX|q C<5$cR5!b(SMhW]34@HG  i];x ` $PDBjl^íһ@$ W<- yt (@+%"X g}٬B!D }` &{;rdY3 Ap 2/_20У&x{<v>C W6c7-۩'!m4w8@@z\Ԉ U ΃ʍy[IP@ tjP0 ջ!@d2> I=1|0}٬{|`P" E™1B8s0 BP`)W8 IQ@D#&$ =,krAII<'QE UV4<,xjU' (+̭] GD?P ?(',R Z, 4@ HJ/LHpa݀ T')s!b  AbH4n_Un.&m\U)ӵ0˲'$@ChQEJwT|˄vB Q6aQ%bS?ڪ7hp`cX3 z@@ "DE> {`` @ZVHoZ .1Ă3 AD 1Yyb! bNWJ$F#LSzAMEAA= (.+@W @z%1 U%:ƒ]Y$..e!:XeRyGY" P6ddP B"4UHjf! "(SSP P4rʚ|&ɀE]5 dpk#1d؄]:gt$QH#GZxEV4xkG: 0+G5, -e. ,f. 0JZ%5Y @ ?L@@YAP?ďe((%jH"B?D3+!hYsР!By^(#FJ6Ko=PLÏp +:V3ov`Fr`0@Fp # (&h0P8Oas@^l$(+(*sEt,`6@ȓ> " [TaC+i z(+ UL0XBl 2 RbF NN/#g_53APdaBP@FBGB@z+FG=#!0h(@b0AwMh>$yM(v(:V_ $p[9硵hXu ,o<$.?hYl cebbbx("&K  @F % UjBK$a ;KH-TFHTc pY(=F#~m Btv?RZMĨ #5Fn$HY!D(R#5HQjhz s_? *y*)2> ;f,r@Ɗd,Yp!С] GdGA픔q:_;mNBe@?ӥؤ#}"b"\|.t ^~/ H!ED#Rz=PH),ZG2CXD  PV"C@nd)С*@Du1P9( SٮpAB crjiLߜ'lA/ /0$ATQYև;vEuOc$K5Q|̭z?Rl< |_x/Z1z/$v|G&e8L#g)/K0AeP Wjdlt}] l,G47t)qH+D3HN0iA(#M1 ߋp( y2q?ށZ|ror =OOI'آł,Qc4(E ,`&0E-( *p\66{;*(=1@T3/F3``ֈff_H@ 8|J 9@P((H~7 Qj5Fmf' ?8bH?aaaa@  `T  b0bC -2(&a9 8[k;9h?e $g 4)U|TS)?d Sp ,1P@j@1Ѥ@Ùė҉ 2!>Hca  $xʑZC)Zյ` :{~|tIo:EǑp)]x3ko\B#m<,9pP4$ /Ќٳx6l66l{=g!0s9s.}ߟH~OQ5@/n(p?A! SDNL>l8fsCH+ފ/>vx B(Qp5FQj5n pNOcc(1A Pb2 ppP0a@  (P0a@0v 22pE0N^(O 0ah;ƭpdeJtV@T BO'G~tp2T.vAԣB(PJZ$X!$c,XB 1l36a_жrv-?:Q=`FB1JR?o&ڛSjk$HBkK%dY/ pH8$ 1$ )@ hYבh| ʗsMH`DIlByA(ElR):v{?䆥5 # AGO=bLI )K-&ğL~ c *{Sy_ 4`  Aŋ(PBP PPU1cŀ (P  (O)UYs cF7~0: Ϣ$P((QE*s1X4@( AB@D^Xb ABߟ:.ʧZC6`l o{=g~`$$Qj5FQ N ~ p1(1A PbA  (P0a@  (P0``@ @@ D"… (P1JU1y7jmM4$HBdY,KH>A pH0$JpqCO'bLI ?x\˭p Aŋ(PBP PPU1cŀ (P  (O)UYs cF7~0: Ϣ$P((QE*s1X4@( AB@D^Xb ABߟ:.ʥZBݓ6l `llٶ{=g BP BBDnFQj5n pNOcc(1A Pb (P0a@ ( 'aC !Bc(PBPBE)VsMM6$H" K%dGA `H0$ aڙQIL]eԽg"14} gQ4q3c& )A k"5DkDkDkH׈׈֑ a@A,XBI$nQj50D "ϗ9(M))Nmf =*ߑsuf?xB>&44zcPP!( $~7 FQj3`(?ݏv=Ǯ=q\z Aa Dv*<}4S(HcՂuk Aj?`D `3d̄ f@d DŽz?wl" j~G^dGC˼@Q1 0$@#7 F3*Vn9n mLL4`=\`|Db>rNI Rjh 4b< A /~Kj 0\A H8(3Ŷ>jH@1p3`3,8?H {A:[ QAxk?_ 0cv Am94RhA qQcӁKzj@$>T\X,NBՂ"D0R%AI@BUYs,ߗYv;* u9P"|IVhPk~TR]= RPMG@wTT,9?xNsC-Q=X^xlB4R)9rd(s5hr(*PRTЀ@ A#,XBCxO/>.]4$χ~", 4<,,x"*(p/,RG6, S*`|Q!`6>RIHQJ4Rޝtl[.O(D@M,6I1sauQ ~@m5 $MxHU#bNEycR (@  5APHM/ 4U5 yhHwXG~A4RpfPd%!T}|{*;OK863O)cV7}0hƤxVS4yd(6 ඏV<4cFx5cC,-cѫX51PY ?ą H Y_ J, VB4I?$)SŪ1y B EϘ:Dkjh nxp֪&{;eė_@@HA<OB A2<&@h:{H0# $3`SP#v2| 3Yb IA F\6p:s%k p #<-YCח,Ѕ1I~/Å  =P( ?$~PB|e>`|Q@1t _ҙ^N0M̆1KI _I>3XC>!EU0K|Gg.L8 : <0@Y0̂G=PdjE C60qこ4IK&@<^@B-)@P ->;hIח'RHJ 9]Ɓ#X *|  0z:d@`Y}>_E5d%YP B^U1z@zz\&(&#ˇ|zċ1b1@xČ+ }P-P+)988UEE9DDtU9 '()= ܡ?-#!ҀK?/=/A^I$8$y0$BR"u~LJnLhqg@$A_D a8=V*DF (B=*=ˆFN%Ec([TIG<ʜA8 @E#AFf:Dyi!GPBu!_')Y0BP*@C`6 Ed{Dd(>$@H_G)I Q gB OT`A^_ACЋ<>D~5?4Ë@0lzZ*O(A~c0xp0c%HG g  4" 04O(! dq =70y#bB(a*!JYQh`('5 L$'*,`: (~sst 9A` n@g4P ~_&w@p"Hҕy "eF&"PH:7J9{ 0@hXX҇FI'*:w0,GB0P,Mb=H DiU0@f9 X");8f"4@ Ao.$+ @zPu*~'yDUP"SpDЈGJ Hm 4@hdb SJA@}вS Bֱ|}8%Q (@Od`r3[2ː]|lb9a+(|@/^<}1dE%ڲ.a{޽O`2P2R`A  i@4Qw9LUfs!I /E$P0)d %,[%LX",ff s:%d߀ K`$ )@zKgXLG&"M7cJVVi-x+ L{6aE Nyt|#Q?d'8O]Ls9) B~uVS5i6sAV<Z$ @AE>w]glpvmjHPf͘a0L$ 0L& (PH 9 *T4iPҡ D"8#MK.!az5sJɫ ;l'0tA:II(\[emrOfmv/+@Zq3S/rDX9krA98в S|N 0M?(` !`'Nb1|aD >-q@8#HBA$($YyybŊ(PB pdE6B%hFg_:;DbՏMl&łp 0@:/QJ4RqB ;wyf (dG;6MȈ}2<:^,J2Gjw$ꂢ-X" [L6,FjRPLjkuu^t(UZ ,@WW)Ln` |DT#zLYQV Jg&FZZ>Uimjo 1,1AԬnE N "Eqcy̞d'8N2qd& Fg&i3ILf4&i2BD$I%)JcUYs1c9'$䘓bLI1&$ĘS (&-r9,J2BFXl4bi0IĐBZX:>0(I&0 BP%t@}$ $g?.y3R8R*ZA3[V酨F!RQs C96] ,CL&af A D 10L&(PBiiiiPҡCFB!DDD(R3 DzNfb5fWˈ&a W%f:)"Q2L&LF2",DXt]#Hdrq98Аm#Hm)@<A 7c "{;6FJO/? |a@@u[ऀܧzS@P>j-u@ȗ*SԮQ4NV,7UixP5%<@%0 < r D93W5&$ 5 j(Y-R"hW7*{QEkd.1?d'Tb"E"G+#!98~aP26Ap`|+<&۰ah()I/A@((QJc "V<#jBw )P&{aɜ@RIER9O( <`@$=&  GrOhA "9n}O2y̞d'8LdCH4Z~L3&i3ILf4&ZH"DI$)LbJ9c1c}'$䜓bLI1&$ĘbJd,xBZDA{RRd@:A) L)^c2כ0p;QE1 D 9U.w)\M:ttb A |L& 4 (PrrrT4iPѶD"  -SL2cRX_> !S d+b"E$G+#!98~B@p=$w |b4 1?\P%@A: ?F:PP E@S4h4FV Wn9#@mX&XgI,`U1,XB (PB @TP!D$StC-Oϋc֘,(10Mb;4E@ 6`X4@SQ @+ ( a! (T@X@zBLl;`0r!^Xbc1c1`P u#FFGI$nrNI$HaD (0 I9 fz`,fiT$Hp92wp>Rሁ$Af@mMY:b1Pe G3ԐP# B7#35 dRhD}>|HvidԸCЊpB͛鰓1pA3i> KU 0#LA:tӧN:`cG8Č$a# HF0HC;h'xDI%#1c?>9'$䜓bLI1&$Ę@\n"YYƅ4od rBx |!&[!Ġ Z|:TbD:Di[ mfzpL  qN0PS @OE92gXH$ XN8S~ *6D"7JDBpSY b@ @ b-̣)|ύOn98`hj^L!Ai_xAa~AECX* X@ <@\F#]PA#_*׊A*G % */Ww@|A#b@29=\U-%JJ- i 2*+<|t> #,ReD(&t5|OA.Au*BV BH~`@<ˎ)u>5y8!( G9Bu3 W+ZRpzlX`dGT*UP D@J H:$FN@-+WSZ`eBnGVe/,\XIJ,I^$)9#8! ;cv.?ɒ9Gh 6ZUI3ܐR]Zv@5شLE 3h `F"a)8hY#Ta:X xymZxpFCxL@" k[>:t>ODh.$q#HG!B P1cO䜓bLI1&$ĘbLIL`/~pu`B|Fɞ3,Ҿ?N04U2TI6J@D@:D Te/@t`>|A $ ?01SrrrT4mD" !7 \MP$|`>@2Ld 3  QÖPiw8980t%2@HB" +WNtƌA4K+&h y}}jB  )T W¥@\*5&Ix0""RIf4^󓸞@#Og񰄀 'd|>`t5~0ϢvTK hQJ:}+[6M%|/`IgT;f\@7k/ *ھTQ o_ӐӐ!A X" 5)h! 9X0TA`CѥEبM`j'p t`#g (<n囤T` N$z@!КulGzFFk@~P%b@j0x qyaq\|. ,%@xll..( JQ !B<X YnHyMvfD 4U k0PB9ց6 !Rn]*fs(D wB$ QpF]PRoل PE*2hRZґyb(aL0j)f->4%0p D fk$"/rqƒ'|.taB{> fCsФ"%!H@@BS0#ni00/6W*mЍCnY Av,*l( D8xY n + * {yHeipQPFthDP r 0aF HL"1(y3Dڣ"cCCTcD#T uu X`ũ^LdZa5qc$@dhVrdk8B88BFtEj<4(#R1t9`uK[a&!4A[< *-G8MR*guP-dۈ;1 Kj!%_R rH&{#@p b?)?H>~' P{-K0dbRX^-73̋!&BL !D$ tRJI1&$ `A@, D?~a-{(p&#(q1O~b8d!r$ÄyJ$B[ ^i)/ǎ>!$ S@t#&Ow0~p  $ :t?cPPTJL@(8.@@Ia5_ȹ'QOΐ}H I xgdII)"LI!/ʸ " sG@s@ >8Gk\Q H%7LP-I,\+#+hw! #UDq'ݴ& MfmpXPއ.Z#7E@D ] 2YAP v43d4CQDUtN@to e#<E z[ 4RCТ"KBK#ʪ?W&HŲHӵPvH`X!B]FT(vS zAB  M*iPt zacp#g"X@R $W PdcNC@%DTP-3]:r `' ' '   ̥ QP@ ffw "W1ֽ@ E|C9\/!E"%^(Jva`9y $XX"~0ά'̿uhH@Hl*HՖws×tL$hD;<3r/_!4A[< *-G8MR*guP-dۈ;1 Kj!%_R rH&{#@p b?)?H>~' P{-K0dbRX^-73̋!&BL !D$ tRJI1&$ `A@, D?~a-{(p&#(q1O~b8d!r$ÄyJ$B[ ^i)/ǎ>!$ S@t#&Ow0~p  $ :t?cPPTJL@(8.@@Ia5_ȹ'QOΐ}H I xgdII)"LI!/ʸ " sG@s@ >8Gk\Q H%7LP-I,\+#+hw! #UDq'ݴ& MfmpXPއ.Z#7E@D ] 2YAP v43d4CQDUtN@to e#<E z[ 4RCТ"KBK#ʪ?W&HŲHӵPvH`X!B]FT(vS zAB  M*iPt zacp#g"X@R $W PdcNC@%DTP-3]:r `' ' '   ̥ QP@ ffw "W1ֽ@ E|C9\/!E"%^(Jva`9y $XX"~0ά'̿uhH@Hl*HՖws×tL$hD;<3r/_!4A[< *-G8MR*guP-dۈ;1 Kj!%_R rH&{#@p b?)?H>~' P{-K0dbRX^-73̋!&BL !D$ tRJI1&$ `A@, D?~a-{(p&#(q1O~b8d!r$ÄyJ$B[ ^i)/ǎ>!$ S@t#&Ow0~p  $ :t?cPPTJL@(8.@@Ia5_ȹ'QOΐ}H I xgdII)"LI!/ʸ " sG@s@ >8Gk\Q H%7LP-I,\+#+hw! #UDq'ݴ& MfmpXPއ.Z#7E@D ] 2YAP v43d4CQDUtN@to e#<E z[ 4RCТ"KBK#ʪ?W&HŲHӵPvH`X!B]FT(vS zAB  M*iPt zacp#g"X@R $W PdcNC@%DTP-3]:r `' N N   ̆ QP@k ffw ~O{Q.KW V/1]ܧBV+Z[iP(vfܒƈJ|@k0 70M×d" 8;<3r/_ 4H(Q AD $H(Q E d8B*(0&wSHp/l08?GVEY(&zQx1܌@$v:?x'{Nw(~e,X!CC@p!!2- Mh&{ݱjY IrI!&BHȢ:II)%$Ę@(1@ S@t#&Ow0~p  $ :t?cPPTJL@(8.@@Ia5_ȹ'QOΐ}H I xg]q J0`F&,zO䜓&`A7?̼ p-BNZ(Xsuѹs{;d~oyԀK9A`C_! E%\K! €&@ہcxqR6IrU*Uj G<ܪfBSs4|Ƹ>,丟ID#,%| y|w['H$lLZHPI0 ѶؕH  B_%)0R"*; S}_LGJd`p.I娭* uaֱ  d$ht;s,b1|7DU1c1`"CF #%EDR`0PPE/x&$4 H@X(rJ)POHtaBD{%q1. `ʦxjahdC)p tx@ɝ?ႈ,*pip`PYpY@Nh@8aI! Ø1' `H.2!B#`D J'f@ A Dyyb-a"s@ IH @1Z#jr @tGCC 0d) /aÔ ,\H.2cJ 4l69}PyHG6s%PA9C"gNgZap 'A+ 8b>?(YP8(|A36@)Vh NQ)ʃHw`b!c $a B$0w@@6 p. DGt]>)@((/d t44i@(K@$ h/Wƍ4H "&Huu/A_ Q1 x^~/? P @E4t>T O$ʠ B hP SC@ A S '-68]7@N N u ( (   QP@ffwJGD9"XlD9ӿ36))5BH@0ySRdA7&֟ɽ(;0L@?8#Wv/8-ݺdY`kQ6|. !J:pj1t0h(4Oi0$zHa|HD 6? Wr0KrCqrz?u$2B&P%N9 eA#)Z԰BoG7GZt`> %t((PGOOHVjm!P7`HD22ȱ\|\ u #"`f?>{$j=N{ C?bz-+δDbPzl 0D"&*WំrwTSe !C"? ww Y4 CLhY$ D1 F  @4$ 4$I?nFQf>H| bٳD`Q1z~̀"#~`I B?Ѷ#$h QӧN:f  H $V< A A; `5  0sTC4}`&&OំpgH"j3` ~ xCH3|NE0! uZ* xGD$$ 94( /L& h?1 @b\&!=8!øecXĀR"2ȠE0$h(J1?;h @HH#@@ D#?LFPL }0y Hրh$ I?oc PbsE!Ll0h0@5 ك0fM_12I0N('c%QyDZ3 @ f`  AϒKl`8#@PP_H)BAABS׿?N< 6~_}@%a&#TP h44[ 2@@GN"  rBX GGX"6v`&KH̐X @HHϿ Pb(1A 1Tw@c+P1ghL8B@!<b :iހX @@ K'a0H$ , $ OM?N&Up2sc@w apP@44iӦL @LB 5 B"'H1`8mMLV{p'8(1A Pb2D gm>@R{444ַN:t_`, abŗGB<5P%0?apm;@qڟ@ x׀-`V#}(`H 2'L  @((x~@ } @!|0N`٘N~PPPh"3P.4ă9wl'u ** QP@ffwʯ~4UCdb@s6 NYoHFs'" @@.@C0ECdqu=Mm.'FA(%CAڀ^:^^|nL7`,}hxA12T2ι2;h I?u,ehG `"@rB` H"jA6_@0D-P*. f8F(X \ /62Wv06D5x@ O',T  $dd"+@(4@3@y8lw<i314xz b(hQI}`v f135kn˩6кSW`$  g4Z~L2! CqSؔDD ',2@2:etY,K%  A3 ffl/qj!q8Wpq~R  ( QK'a0H$ P@ @H$$I$jbp  D@ A% :dI>@;0fL_^1&$dU 3Hg 9^`8@CPg [0!O!$$Q@` 2dd[N3>|r1 1o8jf!/Ȓ{"8 Ab  $@$ HHc>/@t Xs2"(FDh) @: dCc&L^r󗜽yh b0PDS aW$F R0t-^#p$`D $M҈(P AABRzߟL@?@P(((QGHhѧB 4?DʦH@@ PPP> GGK ,# ) A ?O0P)NA{EEސ:d FL3}^r󗜼/9un@( fxZ?DŽŎ upAh pQy'I ! QH_ヂ"$@oN:t@@P(((tzzm?N)`3PHs?4@(@E)a0>`G  b#1}!ؙ  PeGIR3q}_r󗜼/9wz~x@h hx3ܿ H1 Ć$a9a  `J VDB h h444ioϏ:tӦ`dO 99!b]Ǫ@}n5!/H&C   yybŋ ~H @HHcX  c0^ @1KGN^@d !ɖY_^r󗘸Z@1`qT"t@0fgW1:Ip P@@ V#'G^@8 M1s" '0(  R~:`qD\((Q^<   uFDx  PPPqT z:t@d A s, zpGE@d `ddɗ}^r󗜼/9y˯p<*5aq x~&<&<&4q>:tӧNCǃ`6l66l0f 1 P.C`|@( R'a H$P `X ,<#0&0 S ʷM&1V`CHiih0u'1P= yA !^+1T@ O (l X   @P ,t=@Eش@X "4@h A*A`6[  !!  QP@ffwʲ}$R:2 vy7cOlt/-v`P%a%@yyf_nv.a\?BAfFxK?Aed ?"PM{6Y2嶥!F3$@h,#KO+͔J 980}XI  9F,Zx! aĘX\5 q3qe`_/%gMVB >mrQߨ>XlAU*CG̈}G\" ?!@sx $#Aa+g0y{Fd0fPG@v;`3y7]Mt. 33&KOɟўf r1cl"B0d2 d g].K%d@N@f3 16='2`v Af333gK{/EėLK%ZB`xHgƓ;/ ȵx 8X1&DB,2 /QAH2`:@2k~||tyq@bb]:Lǜ{ FS4)6;-   ~Xb'  !cN``u (+KBg( C: !&Y_ OrO3A@uPƀw;fTQ @ APVC/bLlx!p9 O?A qKID @P () (z=:z0> (PQ1E>k6j t~?f<!HPPP}@'@ $:YLѠ:J@/C$H*B.PsGJb@l dd}_r󗜼/9un@a8u5ag~&<&<&4q*@ D  |@h 4ӧN8`~"a`l66mpz 03dBNǐ @( ABa0H$ X XXeL 0L&&&H ?,qʨK+V`Hk@@Dp80B|G@)(A@(}c@E@5 @ *<: .~蜦P 6 6(I6(wQP@\ffw\_  ¯,G6΅7t2j % (hR')#/@t $`n\`lMć(&& EC!'`tCJ~I 56_2jK@zF$;Я$DC q) E"^"F5Q i90D =xC5((!`$kE Vf@u Q+LZw` < O@QS %pIQlYETH"PJWzt}y?>b?Xt$$=K"Y;D% 'F0ҀcCB !AC) "L H * _HIh}$I x ?@t5h6`>4LɎ7Ppuzsue)nM )'w$D( <1# ; h{'k w?2L$I%QXB ebGQUqF"Pffff<" pQ5ǀRbt<sXf'}`Iz'^|A%X+@BeTPrft;G7@k@1' 8ـ|IaCm*g(Dș5 L  b12)0p S¸ъJjS6[CS1}<@Zw(iXy}U ԍ+Lb 7 @\ ai (-$׀R7&o`Ҭ(<5Lwe)iB}0 "*S@h RJFҡāJ=CCA#GJGO'\GGG1`DiO€!D記,G,XB %g `3'A)lUE/uxHL>o0^0 /aȀ(P,BIB1b %s ߲`$į )Ȁ28X#Q鰉?$U T`1FUТj݂((PV}5.ob;WeArFB?+e@ DHd!`*+(#p_<\ @ ?$l%Z7Hȇ@\o EI>h{EAZ @!R,Y4)Mv@[!wD!)/BpjFDrԯ;.kƊV:EpJ Ozd8&-]H: lpn ( }2BTKi< ^+S^@ #8Ą P),Ę3 & k~B`I)1c 3Ɍf]."$GP*)+!Cpd 8[xACB:B_,AgU!p!!`(߯ՌC?㼁.@@BEHCS(n ) Vg& A^L-h. $ & Y߰Dg|+.Q}>U\H~!' Ȣ65HCD? :p:|YfAPY5| X4r~ב)Ǐ  MlPA@   eQP@8Jffw}  g5d4!yj _h(-ѰPROk^ o@_Pb$OtpB"E=?wz00q0G5`h'( )ߞIS g00%؃@/† EaT\6Fku9  5o?u`+1b GѦ!X[FRLla„L8~_ĥedąE (>,5gXw7rf/>0O?/@r+\ 950בh  +$T% wHEXD@a563*A6G䃪`Dn>`p*Ѝ! ШP=D KM6 ,:X͋Sā82]m$ pT]*@P 佂DzJ&)!r?M@w̾F r^7D@0e ,W@B/Iy[" Zɘ mD!NHiz](H &@P)xE  _ۣ8cl8z7p 4 +H EQJ~@Ar!v./Rb1A$B} `Rc@ų$3_h *a!@ AD.Z4>@UJ 0}ERb@cܢh=;5K_TPr>4l4)"].A]L2elצ2Iq0'̶#/9P=XHP]wa7x *m縓p^;@Q RB%( ? JH*eDJv Sl$clim0|?TRUp&0РsT`qyBmO)HF?h?Sy 9`qS7BWOՁV + @[w5)`={/Y34 QAd-dmo#4JF X h.BZ8{opؿhSʱ[$A( @KD?tˇ\h$fnKQF  RRuEEh2y,0*DUz(@e HhEKD>_] $X4j"a. ۧPј k^H@mǩJG Ĥ)~ 7A`5H"G!Zi 4Q |uz V+o. !R~apF5Y NgG'X1x HX$SWӂD^%XJօ^+' c|L0(;oώH YC?@$IAJ> KWQLJ$ CtJ3_OHj`&(h*.U08Nh" 7 iQb,(>F0@>$3ϰB?z2P2uR mL@ aDbޑ`AOZp`D & 4W|FP@R16;^__O&o3"B萏+Ee*fPt>O@4LGK|A=.M9v%982fz옖Gvf< ))NC3!_Չ΀u( ~jOH8UhY~Lbb.P,JPS$* " IvhI?5CtdADPlGc>3T~|fa D+0 pgbti x䬐'$8(Aڬ崤QAq[Ey|Ϟ0059U vmBuOMBD(b2PP%40kEj}ƀ[dž쒐98 XEh(@D|~+'74I9͓#@XXd4I$ a44EzV&6WoPH'(e$ &) 8֬@iIJqXiRW >F*)6@4$%*(EQ1ov6|x@ᡁJa2ϗ\D0(Zl RR9)1 PO믟IO"܀!GHKòN#|)_N{Tx]jϙXiZ !qmǝ*u)P8CJ-X, #,H4l)*#)PZ Q )EPR)9 LЀ@N$䮍)Dݐ(FHS F2Oyh&엸VPrBN(rjCW$xjcE3X8`:k(2 AT.2£h@i# T-SHE9FF䅐 І)6T 9N $ThR<@CBȤ& H  @*ԏˈ +#?."' xPb#a;de91KGV\DJUnRܹNuЏSM⽰+]93(16ηxʤ*Ig U"@ . &!b^0J:AEJ.;NL3ұɋ۞R AgwԵhh "= 7bjêyb҈ռ϶nqSbwDYS@8   0 *6@<( $ƫEThbPAP]!n$h $8өTibe `Şuh,"A IBp-q {a1ؘ}  &-,j?d:jZSP(A8(!@y2 =:t.MZ@'E=l6hR TH%ICNFa^_)D3$k[MiQцT(fႠVpW9>Oc!r !7s K"11H AaNAO/6V cL p 0N0@x #hAUXA*<9(0AZ<2~[B?H?!~CéCˆЄP * #xM!A댉`< b!@K!:6*+p3C1g#pV/OM2}JlCzW8~x3H)L1xƔQ ZhO4[ *oԂ!$J,"qiH?Jˇ"p1J$ I)XZ UށHY b ɂ`%t9_JGd(e?MVɁT20Bc_Nq87@R#nPȣHf PM,m߇1@ 8~l@! ̄PY@F2qh= R  VV̯~!eO/3e2ReR9oB$2H2=5!BFIHXG1U / d|Ji @(6c<}l@ӻNCd$,@#c@)cP)+B@P@8|t+%X`Lz CDPh()N h~SE%P ~ %$ $eE :Y(VhRoLSOrOx!,z̢OEO{>$AHGB Q@$eP Nj(p"A-@|,ƄX(E%&#DI,H,D`C>AA<,˚Di<";=4c-^X|lр"X/ɿM9f 1 dE@?ۈ _ ?썀0$` m ۈ@.W-,!:P ) \`Ap /`NFeC%ա)Oh:䟕ٙcStuܐ`Y (.O,`c{@J D!oB09d,Hpj_BXM812%?XU!tn:_ 5 2!ސr/XO(}?Ǫ%O1`FCg<cY/UO|psCC+_ dCq_ XrܰQ3BtвHX\?G#&t @Vnh\9?/eVڊxI# ĭP+p1\ rG j&#C8B? Ƥ04p\.=@z ZZ3 )\ ݑNA+@PAtXAP:`,6t3C4HBЪ;@N;D.EA&@!L-@A5xv&ތ2 m@z5te ASӬ g?IP 2@WIMuzxLHP f~|D|X [tbņ)<04aUdy"/oPcqh|' DA” p``wྞZOq4`d@$<l,*hT U}gC H  ۢ!(zgB$0SX,< ((?HхHCs`4i*:h  //.X ʃ~͠PGL*LY?3/9Zޘ `0!8T(jx*P7Nh G@_>C<@%k0 !B@4Ҁm\vB m]xI h="jM@TN6 ?GCwrexHb#3hCցM HYH% 姅$tjRv45GD2łz ߣGB@oR HHʗc:RIJ`64Bj{D:(F4J5 _B pE?(z,*Kw0 i$<`-Q(C,{Q%OVhDQ'q iUeB*w8`Th.%Jp0Œ P!4>$KCL%K9% /Su(+@(ĉ,Ǥu]f_R!00!)kB1"s}~U$%SG`fEp]T! 2QPD i]! ( st·bax  (XUQxFdX&'@8ڎ8W0?Qz8im6߀`~3+*k@}1@ꖀ-YU 0\@O- aNMVVO?q0!C3n8dvHPB@/gWkŢ.V0BfT/!) )%M! -J +!NM8r˿[A*`!B3x ?JKpX勡AY0%9(2 P(_댗ITA` h` za/<>̲Q@qF !8[5M BQ| b|t|D\` )B!0Pz@* hZtRA*A\|. rJ3Hրd*aP2#E!@m+p`PN%E逃9, J݅$#MPD`-z0ZlWC iP[dNq,۾$Ć]rp)(PGM/{$/GkeZ940ǰPrhyBX)$R  53/Ƭ+܃+\+j@lRv˨` cb#E^~/BB A=@MCzTRBL" Rz&Q4hhMʀ@B4ԭ  jSF[0tڀhLIMq9AV| WP R_ c$c./G: Pa|!gƬ/A`!0u@-x 4GG% T( 2To2J$&(AL #B0%eIVGabSh"\9)@W JQ5LD#NĈ)AN $D4ªb^RZONB?%/$dQ!`1#MQB8KI1!KdB:$@ WG qix B $F] C@ b2\B,:A@"DHX0`:ub@ ;"`/KlyŮGAP9Qp##HдQO@jϿ 煀?PLd(¨oy'c( z@x_ 1GRX:הCm4!t}P%^ ^b飐@T]($H?XMxiQze kq5&4 Ax ?(0#*eFz V$ @z TA@{͠ZPڕUMbTi&] c 7JD"v._3PQX|LbP^ ! (CD4E?É]>i` '(Q y!@H (/*(KcT1~JUАVG5?ho-kVH& *=EWb zBPP(A@}Tb6{ϟ<T s!e vLB!AdSv= >!AWoI75 H] }~3ėpH |_y^~ Z-F\',v`~-Dzjjjj=A" i R  'B5 AR h/ @WahY!҄ä!GMZ)P D7.*tkP/dT[TtMWo@x@(}{L PP S".@חBUb؁fMh.<~Lm@!+2vXϞ@Pb9 [4My5anDЪZ/ (&J@,AVy(f~@Y*GNbqP &(eCt!(AJP  vJt$ hi]V"\\vciA4cA(}{/m$+(@:@$IA`}OE#+rHl_HEr]}q0dL젣C78@16<_PN@؛=0̋Z 7o`1r0 !X$h& eIJi |r#(4 H 2"G@\ 1anpOЏ<2 ebTA(:)4@Mb3@?D [" >,Fɘ9 @3 i*iD@Yji A]D 3`]KHR-5BBPiX)e8У7X*㙠J 2-t Ԭw#G YVO]J @<@AH<((?b֚mZE@[ĐďE T GeHH A1'Pm IE5.IMGZUxkPGF9+ د/x fuNfA*rjp1C/x/?;)(+=JC/Ь\Xw҄B/BADo2^$ w?#֣(!1CRrĄ"ECI iUQugu,XE⎠ˆYuU(LP4zE6t&wPt0 dA h3(^cд~>uiIBu{#9@Aiod ? 戧20@F_I0d@ O=y;&ɨ$@]"0E[6}Pr6RcV 1-O0 dh!P*vQv<ݚnv" ~\^ 8g/_StH(Dh5*`Jمjm+H"S@,eGC/A WMaST|_A a ]acf1]hDSu˯JpKx {ˉP助sԉ~Dt%D!$'ZNC҇ǂ~O;C~᳙Ġ&_; YFJ{anJo]ì' `0)d@>O |JIJ4I @ F%@B,&4Dgpy?F g W:_3W$Xr5[E +Kg f"#ȉ7btDG|;$( IBX &e5X4@6CUGqJRXaD$SD!SCc*F-:$`hЊZOF&FU΀fV/ϥ@j e-4BD+h (C?/!/Y :f |2]wPM]bu r^0sPW@h b„PHQ+Bhcs?fu~ %Y=[ crD4Q}4 npե6a0%BH80Ptp?+}pTxJpOc̿L"_ <dV #ڐAh$"A Thpł !m VbBhD pcb pAM8h7`fU TOhD9LjC3rhQzqܐڟ5L ,dR3|+fJw^Q n%c/ ޠ0 ,!,?|g09FWό*Z屧MOx 8)Fx̽M@P!(CdCd@1RC _HE P  p@v+4 ,eR WM:$i! t{_S2X.]6B $NP9NhC RCI%b!P PQh$J+P>ڽ~q?$S| ! aIF'2R$+<()@:hhd z@Q*hЇG; rJ/R+):گ/f`&E:`Vpj9 !Cޝ7ȯż̄ĀTnM3 ꋭ8|jT!$ݤ'H7-@R RX P1 XK4>a0 " A%o R}j+ aI t7)5U ir"O b!)9zU6zX !DgPni  I2qH"X?l@gAAVD%f1 `+VRg }j(%@j=4`cc4K %Ɓ :_QG0ߡ{ -yoAgPE?c@a a+T-< b d@x6/ЃA`һPa c)`DHH@<# TB@ |G2ETj;w_2ug@2b3H(%?e?JDBI :y ?(A;5&8D?9.8ApHք| "btjS…K@ $ rB8B 9 })p$Z(@ALAICh ECtTtTtTt![B?I :AR:0LPmΑ_ c/|@/ _P<顿~O~ Q;p1< A< U7<hDzt9ȁqIH)8WhOSCf<HmC+y(/ Ukm5P0&GWh3,QlT"?倕h_}aD.`34A$/PQh @r b_G%p +y_XIG %toٸx*5vjB@pD`h 8(ωM?TZpTopL^ޒߔB䓄3 {&/ wwBiDy |بmPbyϜ$ q YcE~Rz~ |B" d ¡'AH^\@xEZU"(TB6X/ACTpu8(Fht0| |FTw|Yji_.TTB?Z< <`,x/l\!T_qدQdNRTFkY!yJQj,!NUb?H4t"e.eW}޷&D S.?HL3`(\ dAr! LbA‰j @Jd}Q# 䔬u0PR;K;kZ@G)/JK&ULyAiᇅXH1:"*Ct h1$@ tT (XaHRS4D` `aF~R@a? 4@pha$Q j(`@A, &P di(p]@H)X6=K yêqQ 8z ~0a<45$+ d02 mr hEd?ǀv W]`*n>|.~׌Vp_'jqx p\~~>>E}Ogغ>**Д:2ʡ![z!F`AP$}C O!-$*?_Ŕ:44z G+ȍ `>ĮX@@<@Äkd:Qo< *C-7!ܠ !E__?|/(fB1_?s ? yH Z494$wG;Gq| !("R X"u@@HrgT1&ԓx@^{#RSNp[n4"=(輁$聴R a(Kr>%HJ> ')tkϵr!وp>KTv` D2cn  V"Te/P@C 6p"( *+WX & N j9_r@c r1]f( Aim=ʌ0KZMsI#)2X0F$а_00+h hZQ(J9h[łX!~h! ڱah6 Db+4ǻC:c[BD V~_@c@Z0)uc\RA#1K[XAQnc PJЁ Wl0#i἖,'+Y[T(a8(v Ѧ2!BIW%@f Ld+t3 *GB)H?>$ʬ| 0bB$W80h.쯂T<TA /,T W 40: pX0) ` !Aih D@QH8Mf=䌳t@HyPe!Uj)E҃Ok-,!yGQ):bpUW).GM#!ˬ Q8 @`P03E Q@i '?^цo6h 'i m .NM.-@qA`V~U$ AnkcYq0Pf ҆;@32F4RQ0HG݆%RCnxbqHEGYhK' F4d.AʄlX)I_eU?Kެ($N‘WdkuSv[խҖ) `nH ps\J(@B^V LW ;+$Z4kуqBs-1g<<DJPP?mPo@$@_BɁFBB +gFi,4:q1 'QUPnkvG q<=A6_`~^^|~#ENR=FbBL!; uo֗F՞",p P P"J"*ޛ@nF29X%:t#D^D^^A tBQ ,yy QE LЄA=L `A`["9@4Eh.У@Yh["3T"2Ƶ1!j ,$ - T)JP@ǫ ~&AJn4D/yI59L=Qi,6 ])AG]k\v&ZKHŬZi:a@0bq̕ Y@D~m,񲰇d#:4f \&nb֢ Lfs yo` >Y*$a@*q@u/tcBseTM\⭞<,$,z5 L)H$PO'οGu*S2ԣwҍ$!!!3F*ADrXʑA8 j}Ea\1o%w%^I+4H+ )D1P X#TP ŢtRE Ԉy5_䍵C`~Q*!*Z!E,@/%(@ 0q$#a,5P)!HB4ZcR9 zU 0$Z0IB"0hPqA  ^H^x| DNA(D ag$GhB4-A-D%Agdb/\|Wgl uJPft0w]$$ <$"$Scc\=E9T Zr?EGtVF*Z'}ldbm/9)xX) h|3c,i^E8q0w/%qHnr  8HA%8tHH : $Jey 5ܑ:$r%&0 \5" %)J@+4 `#4   ]2PU?PP@@u@A)H?K""/Вߐcc )P! YZky$T\ZsAHZ{9BRU~A J%}U-!A!E$[$|e 8 ؃QXT,s^TDUI1y3U 4dxRio` ^(@v Dq(fV(z0z3AKJ "UPlw͂diTAƖux g ! ؞DJ)^bĈ;,A **]#Qwf-BOa;C?-D#H8f i tp[1 cA(t@lĔ}0x]_E qS:q0Lʂ|](VjDjbSg+_0ѩ]U G_FyPX"7> <АC# ' -H T2Lw +j']6~L1h2Pm Iy$"ĉu(+Ӈ 7GV"eGP$VPނS?~r*2M07Jw|€.P/1 pSxlR~G`2Q ?4 NDG+ĸtX|Mj.4Pb iJ5D$?BKoRg)oU?ub~~ȓLQ=p+ '`9Z5NJ5`TAJ=P+d+g5*%r"p?-H$3¨eAQJpx萐j`ğ((AvhJW7t c*2 z yF"HU][.E1 h@A;& Γ'#^{C#GFp ZJEl0 !r!`|/ A.8!8?"ъD C6[H ET? M_JT !HQRNHhDZP!AB(*TV4b !A*UEE]%^_Y0b!Siv5H|yPyHeb㧤ˏN & ]j+@]4#Ü -X<P`xg *W8$8T"#4wR0M 3,HcD\4QiUtY)h%SH%O &A޸2M!˃T+׃KB*eT@zFu@4$JUQXR @ p6ǟhXhPT)2$V!&$M(H}:DS?ćSHG IC|P,`#tEy@?NzSU`A?D) 䑰`?;aܖ,HB c"5xMKP[J'P$o˧X/cq@>XWCCdC"c } MHSĠ"jm h Ȭ ?xI- ??qƏ%^b -w/P o|$z\4bhc7gפ`8]=PW{)!& MFV_P &T= ?Ӗ+ g![R8j֓Pb< U` yx T@bp +};%pP$A o"f.lQd`9 8_o\po+}4Ną Z0Jk |b2o:@ _A~zăX>oWc)b eq`7 |pF81}}pv/$]ؚFr`ў.(a-,ԱO]3.3JfT3P+@ e0(T`bAP-;'zT.P>( 'IV#t<"%84(UPd/"B hR'DM Ly8p ((@ B{hG00<HeS}`2]ޔzG:ێ#}Lց첆=O90cP` ~~nn`xB=^ @,Eڀy pM TbU "Q2>7@Q!=HO"QJ]h%@r>A.o0:E`GEi='0߰sIsAFĂ $THA# lB~BRsU.O\?#BlSo!E\n0ʨ$-ä>)K3 4߃ĉ(D@R~ J@d6._%j(ĄOcHV5b]& CztPA@/?.HrZ. =(SF%E pEԀSB  A0& +? ?TЄ} ~|ABj0(D``ChH>'wv* 腗=pQW0 4a5,k&@-%̒ z]\! !u!u C~f0 R|XHg8gyQf\1 74A(! Q9R͏)( !Hm?MB֏j(, )H00^pg!&MQU(3A@A "fY]L!@@C P-]Vc4ajhmb Pz |€~@~r3 A+_A0 c"'m60m?\ PVAZ5hH1Ԩ1H4EHnXyDubL 2"7} !VzEb.e?<`(4?'T` 0h l 戟x/J/P(1@gHQ~{ A} @?&%&RT@qyA0@Y ($=a$D&w\m7a @Vo`?2P%䟞 Z Z:hZ!P+RDP!(RvY{d!#|v@,|q׉Gm $-ᓚ(1 daZNP:%ZX0iX< ~"PBӶx0[߂ݤy`kԿL@xpĢ G؆)X(d}lI(Vn$Hc6^ H0BP3poդq@y7!Hxڜt#?M>ChQ FF#?pXR njUoKǔ *DyF2Ut9q Q-4vA!"IqN`'U($(-VT!j%lkXx҃ sI)PGQH:šj X($TeIƁPwI( t|+VPHѡPF$#l'&R<@3 dX"uH4E~*ZM ǧ0ǖJ>@f\+U"|Q(GT'&Čt]Ո6WRSQ%4B CclQvGJ#sF\)#&՗jb$P)pL$JFRZnsN`Q?*sM>J.(@5:ER;H1TG# 3̊C(aHŌY;x-eUwC)+,H@Q4H H(>MW% jR4? ~ .$-5 Z֋a8V8Db$eVH~--5bd"l9 6D+T~[s3$Wb(d<Z1Yta.#capL7Ph0$'ؤ:8<~U3U R̢Ygh !9Yn5ͷҫ,fRI:rYbd7L3Ùd1@>IH&TKkp+X^B4ǒyr AHf RKJ$ /pF LBXdBC! aAtf#3k@1{B1W% i J*J A%4E0,Ƭ ZX_n\Dd9I Ҽ=FM#V!VǞ(j>n< l@t$ 0f4Ӝ-DGA0(2wJGXmEm?G+V?VKlfN ͢#W^RHQګc6N ;8c hB޶59Q.3U:!KSfHb,wsdQ`7HT  BAG9UN k$84 4eyN9NH2:I`HX u4`0*Rh ρH JFn2 `*1CP%E&K)8J@GAzAP! QP\r B)Œ1$Xr޴;L(# PRJ(LI!p$A#`Y  4Zu\"Q(`v,J v %,Db#řGдO:we]D6gJ`.jB]d0Rh3y٥aPp/B Gp% @bE oQ@M 02 sWq:3aD$0xhhJEHҴ)fO¨cD)HA(-,&ދ٭W  .КIG53D~LDu@?hL(Q4]HdA8=I@\/z 4PF8E'[% %BFN)^X,d0YB!B䔎!D%" yPVa;k F#PHXdR%Ad ]npztZ(q߅d[P%pC W! DZeߢ^\`+:-pZ =b (AH R?`xxr( jli-WI"O=H@' AB*t+5(@b<Qlf) *@IL:~VvmDLu ]r[Ksi!?A%ՈWE )Z8PI@T hpǔw(A`/p7|<& Hbc^p?Q&ŀwZ@L%+@9F>V)@BB+tZu,< vS bA !NLihr0̕JXL"p'd}p/PB ^FNERq?N!0|}nҠ)S%UMF BK$h\ J~-S53Tt-(bH=V0<2.I ZY `FHݠ@PhHѠc8Ɨ ;nH%:+(qP\1aOc>j1  8!~m,b?X4AX.P qw>d NFHk“֗:F@B( *@A"!0|2 ]kCDX#Z$S)\u)\vᐛ "]%]AP@" NJbMXe0H@]=6V{G k&xMK<iw;@ ňG@ xBXZi飬Z@Ahk96eЏSp`X JȤ-ՑuT^Cp(EbGÞ3jj] aUuQUϓYPJ?*z_ td eՐPzqAe} *Q\. 20(߫ "TKv  *J ($ӏ#JG XLAt`Q $d@dP$]Y{b*+S R"AU % |A4 FPUCPz#(#H85JtԆEr 1Y 5#Hh$t6q @9 D`j 56AF <Gȇ&hh2)=^XA&6wnb I@fɲ 7cɆ:>Rʪ]PA.H4G@$SP ^G4<0Jt>ե Ehu0)KG#uw =^@iÕ Js4f'PR(&3CjG(@m Hb@h $&.u߲:w[q*Ii p{(%sIK(X%)+N"L8)A0u4KbO<%}7D5kM.Ti|zhhP[$AW$dzFW@ @/ u9huDLI%m9&C2(>PE$B- @IA'AA88Z G X5w[NlrH8^]-hMbYlx,8ԡ將~Xh|0-]u)N0 8i ʳ/1@w2J~FKBp"Ad_>? #ց i?0d#VD[QL ̟cbD@bk|] 0$Hm+D%d p\d2DP z?X(H(WđLE`4$=^0XE; $(ק\Wp($!%4 ^Aatu iB> qhy Wp9J.1djє0?ç<1H+2c̟l* )_he9L{QBGP J~z DVP" G$C /o*'fF EHʂ5:{'s~~ DbQ020`?p{?? @h" n>`.˨\pH 6ew \J` Ӻ< .H~e67Wm V_y  lGlXb P/!@L 7l]G؏<@'uS4|$V(wH`݁ZGiK4 ; AMnaӜBiA _>!LP ԁU"c [A Hp hX+I`N *Zj@`!$RHE*|n!!!!!AP |u!Du3GС䢄PNԚA!QG)T K/@`!8~@aA!##$ҧOX%|!BO-aB> Cn)i]AoF5+: E dYK]A۠3=yD@??@vHTBQ d(@̍A)`'P#'H";~ (B 0#˒@6 Q@/P (0# MqtW`v4201$-Dhe RK"  :j5 ʿ a:T@#x4 hBz`Y96T@Bh#{"taY{Q.Ol$}XVT3`@?/qbp 4.Aۈ@e8)"" !t]Oq}O\}O]>q]>t2!cQΏt>ϫZKGj-LIPU(atT,Bp^0PzRJ?m|#'ÿ#삌_t(nף*(7@L0* K 'ж`d5qgP1b q_(S9: 9+?}X\B&ք(w뮁 vz@E5/4_@^p 7,I3lf% X@"2cZ bC%^gL% *}J@r jϧ01^0`Ele K BB C - CPl=GSC!aJ| `=QК97H N>7F0UP0pQ P rXa(Bf^֪ bŌ!2ZbE-$QTUVbO$VP%/Le촐zPɪ)PIhrF@S? F.$@éCU(G8TU_TِTbk.GIY.ӄՔ.F!1<0]7w bx9K5GfbrPvXYD=}j1z8YwKgjV0 $S]ACJ kup(cB3hh+zH /P#Uw20!$BneDhTA6hL" x+"f q{m $)r#EB<0@?S13D5`Tyas g1g--j!``Ҡ]:cP_?HIC?&B%֛}X"ZAÔ@Gt Dxi]1/p`1XIa@ E Hf=6@lB>qh`$0V|4HD:  (` 5A; ?!$PT y)[ (J6MP UHv5q`AhiPIހR ! + ieىQWe(P*ga\'&@d@MÜKCU-TՑX_=@?]V&0Ć `[Nď#" 5_XQD(5 (!A RuBsbXD"@ѣNj;4 RP]L)jZfX@@.[s^'_[`ar1kӶUj `#A !!$ $kGU*; XPaKAQ@Q E[Dfi_A 4Qy).3G`Z=E>刯 یTC5M G ZfMF:b 61bz~^jZMNUdTn KL\ LBзOF+w|?  %8 Hcw"8=a,DiABtl#p0?*I"H$EGD]^ I@Z11|b*e  tIQX aqf5B+xiLʨB$ae[P(!E;L<h J.P d(I*n$#!=Vf F:(k>F^Yk/2G0JQ;6 px(qu1WvېLg }CHEPa h ^"e1Uˡ `< V rhJapdu F 8uL HQ n|0† XhELY((@E#^,){YIdlf#6DJu%O!v'0us($qI7Z+(,)t.5`eQIDRg`-YjGN1)e $B @b-p{c~XZ>]5h:(4hŅ>mV {ya/(B%uU91EAL} 8#mPAy JߒJ6k*c i'NrqPd870NP @R 'z @Qj>b)%j UUCA)ЂP|_#P\̡a_,(HUxR  b7CC){h|,DݬL29{2'j٤GhVqϙ1X:$DǞO&χhO5r J[ֶJՁdWZC Ԡ(A_5`M5euI) Av_d)nuĀId]ӝ!J־X Q? j3M^ZXa(׎FB|K(jE Eo@B gI(m855^`IEz $hR D(V@kP S[Al-N!AKWఀֱP Z:U$kG1t0HH(-AHG w9="R0"$ i|%/b̐yeڒLOYP.t+"@JeuԪt a9Zk@B(^!TS>cg ֧xotՈ3 d` Ad,]! `,J>zv $Ah$XP] )EUƑ^qJ)H$ j RZ(, 8Neb(`UJAX 5iAU02\-AW&!LA ܫ*2=lf ,; \r0@A-pИr( / \$E@DD* Wd0@_rO/H{&?6{Z]Yb_D6i`uzWBFs8QAkg&c@uŰ:\k|pd.p@,s& %8Pk8P^qk ƻL"jOI)G+e'RDdd %pEw#`\K w WЊZwr+jQ*(-HU\QF9; @e 8@5A4P4Ca~аΩS/!>!qq02F'GN["26* URv?odp/n @H?S| N+}֐PS HPb?\Ő`(0?V|Ak˧O]zhHs r=  `"zT"**@`F "B@9PPRhR&H4q&+P ;!p8 OB3@ZX#E{uN :DB&R؟ٍKWסiE>IxZA음8 ;%+-Œ PcN50_cΗF $> 5J@R\H"$#Ae L7xC Jrd+DZwWц;n`Ù@1qSeIcIz)pfD Ї3i(ipR5^?%C)>5fȓY'q"k[zu% +5dVUBXu(U!qQ-P. };#w )D]f3h1צ $,Bi. jJ`)+ #<]ՠ,PIz(R DJVP"3@YY8)Ƽ),4@&sGY^9Ha #SwfuB+VqP#xB&Df0ʘA !t]O]>t.ϒ>}"*>]HK$l6uh4CjZ@B ac6Sh"""h==dBޠi_+HxDCED!PC¤,m@Q*dY ӧXSp)Iv?P e0)@ .0t`!(hU@ "π0 CopЂ a8)#ـ"Z@Hx?6l rR (X@XM|c>$@SP{BP^h-!D 1T4`S؄C˩=ѻ! H˄m;6  SCc !cj?Lz@ Z+ ʰ$_␼~/| R) *[6_f(?F47$@_GBh= 2Ct#GrAbl /pH xڋ1g?@{@h' 1A> =1-K3f̤= fGʨaN3bȤZ R1  ug2*8fi@"AUDP%(YuYeRiCY %b8Jj'3bV+Fi`hh1O&@xޓ``&U_d(cZ]2[lGh ,IBH*'?C%P[L_Cp~,­siD U)"-P-PE\Q4,D5~AtIq󡨄@QH(jRdEPXB> O␀I@h&y"D$ A$MDHk!1(Y];W ?gC" P]u]NeS@H 4@ 0@VA-bE)ARM"d 0XMt&*I eIlݓm MF?誂Yt>5nLR=;~ ?HC|hC@)eCCrzלPl)Aek2DZXT#CXM4Ҫ3:  sWPs[6@-䚇+D H(Q%$V RB>c R-GBDH[hd$Y,  Jʰ"=FŊR`F@sj0SAa1JVsVN~Rl"^CBT/&+jmx‹5Xd bYJgpzy6N`QeLrI#k`9J9ZG14"<5h fELb%we09S0 Kz=$;D~hϏ" RB|Z>?up/ H!=XF0Z#`|T +ZIXvhJ&gJV*%ҏBS|0vQSGs+95!9S5򺔝 ZD+ȇ+BBfs4QF *BBjD(@% %~`A(k'LHK!F4u_ )--)HaX:jRl-YcB*(ᒞZc5+ Aqazoढao,X8Eהc>Zpj5qS?]AEECLB>IKeg7N_ RXiV#) qx0B!yn5ct!1BVRu aT^ R?TMPi@1@D: ,];Ci٨'qIw+ Mُ&08y,܄ӅB(UJfDQ @P!ThQw&hrkn7?q@d0l 'c]PDx ʑ"Z+K" Q?@*D d^[ ],2$S"%|<=5,4<p.AbA3PJ'G ]ˆ]AQA@Ԍj?46uJ5Q͊RDbfT.@'iu7rzX;FJ=$ ;&Z}g5)KcE',D)g: ,FLpǍMV 9ݱ*u>I!QRa@ pǏe2Rh}.OȊ0`QF(8H8 :@D$HhY( ZRZRA`6I4 <"D5T.EJ 46hQ xbxl@ itx@UruJėI4Uy//렀Sl=,ƾjj xAZ!)h HiBAbGf!xH}A Ti$,.D6|lAra  "$ ! Q BE)@P) -%JoPcZȻNE;-r2u@G+5֪GOdcC;BD1`uB0%[R!1ILE1""0B[ uw]R8Ph7?XQ(@mr2rtVH XCsA :D^ @]zl ͇L46c$5D, &gypf@0z=F[ MEEg-EMtRܰI2FI6D<_  \xJW;²hBj3L5aaez+XPyԁH5V?o 7 4*?QbWm(TQ(XkwX8&ϠQ,ZIa(AQBĖ#A(D"*ډFȅєEIXor"a_<"XZLjLD=5ϥ$<`hP& Td@" ACj *Mh<̫8&3d)P)lDZ #H@!^R^704J)C( xzC`R# !CdFB>J8og!tS9,`P `/MXB@KA@ᓦ*H4?Z&sfmkGgH Vd\NuHd78c 3׌ Vprq0zT$CiPZ@ƚ%^kDXl.hFS09c&y ,$ h9= D8 yX7*$%sAAO{ ?7R0 7y%/ s2x,R2p pႊ,q*@Asbl/)Ļ*0ZA@ʊXg] AfX`"e"6-TqHnc6%1PV5aHѱ37Mȧ'ar9(pHD؍g`[Su \9~h*"-DHOX"7;^s]#*BcLut}$'Z糡UȰ]Pxq#!Z9H fSuVIӎ4*`~ P|< 1@3.(a$. !Q H\ؠB@#!;#8Ve RJ;'A@LW!i$.;`XFBkT́ A@P  h ݁THh`qPz Hh* J]_ i: Z%BJq X%L @PhFDH 25ˑ4 S)n|W}%#" 0DO F*BXgkc )eΞaYT~(4=C6Ҥ 6aa &ia @݅P@"ADS;3gq#lYY>9e"ClTY^T'~R`Sl+GqDԄ0#9Lu! }lwS:(UF-9SΑ"!JX ́NJ(0rd:Az|@vH)@=>DhTT jAZ $Ib4$R(ERP쁖!/ Џ] &A.pZ8@j\%h(QH B OKBJ]`rתsiȹnhbY+k#-T[Hn -oR sX%N0cps/pA[:.CΦ) 5A4By/tT#R"#H i [}UGFZ =HD d`L6Zx@uѱK{BB[b/" Hi?D6)GEDZu"-/d %73mXjs&' B2158ʺObi A0DAZ HM@3 MˆO& 'I-M|P]((. -QyP~ʐ{duo)W(]y-:\ S @{]:h8ŚaPo6X&^C DqJ @QK?0FE5÷Yda +[\B4/d_[C "^:(-lie,gB !^aJ^}SZ !K A! j{U0^2J<>6) HJ 5'T QE`*uaBCWQ/ُ^LjT F5!;E{թۦ8eZ-( Aa8- /I\֔$-IRBDc8Ԁ X D -F0(N-ߧ, H% q󐬵/C@GR螺[#&V<ȰN(iq)^$D~FZs7pm{֊iAPS_ϢJ=sv08lԩVW=;[@+j!҇5y-?"C6=pj)ȟ,A`'D^ (@d' > @4*Et:H G$ ) tX(Y@>PA 㭪#P+!c#!YlA; EQ" V9" S DiXV ]-9Y'v9Ҷy @.??y,giBN/a!v6ykv_Yt+J!AsX>緷D_KЙ= ;6((Js7QP8('h'*BT;@ >Oi/`d(A[H&@jT p8}Q"FV.ATphѸGȢA=Z(Q%%o`*BjU(hg=ri]jJE-鄿MCK6f :Җ"鯮L}'_$+KR"D3HkUE ))"0Ml!׃2%5h >ʝ @ R|˫]_RWк>'*C*"aі~ OdDd PX Ӳ0(p\ȁcS!TC$C >(l@٠_Qf|?PM/I:dS@l&X7<@1 *$DF Cy񃼐)H# SN0mg4B U a4ڵH !;Y!e ext9J+ a$ia@ SV:"Ҵq, ?,kCp w|*8|}AWHGaXB2P 0.8wd≮ Æd`7 "+0=@Wڼ*x t]O]>t\|.w "bKPA!#}0LxAV E. h{} &J*֯;$- *C -/Bi$-ԑG^C5 ]BHJh}yWW7g'  "!@_|"㲝<$Bc8`[Є @d$V(   x^~/?yp( >^`+O~$tz ԯuw$p^hd 5J5kCckM }c@n!`A(+2@q%8%,9*:r1  x85ƈj吃Ԍꈈ ʼ!@ :uPH8E(Ѡ#J hs$j J@U #I.!S,@U:E F(RُsBU J)A%jdV 0kDiAhpտAJ8tE y)(Xr6Bq o+I( 2T=R3\6eP~yqzFBҗ(a@VS[ e G yT*-,ʢq0Ck @xz(Ty=7Kq(żqrDNJ<8?,XT HNg,A_$%))x|;ɢUuņ/ ,~_Lqe9NJ/6`]]&a2uyw&SPVp:?:#Cx0)7kS&3%L;ȚJjVK %~ F%.(D3 D2MFX {뀑fM`BP@|xrkF!J\Aף DKaD " Pk+_)ZIkf=DHY((ҀgB}0Sx4"$[!Jd`͚XHɨ?RX1erL܆>[8O$s =%PuN;Z!|IW"JD Q & Ei#1ŨA}85ƽ2}OB 0[BQ55/6%*#+b?[oKNvܒe̘LXEDJJ9fV$iKPCPq^̸]F1Ԏ&H26bIc"&v?nh]< 3U"S !LKF`W 8 YE!v(3|=!nSWX:8QӘb=* \_-! K.$#򀑹i N/$ LUP^AG e*7uI\UH `d GY?nY6 _"O Sr7-4$8r@}7<++zOoq=RAJ)2qj0#Nh|%DOjkl_릔)D Nh mBg׸ on" +ڮ't5$rBU2a"% %D%M8BH.(B( c"΄iD1GX;V29 YǰK FS6l%(`Z*@R h$n dP(%AG}Z["΍++>1<ZS l2ȨXj5Be D"I2P*g`?ҦwԥyiK9F;hӵφdưʀ 151WQԹG XO(M!9s,6g-Ṁi#=u 8PZ=vw 4S+PZd ARp{bEb@yAO0 f- .Vk_;BP⩤L&%1Cb╥zA 'dr"dBD&5, dykQU4!XG跞%` )ڮ?${ʲ GDT5{Y]q4UIyBt?- 'Pei9ͤ=,0/!D =-SC@sLƧO8xE)5N gUeRvRJ&Y BkUvL%X6i2[*c@vœEhRD k2 JV( Y vXw7 rXkEνgw(Z@^-9NT`y$7%@ƽ징H:vGg6{x.b6А1E+'s݉ڴg3(HP2 }"F*O΃}-~'YMŤ@YI&捵/"7nMb{ojq*.ouO`H'm !kx^)u`b HDf>hȑ qjÎ`4i (z,^F QGp< 1(DaRs(B 1tRC(&i곔f<,R.Ҏ%(J2Q)8 тb@U@!DHt4\q]FVhӎ$aCF"3VWbR +-Pp+(d rbƙE`DJ.XhxX)|&(Cy#tCv VṐ WhB,b+bW^EԐyG#T# 9V>% ""7P B!H?_g7y֯m)ZZ\bToW?G>kRDt 9? `KxD!-Bsk;4c 8<2AFޅҡ+%Z\kE#G*́w4;$BuC1.v]iBX,$NJ) yesy\NRzQ3# F^_;=M!9ET7_{8B 5('-G?ٹXb`B\ HP@J008$@"D(FxAձ ()ёAM0$A3dVgX èbhM#U =.jO"d,:lCKuF3KGByLd@Ѽ;՚AhXc;LT\)JW z_ ! xBjDEdP`]l P"jsh,1)R3hr?/T&/)jΪïj'!#Y% RYNEE kLr)$(> LJ0i 0XC\Œc q:+IpAi԰.+"C r9 a -J)@:Ji+_Ԥ4. lb}T~n"+  U);lZʩCB# HD=%|yi5L[BnYw%>Ք+(;JuJǨ,STa)l3աt\^&|J9^/Z8uE,<ߘ9Qf`rk^8#&cG1cƤ`x`"a P-J%`,CRkY'l.cN5!#b$%XY%01 ?_ud-B@zd rCSA.zDOjQX[% =?ޟ9"Y`a_`YQ XLW_aGO@1J+!Mڦ@gC !/ cKSX1~lx 2^f<%7(|~#rXMI0$+bGĠ${C$H {M$: <-v Bp \RP-aNPeFyZ#T-29N(Dž'C((axtI@8C *eL8\_LG%͆ A4`M@$Ght e=4, PmTjP@,py( RcE2x,@t!X7 (JJRF%[t0A K~Ψ0onH}P$`)VF<(TYڇG Şrb?{ < ڥKQ##$`R'8M\jAfP jCF~9CD m)iR/C ?fSh0r^<8$q#Z-[F""&?H~cP: 9*C)܏ޅp:aXGV9MX19ҟ!;pOSeX 4D 1!RkS9*UDԇGOw-g(~4pΫ6YЄHB(b:%G40+fC R Bb,HH!I=??w AS|7++QQ\Sa&0/lf([jKpJ%A֋2]"8pKvCA4P JvЩP4q(c p R EH)((D&DX:KD`hR.]A@Mt=m!Vn4P D T"q*%S4 '$I1 X0+VfR40Ph(B32?/#Dgc G_兣#y"E`C5vjb< S)Tj$RM)+YG0B!huе|$jhB}.L"Z@*@AhWil $غ@-I >RX: ',| {ǔaĤ}cp?XD7[. |1`BDRoi@8+D9E) )UI3$02DcZitEFkAd% @$s$+av!ND&!@S F$(x;6 KPR)@hM,ku[_1߼@ƶ0 ?s K؂F>#HJ}#4 At <`F,`?`EÈ"( p04ЛQ*;L" vL,XƂfX<0A66! xT7Hb7~/_[,(20% HWȊ8/b"x"tUQT@a$tˡ⇩ *+ZGcL0GMQPcp&)32Bt xQ z- # //M}r"y<@B)D@F5$ZE@jMGV\VIΟ?ۆIEU,`$ X-4 hQAv@\Y  a(REWZk8c+g$s[γ]GkHt|_dY,KgM %H4 +%ԏ4 ŔUvsZfI!QeE9sآI@Eh)Vћ*$@B$HB @d0%E.@mEQdĶۼ$(q(EEoj @B+Fl' 6vC8kA֨*Pb -E( G ڽl k[ӧNR`/@Y*?#3@P 8B11H)<BXT%"bKk(?~qa@D@BSbMIXٖ-l0cXր:L~od& F= SJKQMo1X̠4 TCh 1G磩b JWB(6PqA5_Tr"IE%in_ky#Q EB? ;nD4+˸1RT;DRJU@{*1&=,D!Dyybŋ| }JS BQ;@ R F|xA @@dܷHeJ3ID&<VgQ"'Aoy\!lF!ʊ$b]Ӿ4hXF0k@UE)X dRs 8Q5$BQoCc(I:@g"$DӑArI$u@%(P"fXIHKU1v< ,aHiD3Xb (PB (PBH (]`U#:*(,k FRQDbX (/>!KRq:cN @CӒa O q ~6/z'%D"E2GA0LFdNǗвKyh 8in.QDD>Ѹp3fP$9X  rhEV؂ W0;1&VdJ50U~,X(@i^g43H=0NL2R 6xx=(CHam@/4=4M:݀9P) 0pK\|抚xM4.SXL"DCCIAhh,EG,jUBV-"aQhkQ8!PІQ~@Pݗ^t~@| '!&N Eg0PLO8Ǐ4Rԧ#4H4eK f`$0!9xkJ*-rb%bV UBQ[bx #-"T*!(If'`.;Ta^~QÆ.W$q0#1%/3@MO=JW2s=J^Re+)tT |'k`lD@fN`ِR96]B~$%+Io]UHOq^a*af7"ƌ.Ax#QxGۉPlH TBVd4amC-pٔ9$QS)LDTx4Bm*1F360")*S($AΤeLLnNyLhC+v/LπD$HN N"yReL`H$ dH8`j\pU3G%@1fHÚf(nhglQ1mE;ĿADX0hFP(*Li' yybCɈt2U,h $•](gZsj!WV$0yyb.B!bu !$9ӎO&*rg9 :4/,XC (U-IL]d)UG2LuZ 1\3 F 0^MA(dRF\C`JB*2~K.GƬd$MwJqǀ"D$h+KYHTL dND0 k"T!^BIZg9xT MSI$M5ؠ(RA)2\;4hG*\$yk5fK8Nt )DaF 5X+:@[oxZJJ$1)x("d;>K@>}}}Wi,KRj.}hPʴ?CA (ZT H `$R J!Eaak*<r-WKV W,`+T8.JG5]ZtR. +p iF(fzпJG{` ?pppE*& H7EӧS8.M$IxC"*"B (߈W,`Wźv#5▇BuJ# J5`%8l&f }ItD$B DBPl#eKAH,2a&* 2^-yxYn#UO2yЬD# HN/?0i4P +B"DM9_`iNV*u&Krr±¾4(@6R N UW@k~*FrBeѬWJ%Ē8- 2{H&IҌ'y!!+1P,?,D9āT)bB!@ $$b5f0#^z8#ɖ}  Ãh&!W"Y(P#Ϲ;7̟}IC'E SrA>($ qdJ*DTN ԓ&8A2(ωY \rsQoGqFV3A|NHCq % 5 I/,XC(Yr<R-h%A\k^RӕQ#g9f5T+j1"&|2bHyiq<^Xb1B BHq W@(- B!)Hו7!]U)IjE?  `t#N,ML%Bdhqi^ƞ40(%HR_T!ge7gbO{~Q ][ KkXGmY, XA&dl;d@0hWEdPAgb P:#>ÇT@HR0  ,PJH(z!TJrBe ҈fb vC1Y_XbUVIb1CT@!A(S3Z$E&O h@IJWM)&2gZ~&_EmCȭ> H z) 㦴-qO8P$V;9Ȝ f&t qFlֵۃLBCʤ3b؝HժiB1Lt)HqJA ]0fP)ֽ\KgM~6N)RE8tp8o Z|JT:Z!./iWߚ6Ԕ2(' NN@jRBl6ѓ L(H%$ WV$?'V^T ֙z)xTMy**txS!#dRp+(-2?|Ϲ>HG"1d&@)p SFZsUlVTi+߳Z |fFv+ԓyXO*ENJ9-D0lEHɴJ9ӬAX  ,@R@EAǔ_#K95Ǘ % MjcU8a:;@@9 p7 x~)Eށ  " !PU Z|$Rym!jIt@HJr-]zF@ *D C KOh%B%!]V0}$      y!y!8H (c!(6!QP@ !ffwʨ\ :Gc W,"Lq‡}͘@)rv@"#rBnX# һ=R 0#@GWČ|"Aflw݌](&ˌ,0< AH' }ضť-!I HRBd"@? x% J'Q-"RǤyN@X8"`6#ȌQ)gZnߨ 'շ`ހ<bHH)MlZbӖ(1A Pa/BL# BEACB *A9#+an)JqL_3`E8p u? ;RbSWb 1)9?ѯCs?9@ Vh4%+]c<7* @_~WԳÌʹSj 2)TR! /|#؁)ڭ Kӎ Nָܲ F0EM} %$q.B &{I%)Bkh&@l8q @([ b.~ -p3sAgh,õjɾ60:āw&4(Wd6  '`!ߥ ~RS2]_e lؙfqfAL5"d.0lP!;|`(4Av6d2}~i."I UL^(1&4~$PldqD$ ^Xb (PBPg %@ "z@!C=e/,. ( QUc00r|ہB9 } 4(@ BbĠ@0GHE.a0(HҀ`!_Nɀ?$r?ƸH$ FnP,& 8SXzPUE:S" @G6:y$b};\Od S$04 .DğLQxg](uҫ8M|Q| F| r9Ss GRه\ 9At16!-'N-ZuKBM%zb5=OenPJwdn@$, ##)6P1x``%= A6z>> 8]) d%ĈH O DDc1cŀ@/PS A C8%!bI9B-b+G~H<<b<*9dUHKx'0?HΟ< c0L@<{E:tӃN,Yaybҝ`;wN|%-C#VOZax= $744T l%ή 1OkC\R~t?VEB4$KV5Ba:<~(P+{MT_'I/ 5ƔǨl1y@q/| +`@-l7@`30f14)M HRB$(R'& $q#A 2%-^p(rHF F^d@CAD:Pq)q##?@ N? *T4hB)JU*JZ *B\+/P  0`K $@$HZ #(1$J@"@hF:8Ҭ,dɜ"G!> Ҍ&@r@=^:Og>Jg%Q@"pd'N 82pd  (^> >@BUY+ @^Xb (P(t Tu]u R:5#R8@ @^X|rH_aF`yyߍ5F6qD0e!m44Qs 0BÏpgh$Hq$< >DAlQ?el082E:P %@@@/ =HB#YB1cŀ:Jb_~s((QE*sXp (x!G3╬i]1 $0'$"Ea&pm1Ճ檼Ahc{ '|00@0"AE@>qk`)lZ`>Z(&"?@ ,KoPj}IEQ) S@̇6@L`Ro8P:0iJJҘęZh@@=`3 d~ |Ц4)!I HRB ,~$ G A"[NP BtJ d;ZB2(0 [а XH'؀9o6 )\_ $nnocc Pb(1A Pa DD$$J1.UB " -`$1@Af D0FtUE_\gt?Kflp JU[U2bC8x@ѕ쁀*ɛ+Lg՚#sqx@iʠ5Y?e@ CM@snJ/dW8rrrT4iP΂)JRJ- X1Z*mh$`i0*_307O w9ȌLh} ha c_dI&wpg/1{w(,dɜfaɃ0SCTp )XYU9@ "Y'Fhg+Wu3R K$oaHW2)-lV "fFR`: OPGN4ǦUlz)ߴC@3ޖz}@:ehJU1c1`vъBzjFrs h?@G 3<  u#)G ΛNSnucCUi:];̀ ` ( <qZR3 aOЦ$)!I HRBP'p'8NOc(1A Pb6l`++aXVW9BS)0) R)JRK@E0a !C|o2ɖLddtYg,L@B>7(l F;f~(PK`qZR3 aOЦ$)!I HRBP'p'8NOc(1A Pb6l`++aXVW9BS)0) R)JRK@E0a !C|o2ɖLddtYg,L@B>7(l F;f~(PK`qZR3 aOЦ$)!I HRBP'p'8NOc(1A Pb6l`++aXVW9BS)0) R)JRK@E0a !C|o2ɖLddtYg,L@B>7(l F;f~(PK`qZR3 aOЦ$)!I HRBP'p'8NOc(1A Pb6l`++aXVW9BS)0) R)JRK@E0a !C|o2ɖLddtYg,L@B>7(l F;f~(PK`qZR3 aOЦ$)!I HRBP'p'8NOc(1A Pb6l`++aXVW9BS)0) R)JRK@E0a !C|o2ɖLddtYg,L@B>7(l F;f~(PK`qZR3 aOЦ$)!I HRBP'p'8NOc(1A Pb6l`++aXVW9BS)0) R)JRK@E0a !C|o2ɖLddtYg,L@B>7(l F;f~(PK`q ZR3 aOЦ$)!I HRBP'p'8NOc(1A Pb6l`++aXVW9BS)0) R)JRK@E0a !C|o2ɖLddtYg,L@B>7(l F;f~(PK`q ZR3 aOЦ$)!I HRBP'p'8NOc(1A Pb6l`++aXVW9BS)0) R)JRK@E0a !C|o2ɖLddtYg,L@B>7(l F;f~(PK`ʬ `\3 aOЦ%)1iLZ `'p'8NOc(1A NbbC>'>^ 0s+ b·9ik0)S bOiiiDɝ)JRU*lB<ct@M>'2ɚLd` Űb8Q)$T8@q` L@B>7(l F;f~(PiC#\B?D of;M}>t@].A | '8RA0FB+FJg9r#Ȍg"1H07 `F#o"k`g)IK2TR42Y U@ ~b^r Ą  ; w20b@ x`\.> q\| ud=G=^a,((FL+:%:Dt(]agf(? D@-l$#H`p^/?y^~(  ut?G?_₅  tt 4 ttА8@zd@z@8Ȕ  6 6( 6(wQP@\ffw\_  ¯,G6΅7t2j % (hR')#/@t $`n\`lMć(&& EC!'`tCJ~I 56_2jK@zF$;Я$DC q) E"^"F5Q i90D =xC5((!`$kE Vf@u Q+LZw` < O@QS %pIQlYETH"PJWzt}y?>b?Xt$$=K"Y;D% 'F0ҀcCB !AC) "L H * _HIh}$I x ?@t5h6`>4LɎ7Ppuzsue)nM )'w$D( <1# ; h{'k w?2L$I%QXB ebGQUqF"Pffff<" pQ5ǀRbt<sXf'}`Iz'^|A%X+@BeTPrft;G7@k@1' 8ـ|IaCm*g(Dș5 L  b12)0p S¸ъJjS6[CS1}<@Zw(iXy}U ԍ+Lb 7 @\ ai (-$׀R7&o`Ҭ(<5Lwe)iB}0 "*S@h RJFҡāJ=CCA#GJGO'\GGG1`DiO€!D記,G,XB %g `3'A)lUE/uxHL>o0^0 /aȀ(P,BIB1b %s ߲`$į )Ȁ28X#Q鰉?$U T`1FUТj݂((PV}5.ob;WeArFB?+e@ DHd!`*+(#p_<\ @ ?$l%Z7Hȇ@\o EI>h{EAZ @!R,Y4)Mv@[!wD!)/BpjFDrԯ;.kƊV:EpJ Ozd8&-]H: lpn ( }2BTKi< ^+S^@ #8Ą P),Ę3 & k~B`I)1c 3Ɍf]."$GP*)+!Cpd 8[xACB:B_,AgU!p!!`(߯ՌC?㼁.@@BEHCS(n ) Vg& A^L-h. $ & Y߰Dg|+.Q}>U\H~!' Ȣ65HCD? :p:|YfAPY5| X4r~ב)Ǐ  MlPA@  09 09 y!y!8H (c!!(6!QP@ !ffwʨ\ :Gc W,"Lq‡}͘@)rv@"#rBnX# һ=R 0#@GWČ|"Aflw݌](&ˌ,0< AH' }ضť-!I HRBd"@? x% J'Q-"RǤyN@X8"`6#ȌQ)gZnߨ 'շ`ހ<bHH)MlZbӖ(1A Pa/BL# BEACB *A9#+an)JqL_3`E8p u? ;RbSWb 1)9?ѯCs?9@ Vh4%+]c<7* @_~WԳÌʹSj 2)TR! /|#؁)ڭ Kӎ Nָܲ F0EM} %$q.B &{I%)Bkh&@l8q @([ b.~ -p3sAgh,õjɾ60:āw&4(Wd6  '`!ߥ ~RS2]_e lؙfqfAL5"d.0lP!;|`(4Av6d2}~i."I UL^(1&4~$PldqD$ ^Xb (PBPg %@ "z@!C=e/,. ( QUc00r|ہB9 } 4(@ BbĠ@0GHE.a0(HҀ`!_Nɀ?$r?ƸH$ FnP,& 8SXzPUE:S" @G6:y$b};\Od S$04 .DğLQxg](uҫ8M|Q| F| r9Ss GRه\ 9At16!-'N-ZuKBM%zb5=OenPJwdn@$, ##)6P1x``%= A6z>> 8]) d%ĈH O DDc1cŀ@/PS A C8%!bI9B-b+G~H<<b<*9dUHKx'0?HΟ< c0L@<{E:tӃN,Yaybҝ`;wN|%-C#VOZax= $744T l%ή 1OkC\R~t?VEB4$KV5Ba:<~(P+{MT_'I/ 5ƔǨl1y@q/| +`@-l7@`30f14)M HRB$(R'& $q#A 2%-^p(rHF F^d@CAD:Pq)q##?@ N? *T4hB)JU*JZ *B\+/P  0`K $@$HZ #(1$J@"@hF:8Ҭ,dɜ"G!> Ҍ&@r@=^:Og>Jg%Q@"pd'N 82pd  (^> >@BUY+ @^Xb (P(t Tu]u R:5#R8@ @^X|rH_aF`yyߍ5F6qD0e!m44Qs 0BÏpgh$Hq$< >DAlQ?el082E:P %@@@/ =HB#YB1cŀ:Jb_~s((QE*sXp (x!G3╬i]1 $0'$"Ea&pm1Ճ檼Ahc{ '|00@0"AE@>qk`)lZ`>Z(&"?@ ,KoPj}IEQ) S@̇6@L`Ro8P:0iJJҘęZh@@=`3 d~ |Ц4)!I HRB ,~$ G A"[NP BtJ d;ZB2(0 [а XH'؀9o6 )\_ $nnocc Pb(1A Pa DD$$J1.UB " -`$1@Af D0FtUE_\gt?Kflp JU[U2bC8x@ѕ쁀*ɛ+Lg՚#sqx@iʠ5Y?e@ CM@snJ/dW8rrrT4iP΂)JRJ- X1Z*mh$`i0*_307O w9ȌLh} ha c_dI&wpg/1{w(,dɜfaɃ0SCTp )XYU9@ "Y'Fhg+Wu3R K$oaHW2)-lV "fFR`: OPGN4ǦUlz)ߴC@3ޖz}@:ehJU1c1`vъBzjFrs h?@G 3<  u#)G ΛNSnucCUi:];̀ ` ( <qZR3 aOЦ$)!I HRBP'p'8NOc(1A Pb6l`++aXVW9BS)0) R)JRK@E0a !C|o2ɖLddtYg,L@B>7(l F;f~(PK`qZR3 aOЦ$)!I HRBP'p'8NOc(1A Pb6l`++aXVW9BS)0) R)JRK@E0a !C|o2ɖLddtYg,L@B>7(l F;f~(PK`qZR3 aOЦ$)!I HRBP'p'8NOc(1A Pb6l`++aXVW9BS)0) R)JRK@E0a !C|o2ɖLddtYg,L@B>7(l F;f~(PK`qZR3 aOЦ$)!I HRBP'p'8NOc(1A Pb6l`++aXVW9BS)0) R)JRK@E0a !C|o2ɖLddtYg,L@B>7(l F;f~(PK`qZR3 aOЦ$)!I HRBP'p'8NOc(1A Pb6l`++aXVW9BS)0) R)JRK@E0a !C|o2ɖLddtYg,L@B>7(l F;f~(PK`qZR3 aOЦ$)!I HRBP'p'8NOc(1A Pb6l`++aXVW9BS)0) R)JRK@E0a !C|o2ɖLddtYg,L@B>7(l F;f~(PK`q ZR3 aOЦ$)!I HRBP'p'8NOc(1A Pb6l`++aXVW9BS)0) R)JRK@E0a !C|o2ɖLddtYg,L@B>7(l F;f~(PK`q ZR3 aOЦ$)!I HRBP'p'8NOc(1A Pb6l`++aXVW9BS)0) R)JRK@E0a !C|o2ɖLddtYg,L@B>7(l F;f~(PK`ʬ `\3 aOЦ%)1iLZ `'p'8NOc(1A NbbC>'>^ 0s+ b·9ik0)S bOiiiDɝ)JRU*lB<ct@M>'2ɚLd` Űb8Q)$T8@q` L@B>7(l F;f~(PiC#\B?D of;M}>t@].A | '8RA0FB+FJg9r#Ȍg"1H07 `F#o"k`g)IK2TR42Y U@ ~b^r Ą  ; w20b@ x`\.> q\| ud=G=^a,((FL+:%:Dt(]agf(? D@-l$#H`p^/?y^~(  ut?G?_₅  tt 4 ttА8@zd@z@8Ȕ09 6 6("6(wQP@\ffw\_  ¯,G6΅7t2j % (hR')#/@t $`n\`lMć(&& EC!'`tCJ~I 56_2jK@zF$;Я$DC q) E"^"F5Q i90D =xC5((!`$kE Vf@u Q+LZw` < O@QS %pIQlYETH"PJWzt}y?>b?Xt$$=K"Y;D% 'F0ҀcCB !AC) "L H * _HIh}$I x ?@t5h6`>4LɎ7Ppuzsue)nM )'w$D( <1# ; h{'k w?2L$I%QXB ebGQUqF"Pffff<" pQ5ǀRbt<sXf'}`Iz'^|A%X+@BeTPrft;G7@k@1' 8ـ|IaCm*g(Dș5 L  b12)0p S¸ъJjS6[CS1}<@Zw(iXy}U ԍ+Lb 7 @\ ai (-$׀R7&o`Ҭ(<5Lwe)iB}0 "*S@h RJFҡāJ=CCA#GJGO'\GGG1`DiO€!D記,G,XB %g `3'A)lUE/uxHL>o0^0 /aȀ(P,BIB1b %s ߲`$į )Ȁ28X#Q鰉?$U T`1FUТj݂((PV}5.ob;WeArFB?+e@ DHd!`*+(#p_<\ @ ?$l%Z7Hȇ@\o EI>h{EAZ @!R,Y4)Mv@[!wD!)/BpjFDrԯ;.kƊV:EpJ Ozd8&-]H: lpn ( }2BTKi< ^+S^@ #8Ą P),Ę3 & k~B`I)1c 3Ɍf]."$GP*)+!Cpd 8[xACB:B_,AgU!p!!`(߯ՌC?㼁.@@BEHCS(n ) Vg& A^L-h. $ & Y߰Dg|+.Q}>U\H~!' Ȣ65HCD? :p:|YfAPY5| X4r~ב)Ǐ  MlPA@09 @` @` 6 6(#6(wQP@\ffw\_  ¯,G6΅7t2j % (hR')#/@t $`n\`lMć(&& EC!'`tCJ~I 56_2jK@zF$;Я$DC q) E"^"F5Q i90D =xC5((!`$kE Vf@u Q+LZw` < O@QS %pIQlYETH"PJWzt}y?>b?Xt$$=K"Y;D% 'F0ҀcCB !AC) "L H * _HIh}$I x ?@t5h6`>4LɎ7Ppuzsue)nM )'w$D( <1# ; h{'k w?2L$I%QXB ebGQUqF"Pffff<" pQ5ǀRbt<sXf'}`Iz'^|A%X+@BeTPrft;G7@k@1' 8ـ|IaCm*g(Dș5 L  b12)0p S¸ъJjS6[CS1}<@Zw(iXy}U ԍ+Lb 7 @\ ai (-$׀R7&o`Ҭ(<5Lwe)iB}0 "*S@h RJFҡāJ=CCA#GJGO'\GGG1`DiO€!D記,G,XB %g `3'A)lUE/uxHL>o0^0 /aȀ(P,BIB1b %s ߲`$į )Ȁ28X#Q鰉?$U T`1FUТj݂((PV}5.ob;WeArFB?+e@ DHd!`*+(#p_<\ @ ?$l%Z7Hȇ@\o EI>h{EAZ @!R,Y4)Mv@[!wD!)/BpjFDrԯ;.kƊV:EpJ Ozd8&-]H: lpn ( }2BTKi< ^+S^@ #8Ą P),Ę3 & k~B`I)1c 3Ɍf]."$GP*)+!Cpd 8[xACB:B_,AgU!p!!`(߯ՌC?㼁.@@BEHCS(n ) Vg& A^L-h. $ & Y߰Dg|+.Q}>U\H~!' Ȣ65HCD? :p:|YfAPY5| X4r~ב)Ǐ  MlPA@P y!y!8H (c!$I(6!QP@ !ffwʨ\ :Gc W,"Lq‡}͘@)rv@"#rBnX# һ=R 0#@GWČ|"Aflw݌](&ˌ,0< AH' }ضť-!I HRBd"@? x% J'Q-"RǤyN@X8"`6#ȌQ)gZnߨ 'շ`ހ<bHH)MlZbӖ(1A Pa/BL# BEACB *A9#+an)JqL_3`E8p u? ;RbSWb 1)9?ѯCs?9@ Vh4%+]c<7* @_~WԳÌʹSj 2)TR! /|#؁)ڭ Kӎ Nָܲ F0EM} %$q.B &{I%)Bkh&@l8q @([ b.~ -p3sAgh,õjɾ60:āw&4(Wd6  '`!ߥ ~RS2]_e lؙfqfAL5"d.0lP!;|`(4Av6d2}~i."I UL^(1&4~$PldqD$ ^Xb (PBPg %@ "z@!C=e/,. ( QUc00r|ہB9 } 4(@ BbĠ@0GHE.a0(HҀ`!_Nɀ?$r?ƸH$ FnP,& 8SXzPUE:S" @G6:y$b};\Od S$04 .DğLQxg](uҫ8M|Q| F| r9Ss GRه\ 9At16!-'N-ZuKBM%zb5=OenPJwdn@$, ##)6P1x``%= A6z>> 8]) d%ĈH O DDc1cŀ@/PS A C8%!bI9B-b+G~H<<b<*9dUHKx'0?HΟ< c0L@<{E:tӃN,Yaybҝ`;wN|%-C#VOZax= $744T l%ή 1OkC\R~t?VEB4$KV5Ba:<~(P+{MT_'I/ 5ƔǨl1y@q/| +`@-l7@`30f14)M HRB$(R'& $q#A 2%-^p(rHF F^d@CAD:Pq)q##?@ N? *T4hB)JU*JZ *B\+/P  0`K $@$HZ #(1$J@"@hF:8Ҭ,dɜ"G!> Ҍ&@r@=^:Og>Jg%Q@"pd'N 82pd  (^> >@BUY+ @^Xb (P(t Tu]u R:5#R8@ @^X|rH_aF`yyߍ5F6qD0e!m44Qs 0BÏpgh$Hq$< >DAlQ?el082E:P %@@@/ =HB#YB1cŀ:Jb_~s((QE*sXp (x!G3╬i]1 $0'$"Ea&pm1Ճ檼Ahc{ '|00@0"AE@>qk`)lZ`>Z(&"?@ ,KoPj}IEQ) S@̇6@L`Ro8P:0iJJҘęZh@@=`3 d~ |Ц4)!I HRB ,~$ G A"[NP BtJ d;ZB2(0 [а XH'؀9o6 )\_ $nnocc Pb(1A Pa DD$$J1.UB " -`$1@Af D0FtUE_\gt?Kflp JU[U2bC8x@ѕ쁀*ɛ+Lg՚#sqx@iʠ5Y?e@ CM@snJ/dW8rrrT4iP΂)JRJ- X1Z*mh$`i0*_307O w9ȌLh} ha c_dI&wpg/1{w(,dɜfaɃ0SCTp )XYU9@ "Y'Fhg+Wu3R K$oaHW2)-lV "fFR`: OPGN4ǦUlz)ߴC@3ޖz}@:ehJU1c1`vъBzjFrs h?@G 3<  u#)G ΛNSnucCUi:];̀ ` ( <qZR3 aOЦ$)!I HRBP'p'8NOc(1A Pb6l`++aXVW9BS)0) R)JRK@E0a !C|o2ɖLddtYg,L@B>7(l F;f~(PK`qZR3 aOЦ$)!I HRBP'p'8NOc(1A Pb6l`++aXVW9BS)0) R)JRK@E0a !C|o2ɖLddtYg,L@B>7(l F;f~(PK`qZR3 aOЦ$)!I HRBP'p'8NOc(1A Pb6l`++aXVW9BS)0) R)JRK@E0a !C|o2ɖLddtYg,L@B>7(l F;f~(PK`qZR3 aOЦ$)!I HRBP'p'8NOc(1A Pb6l`++aXVW9BS)0) R)JRK@E0a !C|o2ɖLddtYg,L@B>7(l F;f~(PK`qZR3 aOЦ$)!I HRBP'p'8NOc(1A Pb6l`++aXVW9BS)0) R)JRK@E0a !C|o2ɖLddtYg,L@B>7(l F;f~(PK`qZR3 aOЦ$)!I HRBP'p'8NOc(1A Pb6l`++aXVW9BS)0) R)JRK@E0a !C|o2ɖLddtYg,L@B>7(l F;f~(PK`q ZR3 aOЦ$)!I HRBP'p'8NOc(1A Pb6l`++aXVW9BS)0) R)JRK@E0a !C|o2ɖLddtYg,L@B>7(l F;f~(PK`q ZR3 aOЦ$)!I HRBP'p'8NOc(1A Pb6l`++aXVW9BS)0) R)JRK@E0a !C|o2ɖLddtYg,L@B>7(l F;f~(PK`ʬ `\3 aOЦ%)1iLZ `'p'8NOc(1A NbbC>'>^ 0s+ b·9ik0)S bOiiiDɝ)JRU*lB<ct@M>'2ɚLd` Űb8Q)$T8@q` L@B>7(l F;f~(PiC#\B?D of;M}>t@].A | '8RA0FB+FJg9r#Ȍg"1H07 `F#o"k`g)IK2TR42Y U@ ~b^r Ą  ; w20b@ x`\.> q\| ud=G=^a,((FL+:%:Dt(]agf(? D@-l$#H`p^/?y^~(  ut?G?_₅  tt 4 ttА8@zd@z@8ȔP XU XU%XUQP@ffw: өl}yc|g < 0(!_dWg Xl=XmS#Za0F!bzCܴ:"VR _#Rn ݤ fRBk$(Q B ?Hf@CE6Kf i8~AB( = LJ8%U;8hTPAlFcȀr]YBDT ,,#Pl+ tޑ&Y&,0IH !~c*& P Z_ "8 N ED{ PPB1$w-/vrC0P11N"(\؅)T jxIa$YP6y"1  k~ ðߡ_JmyNz7)-24G$(MȵCUAG~PH5@Fe0 a ڈf fH(KxƢhW@s6Qa?魹+λZ~aKrƋPE%bOiB2ʅLPԼFvJ>#]o*bEТKW%]:(QhAxPj$RP2 R+E)z,FX # ߎ~%@ X `'1k/  E78u(l`acJBj9!p`96H2+F|3DAB_zL?zvX[pya 8@Mu@)h^,;b8a@qa@t!€wct~X+^נ hc^i(:d#&Z C0z@P,|=U,9I 4#@J`cl@GF( J$<#O-LΒBʄd".NJd@sy0s'|"!/ev]131`L bo fhŤ@i%CR &: @Dt z 4|z,-BZ(?# nQFh4:Hh~`6}Y~_$jl/T!D\@Z(QMfQEyLL%F'?BBJh^ PTzxLj|.tpTSFVD D Ỵ0YWa3zP f&6hjj̠ ZP@ 8h\%"|L @BTI=T3RO.w !!B`OߴwN #șR L"0&J̈́WIR`pGk/?(}XXk L[=\TE\,!aq`IG b`}.vhO]'.IE}">tHO]'.IErJ(H!!$C$C$CH8H8H( p"@Y &n,f6gְšſ4t36`:`I ͨ\"f,FC3h#`xd R]]BGк>.t} ]BGк>.[Hs`$s`K )6Acd6Acd6@D^dgTa\Ԧj5P#A*gBXm|K c,я *Y?5*gjT@/_?|/_??@@{ rg rg r 7s }1} pt -=r]=rD=rD2f͛%5)39<;C9vR>;8p wd. <A PTĥ?%%1м `HddZ`c.(P>b9F3asZ=P2V_%~JWRe+)YJVR`@B"DL[(.a~cN.YoXa =`APXf:?+^ACf$YC& Cȑ/c0fJƎ#v(,"I5F1LxLxLh1cD `0 E# STdEeȇ@@=a pcŃ 0c NI A]h``_0!AO.kkQϗ`7cG2apӜWF8F@0QљNZh ,oHPh(t)0l@@ __ǹ*V/X PT222eKdY,K%6%<J!ӭXP( @h$}?+٤+ a)*  `J'X,_K^{.e̹e" `C+@2`!OV|G᜝8"E1*20D":#IJ3Z # 3+|4hC_ u8PitXDVD`"-44U7_jXj~rdsY c a0H$ A  B @!&e8B%A`!1F ]A$ C"LUX=WD)T \U136f̑R*Ea!<ˉ+W4$h/_ *8kK{.I$Ȇh.tHbw}T6vE}">t_X ?Pe e2*0m$@1~ %9+!%"E8G2 ~( _SSm)-$0P@W~(dNa4EA*©eB?9 2LC<BLAm t} ]B ddd>.FH6͈Sd9O33@o/U" PTܢ@u92ZBW 80  L+ _u( AB';@{ il3WX@UpyWP݀Wgf,_Ъ%*HpH@P P P XU XU&XUQP@ffw: өl}yc|g < 0(!_dWg Xl=XmS#Za0F!bzCܴ:"VR _#Rn ݤ fRBk$(Q B ?Hf@CE6Kf i8~AB( = LJ8%U;8hTPAlFcȀr]YBDT ,,#Pl+ tޑ&Y&,0IH !~c*& P Z_ "8 N ED{ PPB1$w-/vrC0P11N"(\؅)T jxIa$YP6y"1  k~ ðߡ_JmyNz7)-24G$(MȵCUAG~PH5@Fe0 a ڈf fH(KxƢhW@s6Qa?魹+λZ~aKrƋPE%bOiB2ʅLPԼFvJ>#]o*bEТKW%]:(QhAxPj$RP2 R+E)z,FX # ߎ~%@ X `'1k/  E78u(l`acJBj9!p`96H2+F|3DAB_zL?zvX[pya 8@Mu@)h^,;b8a@qa@t!€wct~X+^נ hc^i(:d#&Z C0z@P,|=U,9I 4#@J`cl@GF( J$<#O-LΒBʄd".NJd@sy0s'|"!/ev]131`L bo fhŤ@i%CR &: @Dt z 4|z,-BZ(?# nQFh4:Hh~`6}Y~_$jl/T!D\@Z(QMfQEyLL%F'?BBJh^ PTzxLj|.tpTSFVD D Ỵ0YWa3zP f&6hjj̠ ZP@ 8h\%"|L @BTI=T3RO.w !!B`OߴwN #șR L"0&J̈́WIR`pGk/?(}XXk L[=\TE\,!aq`IG b`}.vhO]'.IE}">tHO]'.IErJ(H!!$C$C$CH8H8H( p"@Y &n,f6gְšſ4t36`:`I ͨ\"f,FC3h#`xd R]]BGк>.t} ]BGк>.[Hs`$s`K )6Acd6Acd6@D^dgTa\Ԧj5P#A*gBXm|K c,я *Y?5*gjT@/_?|/_??@@{ rg rg r 7s }1} pt -=r]=rD=rD2f͛%5)39<;C9vR>;8p wd. <A PTĥ?%%1м `HddZ`c.(P>b9F3asZ=P2V_%~JWRe+)YJVR`@B"DL[(.a~cN.YoXa =`APXf:?+^ACf$YC& Cȑ/c0fJƎ#v(,"I5F1LxLxLh1cD `0 E# STdEeȇ@@=a pcŃ 0c NI A]h``_0!AO.kkQϗ`7cG2apӜWF8F@0QљNZh ,oHPh(t)0l@@ __ǹ*V/X PT222eKdY,K%6%<J!ӭXP( @h$}?+٤+ a)*  `J'X,_K^{.e̹e" `C+@2`!OV|G᜝8"E1*20D":#IJ3Z # 3+|4hC_ u8PitXDVD`"-44U7_jXj~rdsY c a0H$ A  B @!&e8B%A`!1F ]A$ C"LUX=WD)T \U136f̑R*Ea!<ˉ+W4$h/_ *8kK{.I$Ȇh.tHbw}T6vE}">t_X ?Pe e2*0m$@1~ %9+!%"E8G2 ~( _SSm)-$0P@W~(dNa4EA*©eB?9 2LC<BLAm t} ]B ddd>.FH6͈Sd9O33@o/U" PTܢ@u92ZBW 80  L+ _u( AB';@{ il3WX@UpyWP݀Wgf,_Ъ%*HpH@P P ` y!y!8H (c!'(6!QP@ !ffwʨ\ :Gc W,"Lq‡}͘@)rv@"#rBnX# һ=R 0#@GWČ|"Aflw݌](&ˌ,0< AH' }ضť-!I HRBd"@? x% J'Q-"RǤyN@X8"`6#ȌQ)gZnߨ 'շ`ހ<bHH)MlZbӖ(1A Pa/BL# BEACB *A9#+an)JqL_3`E8p u? ;RbSWb 1)9?ѯCs?9@ Vh4%+]c<7* @_~WԳÌʹSj 2)TR! /|#؁)ڭ Kӎ Nָܲ F0EM} %$q.B &{I%)Bkh&@l8q @([ b.~ -p3sAgh,õjɾ60:āw&4(Wd6  '`!ߥ ~RS2]_e lؙfqfAL5"d.0lP!;|`(4Av6d2}~i."I UL^(1&4~$PldqD$ ^Xb (PBPg %@ "z@!C=e/,. ( QUc00r|ہB9 } 4(@ BbĠ@0GHE.a0(HҀ`!_Nɀ?$r?ƸH$ FnP,& 8SXzPUE:S" @G6:y$b};\Od S$04 .DğLQxg](uҫ8M|Q| F| r9Ss GRه\ 9At16!-'N-ZuKBM%zb5=OenPJwdn@$, ##)6P1x``%= A6z>> 8]) d%ĈH O DDc1cŀ@/PS A C8%!bI9B-b+G~H<<b<*9dUHKx'0?HΟ< c0L@<{E:tӃN,Yaybҝ`;wN|%-C#VOZax= $744T l%ή 1OkC\R~t?VEB4$KV5Ba:<~(P+{MT_'I/ 5ƔǨl1y@q/| +`@-l7@`30f14)M HRB$(R'& $q#A 2%-^p(rHF F^d@CAD:Pq)q##?@ N? *T4hB)JU*JZ *B\+/P  0`K $@$HZ #(1$J@"@hF:8Ҭ,dɜ"G!> Ҍ&@r@=^:Og>Jg%Q@"pd'N 82pd  (^> >@BUY+ @^Xb (P(t Tu]u R:5#R8@ @^X|rH_aF`yyߍ5F6qD0e!m44Qs 0BÏpgh$Hq$< >DAlQ?el082E:P %@@@/ =HB#YB1cŀ:Jb_~s((QE*sXp (x!G3╬i]1 $0'$"Ea&pm1Ճ檼Ahc{ '|00@0"AE@>qk`)lZ`>Z(&"?@ ,KoPj}IEQ) S@̇6@L`Ro8P:0iJJҘęZh@@=`3 d~ |Ц4)!I HRB ,~$ G A"[NP BtJ d;ZB2(0 [а XH'؀9o6 )\_ $nnocc Pb(1A Pa DD$$J1.UB " -`$1@Af D0FtUE_\gt?Kflp JU[U2bC8x@ѕ쁀*ɛ+Lg՚#sqx@iʠ5Y?e@ CM@snJ/dW8rrrT4iP΂)JRJ- X1Z*mh$`i0*_307O w9ȌLh} ha c_dI&wpg/1{w(,dɜfaɃ0SCTp )XYU9@ "Y'Fhg+Wu3R K$oaHW2)-lV "fFR`: OPGN4ǦUlz)ߴC@3ޖz}@:ehJU1c1`vъBzjFrs h?@G 3<  u#)G ΛNSnucCUi:];̀ ` ( <qZR3 aOЦ$)!I HRBP'p'8NOc(1A Pb6l`++aXVW9BS)0) R)JRK@E0a !C|o2ɖLddtYg,L@B>7(l F;f~(PK`qZR3 aOЦ$)!I HRBP'p'8NOc(1A Pb6l`++aXVW9BS)0) R)JRK@E0a !C|o2ɖLddtYg,L@B>7(l F;f~(PK`qZR3 aOЦ$)!I HRBP'p'8NOc(1A Pb6l`++aXVW9BS)0) R)JRK@E0a !C|o2ɖLddtYg,L@B>7(l F;f~(PK`qZR3 aOЦ$)!I HRBP'p'8NOc(1A Pb6l`++aXVW9BS)0) R)JRK@E0a !C|o2ɖLddtYg,L@B>7(l F;f~(PK`qZR3 aOЦ$)!I HRBP'p'8NOc(1A Pb6l`++aXVW9BS)0) R)JRK@E0a !C|o2ɖLddtYg,L@B>7(l F;f~(PK`qZR3 aOЦ$)!I HRBP'p'8NOc(1A Pb6l`++aXVW9BS)0) R)JRK@E0a !C|o2ɖLddtYg,L@B>7(l F;f~(PK`q ZR3 aOЦ$)!I HRBP'p'8NOc(1A Pb6l`++aXVW9BS)0) R)JRK@E0a !C|o2ɖLddtYg,L@B>7(l F;f~(PK`q ZR3 aOЦ$)!I HRBP'p'8NOc(1A Pb6l`++aXVW9BS)0) R)JRK@E0a !C|o2ɖLddtYg,L@B>7(l F;f~(PK`ʬ `\3 aOЦ%)1iLZ `'p'8NOc(1A NbbC>'>^ 0s+ b·9ik0)S bOiiiDɝ)JRU*lB<ct@M>'2ɚLd` Űb8Q)$T8@q` L@B>7(l F;f~(PiC#\B?D of;M}>t@].A | '8RA0FB+FJg9r#Ȍg"1H07 `F#o"k`g)IK2TR42Y U@ ~b^r Ą  ; w20b@ x`\.> q\| ud=G=^a,((FL+:%:Dt(]agf(? D@-l$#H`p^/?y^~(  ut?G?_₅  tt 4 ttА8@zd@z@8Ȕ` 6 6((6(wQP@\ffw\_  ¯,G6΅7t2j % (hR')#/@t $`n\`lMć(&& EC!'`tCJ~I 56_2jK@zF$;Я$DC q) E"^"F5Q i90D =xC5((!`$kE Vf@u Q+LZw` < O@QS %pIQlYETH"PJWzt}y?>b?Xt$$=K"Y;D% 'F0ҀcCB !AC) "L H * _HIh}$I x ?@t5h6`>4LɎ7Ppuzsue)nM )'w$D( <1# ; h{'k w?2L$I%QXB ebGQUqF"Pffff<" pQ5ǀRbt<sXf'}`Iz'^|A%X+@BeTPrft;G7@k@1' 8ـ|IaCm*g(Dș5 L  b12)0p S¸ъJjS6[CS1}<@Zw(iXy}U ԍ+Lb 7 @\ ai (-$׀R7&o`Ҭ(<5Lwe)iB}0 "*S@h RJFҡāJ=CCA#GJGO'\GGG1`DiO€!D記,G,XB %g `3'A)lUE/uxHL>o0^0 /aȀ(P,BIB1b %s ߲`$į )Ȁ28X#Q鰉?$U T`1FUТj݂((PV}5.ob;WeArFB?+e@ DHd!`*+(#p_<\ @ ?$l%Z7Hȇ@\o EI>h{EAZ @!R,Y4)Mv@[!wD!)/BpjFDrԯ;.kƊV:EpJ Ozd8&-]H: lpn ( }2BTKi< ^+S^@ #8Ą P),Ę3 & k~B`I)1c 3Ɍf]."$GP*)+!Cpd 8[xACB:B_,AgU!p!!`(߯ՌC?㼁.@@BEHCS(n ) Vg& A^L-h. $ & Y߰Dg|+.Q}>U\H~!' Ȣ65HCD? :p:|YfAPY5| X4r~ב)Ǐ  MlPA@J :: $)QP@`ffwc(Q@!@) 6X C!Ă"PB`V@0Hf*8N`' ,D4d4ēADK"brR BA`K`!8 !P )CUHQ  PL\d, @DE% k "  PaB(*1J𜾖Jo "`N h  @(@bB&Pq*W   @$  #?g%`!,D+$&P@Q_0P" d hz $#P(F",1IUO a@hJ$A0(RBcd@! <0b!JZ aP"H)(ZRQ@,@, J( a "`@{&" S@A@P%Ce^G*,Wp PA @@$W `T",o%@PDJJIE~ͦ@H  % PDpP1(F*"0Hq`m #H/ #\QA$:@ F""WA @$  <0XY @А E b"P)! @( NV`0 O @ʍ 1(!L@ -F/℉Gi hPZT?UizJhVH y38%b AGH&9@Ijd?kOPA,/|e"lXkLA H\âK.A(,RDr4h dQ4OCn_h>!e/'mdEf5Lн ?!1r iL1&@+E8H`mk!EyV|`EAd3Ea@HA.pCIVê >P]ԃLb8@tAdH%H$J %1ꮸG Ss D~" W5d H$WM"WQbԜXAGyX. VP(@bd  `zGzqi8@j@Ȃ %LF1\((ں-l\td @Psc 9LK >\w@hBmkx@d4DC! F,ᑨ@uGq"HŜ.I9'9Vs)X)KV{ YԬB-VJR^Z)b$`ykF#Qs'f*8iTQY+31/@ B$ (t-2,&r)T=~d s(B5u "XF@@ &,h-9n ;N/FC0! n|I6Pmb X~䓻׬<06,P]Z4yFĖQ>/1z&(?7qkj!A\! u>,x} ]?@ p怠>B#8g?Nn;5PF*j24 E!F  S砒(dI-HpZf Oˑ@R %"I|@Wzvv'aYEA%9)Cj@u:[@Pό%^ rcXLHWa"DJ# s 1 # Za0\2yGмLҤa(94$_~D!`@AA1 (ml0NG.V"r 9|@    J٠8E w`sir%(bO  h-t!@PТPAIB_D^~9{5&H_), l(P(@EJ_(x^?@)ЀL/" S:Ӻ ЙVz?P <<@|^B.B">DB _">D9P9@F2w)E`<S,:xLSry  RDD61Ο/dd| p'P(Q He*TWy?lL  `@fAHPpa@JA$ @M#@r&#H 8 a \0pP!EP~XMP  R   DP)(&P6j  0%94RNWU8P< # ł"$,S? P & t#" @b A$)YW;M$H @$0A` H@B $Bee "HA 0p㘂W섀AhB`xYAa`@@K ? ~ ZlC@dKNSLIA #{Vkr#<$ E DRR &HSHGJ .CT @C5+&g@ dNt7>Dax`(Z#X0K rr9=jCpEj)qw6`hAAY~ ,~>?%#&F Ye_B0"ojok5܅XJ,.KGG k@XtUqUh"uu6e t}[Ox N!h3? *~kAv  0 7#AbLdj Z.P F*P$N,"IY*rU&||\`GQh$ [?E+cJޗZ` AHDbBKbu"l 2 !r D(? "p@AC+}DⰈ:?5 7Q.% 7@y. -22P`.t"L1_egFP9䮁,hȢc0O:5%GhX QΦҠ9OĐ[tysDl";,{נEp($P *" bIAQ>ԅ0K$0ʲ'pP*&UU[T}ꭁKxkY)/K V@0 COW_,d@P,Z=p%BA.n7i0aM6&R߰ e H D] 2)`r"QԆAUЄƂEhf+2XmFJ qG" ڗB'# ¿`(ϊhAG9!fZSOlT`x 1x7/A(l}>Sj<"J(u4yrjhw 8 0@4Ax&TM(1bD$PI?*(Y0@? 2;I{C!_ H~5 p KC 2lĿ;FO\!*pۼ!a!a@ +tfG0XҸQ b `(|piQ\$reA}LO7A yiz+}GxV.Dv!N> TY||"U Rm *3D%BF>%|7 Cjt4SX !]`&B[(mƠJ 4QK*0X&9k@8K`A T!ջ/ GU!.,T}oM j@FM&C-{BYH)4-'Ł"4R2jARCል$*E4@Go@"mD#?& kaڂq 34Hˬ1!ZWP_@u0HEG^~/? >\ܿ@  'ET!@})( .@ktEO /U\B]-[_q.w@,*(ȆBBD ,BPƄ@;J" (rj%8z)ZHzDEH$Da!*,Xb P'P 6L>D8*5 EIA =&";8ݒQ=ܴ yy F8$)@(*&jVr_U8L#-xTZAJ5b( 5BۄDڎ\rrWVi2)z0m9 J·"`}/+8[rF|v2E|yr#@) [ Qk} { ARwfAS䚇1@lo0I.Q4#0~k@{ 'Hx{C8G'"?@O )%4l \] j1ÜFU+dIycq7 4F<ypiӀ K6{}lIw@rހjo@6q_?@>|^zjjF`!M }R1$\Y膱Q'@ AYi0CnAȲ?pM,_!%'L(/48esIQPe0.[ 8dCdCqun.D^G^>Q""""^4:@sX-3Ӥ0\GHj@AkNO(LB|/ QY -!DMqKB^i%`0XGi{(ɂq*@ C%D (4"0F)QHDL%8JA1(NE( `4{'"@$@" pT IVE D@ `ʂ 8=JWI0Ծ_IAvkyDVtp9,*QANR6ck?*]k BU5/ J (@1u7"Se1(2 ?T4T %IEqa5B5@WI`hBpziU>N((Zmi ($h<>4&$@M Eq䋔@n% @wxdrAnw"L}C[.?T@d?;y&J "{Glɍ1 tqU&h  AzBlI`҈C-%Hj`0L(D8L.""L0DHwHbK )UL!HRJA0~<@bW3 CV$QibTd r] 3HtK5 Fm=?r׵" A}k?}AP1$@PF@ .N?< ȿ =2Na7x5%8 d%`m՗-!p=H @ ^+u6WMWQBt|"tT@w 5'yep0p i>4PÙ% h&%A@DthA,A`2 b. BAJ*ʆP!@aR=% B4jjC @9+a XEa?`UѭM/ۀI:M`\6SW4MUҡj} ȽXw-@l X@bHۣLF`D!#4NViOF_*= 6`y 崑ğ(vB@(4aEკƸC 4=|x}o06bbE|G@ONa\ bTw09TGC&r5y!?W)G1~yx8A tÿ_!# ݺ #'HEgukwӊ%21ːte;_~!jA <8<`$@TT*i(Ѧ$*98SE+<}z Jj2t U">|XrC:1C.!1O( \ A* 1Oy2Qa@~li/ XTr9ZKb,/^ )kK#AZ;H)/F?,_ᄏ& kbDN‰ * 4  pG5TYpX:A8B9C(08lGh(tPiQGXU%3CiLjz|TI4`R9 xNh%v' A%n''mNM""K͢FŘTNTp_̶3#@fzHT "(mfL-9[*@EnS J79I'gyA8q $=JG`5 Py W^]C0""6lo1 <ޟ)!T!S|?[[?!YW)2V4#2fj`y!W( ^y7XƟ҄\Bsz<4$\hhBiF(?~,aٌk7a2$NnnV/*n{. קn(1ӏN h;UҤ7>a/]P" t 9 *Puʯb4"~DBG+@r頊J(X0ȸAZԤ * d@GK8f9!2iC J=J,.ѠP ps?PX( Ě-Jvm J _iQF&Tk UB8A55a)FkB [BXB!WPⲁF5_i_KU@)V/t T@tR`}X \ iA"{8G_V*Ydup:$F8T~NH e2t9N%@XCk ?Pu/3 PQH@G(bHTTt&!M@km^?^Z! N2@#NPG՚ٞ<' C CƄkhr? ds*QA1ńxk+9 $^ Pb @ER =2BU(%B?U  f@'0P0-k/ #n>!!J S< 7=(_a׀EY dbtrFZV*tPf ; *rRJ zaԪ`[8<\'@!&QG}@*u"AR_/ф+>Ki>0*M2 ?`A*PhG1A >a@(w_,#B?p?:-*!4?BU'` p  np@10㳊# +#3(B!:I? - gn0]AL5q%.LA?t, G1h+s:+`,3IjnZT T8ŕj}2)yA,%p nt c8(D3>RPDR+Ȁ!wm:oB?JTBxU$ -U H('HX/06F(@lwJ/SMP;F4%W!+_"K5HB|n0Bd4@-%ŝ@V/#C 3|.1NjY O?/Pſ1@Bda8 ( a캃eJZ #,dj0!gB9@Jb,7 @|0@44Q@0:@:&*1D 0Ui@!AkQ Ah6HGҪ׀ף69ePO0O!!-,WHՙ %)@FҋOWl|C!@,u4qC @#=R+T2/ d hψDY52Y(n "b@(0Dxz 7SE`B@}D/Hh `r*V Wؿh AZJh@+T2&h8NY F?ɴ) ]* { |?@}M=  #7gfbF^W`O*Ur1xZ o(_ʔxٛD0(N?xn@dxJA(G N~( 2PtrJiJw+8C;M5/ ^\D Zhy6*z#E R+R8>/TF`!u>I٨ @R- iShz 'LG $0!=5HY P]UE G=QL4*|Q}?&P$7@ d+6vh~ ҡV\X%hRGz|gaRGf #Pax5P->S^~ ,%,I00"'B,M%AoRR L#2C%JP:Av(` vB ꥽[,},$K$0 P$I I# @db#@@0`@8yFʅ*#%@ 0!p PPh PZ,(CL)0BU*(!a T.wvQPPЊ)G-Y ^s|tF5,ҵ"h"D *F-&Ǟ074iMH]FQ,+kKɆUAu ԼV/Ӹr < r c=TK b|_!ZČ[WXXDAg / $d:"v ;x,$Rtc HYNJ{59Ab`@g?0&Eu +=Vq؈&`aB0y-lEiDj5*XHdcm@%Lb"  h ua%P$ "!@P4:D+]Z{6VhAΉD=\bM KLʑS XBxͅ6!2ڄVbۮp,[v,OGVA=$A|Mv!$3԰% ~\ªLLA"ixM|¹wػ)ۺS..h|W0k6Y1ioD} 5?_V$w167K,ՂRQ?sOM F ,60I!.R.aԬf'2xXDJBv"YdV^7񒋿w1ů63*uI$M2oyJS: lVh(0 `9L1P %LEqXH*PDP>t,L0FXI*$ IFXX6ր*J}%4I J)BR4)*P!It$"X&X%Eٗ4@PQJzQ#3H{DV:Az 60KDT2)XGZ9Z<3c)h/mRT-]N+䫉y%Shkؓ$bv J9%XݼD!"jqcGh0`uA  $6qJYQZB5zx\0C(BJVI(Xpr &V&r3C02ܛ2'KGm=h|=C2 t3U>0 +ą$!Wz6? [ '%!܌c7_UZJ@p)h<_q@ HA(BTAJ`P ."q" @P(R41SXSBE!h $&B Q -5N :X1":1QMs0 5(i9rY+Lֽ5'uCJ˿ 5YJ%,.5tMWl0\2rVRҸq:`"@C&)-OA`HQVD\T4=m¨WՙuI 3\ʰ_,(PF‡ŗ*`hsD+]V"),4aEKFZBNPf1ÍK 92) AX@6 (" KǹBB(r|T C@,0RYgV; 9"1:3ƌU*2k3U=.[UNk H넬ⅡRErEt}*r`ٽIA`Ltry8Ckʆ/yV>bmg)Py` $Ht&!E@؂f攣V{cu4^rY8g3d:jzD!Rk@Y7"H5BI*P&Lģ@/;,E-52ME0$8$0t˖4Sʀ12IPIڹOYlHY01*]gP! Teoǣ@Ffp9$a1k/SB9)6/%A.B\|p2)RQBPz)]b-wHJ]> snI!2?5P0ትhGtV\TZ1ʔBG] qسCI!a# A(sQlrTQ N ⌭pRt Q|=g#QP1z L ԯ (Ag(BA$ECQFXHԁf QuZOViVN$XFhе$TJyC($h d)J Q(` Iya y|*'Q@$Hՠb2NO"G+ǦD$8D(|A 2}Bgr@HpPR%g0 *.*K8 VC΢'IL-B ?)JC_T$G`,EusވRArb+Abٜ#@ґ !1о:j*E,qA8@Q+"iO;ÈS (ϘqO)ka_C]QvME8Dij4WWԇ,&,)^85#*Q. 14?HE1H,DxD$"p pT( . P$u8z?ʬt Y+0-GW##(گ##4"$@R+Jj@/_h,ʿSZm#q!KE$k]KL%JaNފHF׾B#j'cH*K<" )Cg ~H& Ps ,">CLm!"I м\Eix @p`0-(/AyA QEC rÃK``a(@ `'TtG*%B|t63C! 8$,Šϥ΁&C9?Qy.=.3y (|z/Gp}@-E`BQv]QDZXI:'֑~/ʑye'Oుazō]EBON a)<\!@$X. \/?!#x^,B AiXx|d~P?(7c(\|zPoFy@  #@T8/5#"4P"(@(@! D!B F !@8n^@,J:C3ׇDQC*hS? @M(Pz!Z(O^@Y4 ^,)Ԍ^\@vF7 =L@/6dQ?gB"\A  "-PJ0GԎÇ`CA/ zi 'VP5(r,@(L XdsQ@c3`wDY aA~+p@@#E` @ "5I@*QB sFV@ Hvl N,晬F-W # 4 ddd1#Nj-&`5G'M!i*  %4'PB#)D!_爇& @ ah _0p?4 A0aK'!((AoHs搘Q%w6 K#L?\a=N94uJ@ )3APLU|$ .6(?ade 2* Fbt8@<@P5B(\U/3(})?ojTt=׌I]E\\DSA{,D[(B@T!Kf0&1?s vN jH"'etÓQxVиG@BYg53 9 Y#& 14UZ< ՠ@ hI - IB> ]y,L~0T:6m CJ0$xJ]@Xպ+g`a<n*IYBH (qܑA0 q/z5+Ɣve2`ʗ`gEA9EZҋ$5CN-@ BV4 M7(%_QE W$ P=  @2?aHgL@# "L~G(W4HNə~*#$+<V?M@@`4\B-,d/(i$iZ X@Bt``  $ D^I@< RN $tx`%@ Ҁ4n5@/VQHY]@| Ӂ*0NH DEFȀ }!b(iÕTf/hd Ac(-I`x!I Qn>!!D0D8 H¤/ ,xMP$.-X-(RtE@RdK1 :a&!* %,gDuN~r 9UɕծE_ܧ`AJʑH\9W~`W_W(]`Q^潏 |1g>Ph>" *,(Ddɓ&ij t/$DCxΎ{tl{8@\B8R>oeriD:F`<"LͰqQ-qH?i, 3a؆cEH !H)ȴ(H (Hadc8d T"1貊 T"1X1踆*Q #@"Dddd0 %!!""Ai^t@?\.(?HhDP5:1޽(u$R`Ϭ'DJ)}a,$zr:if&*+0B1tkeXB#?F@(FTJ)@EAja'#GYL?!UT6= 4<d@Dbwa s&?@?5|P`D`" Rw$r ! Zn!h h^$t%B] A^ KC"A[J3:٠Ba{ `S%h1Ά{E9Р#: gBиЩAjt  8>hh$Xdx!Zh|<<]>.JiC`LDM^&^)oen uj| oX~N( !&184b,;W#=0c{8^M )f0^ bq&~(m"Ɉirb+ 12QJTBPA* B QRHm 0%(i)쀇ݏUGڱGfsS>P[/W+W-#ZCA:9@fBET>HQ# '2mpPJ")i@7!aCGo󞧳@т]i d\V@ R]0; Zh8&H$80Z ' Q6hUYДf2" ̐P,+@`B0d"Hi UJT @Pd Ex:GyA,`K ^sii-]Sba wu'!Px82'! p,GBwIJ)Q [ɑ@P4ӆD DqwpӢvSEw{Ԍ>"y!-79u9prr" ', =@+䣳$A"ʢ 8s \bƏb`q&N3ɈxAP @b!\3J Ck@P) Q/XU`R_46EVf 2F0D8yp @&B2PtP)ChI9$BVTF34px4@T"y!jppQ  `1$kh5 dj(ŀ/TQ sH@BÜ&hs 5 sh<S44S8f(U3h>ī~2r ZPA!H 0)@ZHyV `B$NB"jR#v (!0@h(D? APP '9Hx!xEV,5F0.!@F8!Pp*` [nCD$ ()ӯ"D Wc-*(b FBA'ZYiSpATpt JD(*!PqB$z.DOD{"dmE&#N]?\)2@Ր|(ϒ'(b(,CQgL_2?HD ʠ8&\C 4jf $AĜހj>%J@6s* z92 $= X)K0XF G% qB%W))פ!(qHVJBY4)sd@E@$6)k@kiD|`7FHH t4AZzGH8@h%A  ] 2.0P!fBH)aBPY <4hk)O}XP8ro` A/QEb$GJΔ$K(HpIEt17EI($`؁ɓ/亊K`@(_h>~.J8%0LңBEwaSWB H_<'E{#,pTˈ@KUHi@vS*wfۊ#;` ^耢V)"p4b҃ˁUUY !ƀ @@Ph(&q=" l!Dq)&׿hno((! V$m ``hh&aNo)(gK̄K`(88)A:?JߣgKmW8e7LttŔ]PNeVkGq40 Bϖ&%bz^Y`U1'AE $\ko:(ք MI B{aDk++-TEe1=A 1 $賈i0*!\$`@D@K~Y"!c#PJ*u&w)B:wa(<ĺ(("[ᒐ_Ĕ)" 0-A EDPX*.#ʠ수`4(>5@Y#D⇞8etyHPp$a&R@<)_hZ H ;C xwHeH>h+: :\\ bЂ5NÆ-#/ ]d)jBlI|aGЂ>DT@,ϐT[?ang{b#ةA+ ? MED%NO`RM_,Ru30+wbCqL>+"tK74HU* D`FRPz#"yn3_q)U zJr`/0_J`+3X$?T &" Q:3/d@խ  `$@slGT BR$$ pjF (Zo$hzՠ_q Z " UGj4w$3|ܸU~=MSUtlXY Rlh'ȕ9Tv5gs%owNdbKh /*8=$OPGH0o`?|NRn~e* +k ]9fu%ҪYsH kNS'[1^s+Ve0UG X@0(:zDN@`<j5B. q~9Y: Pr@ќb ? nF91 M~""M@1 y,!APF/5 j}>}J# @-EcCڐ3t5{9p`PHh3@@p@$|vF|P x!L q $ kB$PA 4n _>C]A 6GZ%^AXaad 8hy*V( PM&J? .(=A@! o\=րS`{!urgpP+PIhPӅR-786$d? m`#&J g%ʕ\%|hAt x/ɐ_ $@$ p2ʁ  0B^>}` @DO x,4A/EЀ 08!-18hhC((!K  x`x ʧ83)@ @~H4h Ѐ  Ph(V`@4((@D"rR~}@@T )R`@$    @@ p pkA8WBb#  x(;Q"qIΚZA-)]' @DX"IlVtAUE0HTL P PhÜ@ \AКrEl^g YKu\PH#AT)Ȑy4REMC0̂wח}aSRf* *yu¬I,NkkP-# C09µq!unE2;dΆU1Ѕ0}&>l?A1^0 !P ^.9Y+0A/yI2h`cI*b9t Qg=Tpy)z>=ðp S`u$A2ttm%`,h% Uj#B4P P T@R=1D:+ZkȘOnL=}|r]Sb>R ZrULvJ#H-`VֹBӗBX"lS noǨ-S&nG;+ WnM Nf34<$IYi4J '7%S#JĻ(c(Y =bI*J %#Q!()J!̐cR^50)~RW<@*2㾱0Dk9~Ң̟x4O {ax.(0SXQJRI7^†s ]Znѝ6D`%zpgC zP*\yș` ]* R?İ0С$kD]; cX~gUuhH60V8"(F/LV Q-_zy &-N*@& ( TC*+ FVk5H8%B٥46aaRzVz'(fFJ˭Xb: -]iK) fҬ @ӂiuJ(t2P&_DRp|an(2AHF -JP`2xFh-آ)CB,y. BoȮ64R89S"I +1BPuSO L XAC 2K-)uw %/9Lf|̺jAIdTAu1 x`2`J  hc+(wLy8,bcJ-& \9*ܠS @ KIPG Aʬ`iDW"TaP h1h,Ql8zAYT5OQ {C:-R-GK4" i5JԬfGp %BB0 $z"ބt8 /qIKHh &$A%(hJ4@zND}VL4X 4k@xJɎ@I*5A:@b &P`yl)8q\L !:Plr_V!G~A[UbRH@cLR( (A  BrQ(BX$BHzic }Mq@9v~Qr!W)s<)@}I)u A #C?pF46{"*N0`s`Y9"Z sFt*LP1QS?xfℨ鑁iJ]QJS!Cy_ hʒ6xΚِVN](*ր+,nfT25 N̕*mc ݒ .@a1 i'^ %!B)X,.=0'x&68 }55oDJ2\ SU SZ !`yZMo$KQ|(刁kpdHP= QFź[R#I1(3>YU.E(ԦX!'\JP )GfBővqGQx&l)PQ4ڔufG>z9}tUi"epa5o!^8J/Zl3EEIȵzE |D9&B.`]hw@~$>,Zk^KP!FX9ʀՎDQn}$l *+KV46@5H7@4E4@/@R z]h -hOx  EU ,I X+HQт>Bp)#Hr-=0!g&# y]xb$ W$ #"tB(%ԪJ: WEPUH*J-QKJBHH)D5Dq2*&P@`?:E? fX$@ ̍ P\*hĉ .zC!`U*/T!J@?P]O+Ny2i' ?-$#O+I la@AH9@J 3rzF(P9d=Β 0*5=":]!u #>l/ wbTzH@XQa N"TLI@3D0RXbuo(U!`l*^"@` Y|Wh[XW{ ,p`p<?t01O!Zp0t%AÃM (d0ʆb(ب1G0GQV$pD$< H Az!HA=H@m@DkњЀA:!M*&*&<4b %Hi!0()OEAޅt)-P$,?]V9@ ɬ"%Y+1`TYA jVc ý ~ Q WD!H݊0JX)F G_ZF\ l ?,h0<"e]EF,l$xc< &e0pGWz89 393JOl t r w!rgK&{OW@?@?A=ByrLXNš ؀@A jUG<0e .r ((0/y?ǒ4dA ($(@"8OA@rx7Ar t$耦)v( CxMF O) 4[0@"!T,0:@GH i$%p   TfgbYo4t#q,@[3 h0(W((p @60p$琹qs !4_@0.#P) jKB aAe=$P0,ŵ"D0Ʌ(0M) Z :ȡ`,Ga醡! p$6krD@]. a?#C4$F ]e0"t`,_?8ħNN"  Q,M@_qzG-)ąT2O#%X!ن(\ey87 ^PJWM1ඎ$ t %T QT%@Р6 (  .m+HT:? &:+?W?1( 'Mp;\Zaw =nQGQͳZd(XAr0>meOpA;U8~k  )BrxGK6~lxHJ(E11@tEDIpZ9T!%I_!%P ȘQڣԡ 2 #5Wf1eD xS0`@6w_`ҕ@xV(^mHH0EM-ApuX=#SLX~сZ( /6TĴ^/u H$ Et'-,K0Mf(L%Yƕp6@8Adx/DP ڐ\B#M`sp ,_tBIm BӨmodpoQYaQ/&hJx4 2LWlHa;7(2NiAxB0 1hxABPbѵxꌥ+@fUG 8pZ 1 I`0!! AU 4N.L瀔w^V[t@Y z$ dBMBEԲsw;'}{XrnmGEahG r} !" uQEǴ-&n4O*_b-UcH(דGsBS4f0#R,ՌIʈO)EZ=X2 HAH "A :Ta\zMP GEB;@h 4iWpeoz Q5tpBȏ ĄRд%Ҡ-kF%7`xJ (c UhEHD;s`S:̅2"ؼMGs<0( %ɿZfm5(H0NU[ p6qMꀹX=##dz* ` #1D!@3F@P'Ad^~/B  K ZQBEP A@Дz_d"9t1htBN(@@ۃ PUhrR/E -5ߨ R>A(H7lBW6H߁-C< O~2> JCW0x8ܵ^zC.s3XAfh0 ?I@F)`v(ZLS>@ "\_TO& ?xI*|*_* wdXE^f˱`MT}@D5bToCAК2V"Ǵ*JI@6=p BJ&0\"ha DD Ea:Xy@.\b4P hCtx`#xFb(S pSl $cPQ1XqDRo 'sJ` y<|`,X<')e"oGJ9Ƈ P>FM (@( g@PPr-G.W]@z EQ@&U+@m db!-4"+o#DI8 %ePf_!Bl0 QO?Z? :!r9gArdO@PHP H.+% )$"" LpNp&E!@b@ b(yoBO\Ipb5!A(!k!eT4N (m aj" tpΙچ4 7@(; !T >#C%G"p0+p݊jpb"Ms"T%J cW:8YDŔO V%`H $ **a&S]BYOy+OP[OG`*> A1OSjHX O 1'7BcbM!~t1PdT ` D+d!TB$6<#}lr^Db/`eJGBp7RzP%/ 4`0Fh"8?44y$ xa`>2Wr';~V W!\r +.5vJ$,Ǘ͘8U!p!еpѡܡH-V,1k %@/,  (4EbN`PxS'W+H$LFwmhB^D?H#0ra"9l["Q]6}NmEW FD!,9do!$h&CBX ~(<J8lQDŽ$xi ?@2GhGڡrBB^(0`݀K@%#Q*?>PP0>#H _ BPB?'JP?=A[e@@Ɍ1]jA]آ%XIÉ $1__ J 4{Çaa@F@rsYz/"𨭃͡j3S A[a7'&Q0K?(G˗/XL":KЈntGj'dF9JI<W:^tOR(@Y5ha GhC^h- @¢,6 Y  ХAhg8D1{VS_L`RIIC4&P&ȠQrP@Vo}Hbt1+!,g 4j#QYd1} p,; _`7РʇD (ԟH@P_K #)%! kzif~[ACQFX)QF+A4*]}Dvq Hq$Hao@`8Y5h >oFhu$0X=$UCR! tpUQ{(Py8@\ U?}i  ԛt(b1#/ ϪtȠ=Rj(v`@2 Y` uX@N<@2E14@x:2^ZЍ V#E+F" zqq% CF.F.&*gD0]bX?( (IL ,$a1Z8"чP1"ZAQ,ߔHao Y]#ʜ(, O%AzCtڅ Kȓpr"Qq8e B4(Z1hj%F`%i(Kk3Q?Վ! xDʝca(x)%uBe A੹l%9QD o!ܸ |b 2\|l7 @ A UH!JRa ȆɆ1!n4SnʐJAEZh?0ae 4w0 ',>fZ#-Q@  @io@!yu3E)_Gӱ@pʎgd?Cg o!۲ab!O䁀DB   Pa1P! dh/A 0<tBROH+GY(PU5@GF^nnn_B\ J8Q]Rb+#q BdQпN??@OM #!~Hdn /DtE  Aky X.JLR hPH2 8pTP$BCah.P裃1ZaG-I@kO{ f)@G0@%5|HJ@Y."#H0q(brȍ !! Ѩ$"Qac$i*!@3u$POףeRBTGk:=lc\!dAʗj5w@ b4D:)U 6*ҟJke,H^A Q*qԏkMdBfuaJ42\s>A~5&/˖'1zR %HhD~6x),=c!=-߷$i}Wr >BJdcQ@Dk"n!!}iBW@M E22)JP`eL@訡)5!_pݏA,]9%Dε9gX1&ʘ:fRB;,)  !R!I@PQTV  tVy1W u$myxm$4础Ej(S@F,j\Yh +C!XNȮVr%kN? o8:B2bﮥKMdJ1F+Rtus"0@@AEj PbBF*J#Ɖ/NZ~|9w( "%BPG (ZƀE. dRpA^@ y4P^R%<)JP`l&} $(+:A o$"հAH,q/0FTP< u4b e)(s5ĸGƙ#HNͧ<1{'̩zpoEWa P+ .',wV`Asi5P&d"\J˼|eE£&s?!&XcP3` ݩ)!'H!(j4V |lG) ;ĖJF/(M=[)F GLTb}icEcC0 "K RbP>V4yDN0SWFK%b1i0p9tv AB9@*Q?(U8r!x"F@AHݒ &XON4ij4@gF"(Vanj)0̸c@aJ+ ec  AN(3/2)`Uˮ_i,'ȭ*遛0\)`1Yr;)4z};C )!$!S]\s}) w}@H|sْ8YXB!_XCOv t0B4HЪv  `&>xw! |hfp\4bH$"R,++ŶxO^x[ɨ\hj~Pa†Q?#.C\-#?4Hb )?lם8I{aToHFNrZ >8jk r4}:~ue=&>dcfJ{@Jg1-@]M@Mjh .4)@M X5ZіR.B L.&!@Le9 E}/CpCcHAE OiqBQ2y*?HI8*%1,$H  JQZK1͏g X3Fl<\sF E BUN;FGX "@00i"60q(^,>H6ؓXЌWL:[3נT 0i!dI $4CI%RbBD4>yU:L $  @d٘ P` ʲ H-*BAHtIIREP @@ @C3R Aq@%TȀBl@#$ThQ0U(!` ~8 8hnAh4Ka@!soN $ʻL0,nD$hbRD8nK` Ɵ T„ r p8ZQyٙPn@$!KQQ΄P 3Ğ@UTcz"A4HjȲkx @UPˈMwJam.PvW99@d(%{+P@9 r'$(Ġ#DR)81 u) BTHPk&[3j@L mEQI*F0 _0DR*&i'@3g1p QTCD@nAT2&4ZB(B Ɇ@ȳMX"2 ) ,cb{sIVI Ae>|X T!tO@l$`ť PhT H`|/FȣNFOóvv;;;;;;;;;;vvS:uO ~=@A A PH" Wy"@$I0x#(%(}P0V ht['zwl(4@NECJ8w"f~4b(0 /?}f~C@tANY Pj0!@t&ܠ ?]=PPQ@$5:@%BUYs1( EPw]@ꀈ<P.I*T) Td(BN tδfħ'S"(q!d@0~@<!@0E ' )K'a0H$L ؀ '!b} >`x0Q1+Z?|+2MHJ wZT 5@u $G - h! e&%Eh8QJ8Xi AW^a.YCZ:-%R Jx9w!WTА0FU, jb3!@,?ؚülM:Fg)0A:_FPS oHR1Ixu|*HC$K#`%S S ‚0kӱ#LQB'NA,`bUq>Zu䀞#)!X4Aж(=J h (hw~%DJV0|$^}  @="0CH b % D3E Ғ3X9 ?.WBXO[JYb!_zu Yqr@A|Fa_TRBWW'nC60mQ>U\C>1G7hiTk+ "Z)ptS 08b paq zĮ橘Љ~@cgs':'e콗2\q&$k$ ""iNJdswM E}4GJH"V%מEF-YںFF Qs5K15 ,UXPdti f>o2He68Y.5Т f8&*ۍ@h44Qoj5FQ̀?@HX" 8-l$k&IN]$EE^\X8BW!EOGͯ Xc&0{П.IJFDZhl D6#Kgu*pg"hNmEum#@0$r WzUf렆VG` =@$٦tUU- AwCuJ(Hi!S- (Z*h)Q j RVI|4(%Jo2SNt%U@ (.]D`UO'E䜓bLI1%ϒbLILc Q|20`1:%!dQՉ1R%?n1+x<.IQ w:LƔUx׉E|)Jro, BJR,`!Al@Pp[ dbA iV(Ђs(BD'm' &Ij3`C@P !Be]?)Cŋ R @E&C Q LЖ^! `2 |jdjM&81ɀu#TWP P@$acjzɋU ,Dɍb@B1e:FTyť* i @D/I`Ig^VJ!H 7G  `ԅi ~:#Hĵ (& ?>JhC?-,^G?Ner?DDHOһEfVm[p9c@(PI#PBFG̒VE"|\xL -A-̀?mخͧo?yCy @bbG!)Ԁp.Ftֹ#?( d|+_dv.m2$)^ M )w+ s?ZSHANhih=]PG&E!74s/1"A<@M / LUP?Ŝo(Di^IN j2nlPFL4`EBAV*1PQ)Z.i$di .sD?.z@YV P FԕKbgiw :`TҖULΆA=\ F0 $!V$[?WW2;1ii">fX\!"'Jp;X2 b*20("%'͒ ]AP( J$h%v.-(@4@`T) !0@RAiQIE1ꠢU}8䘓"f\˙s.D̹"ǀpA!B J j$Nv(b PW!R*Paj(%5Aί/p8>+O@^` ĭO, ~BO!GzX< dXh^ b! `U͋99`~i!܆O3dZ2#̞ Qɂ!I chGBUv]dF1EQ:p9Nt& nZPKB\iB:P$(EtPfABdRipj5Qj4 |@DH(6Eİ$a֠/@Q-RĠ$ɈKR@xR !$cR1KMv (LgL) C;=3 up9P=P9f24T P< P Fn`PF(A~^7 P ijkCDQ:`G%1"[oۧOn=ZyV0P `!@B#Q)$T_Pq~7oRx@SwU-7i=b`~8 xINpH(}Z@_BX ea!Z‡5ea)ap4EpP P-ZOhK??$H+)PC YQhQC07NNGASp,\ $2Pd 288`0<&'c?` 0$7TL@Zv$ʢ364bX Dh~S,ިQA:Cj9K%(Iv ]> C - A'􁢭CZ G a 3P_{:׀{-7GSaC(ĖdqSnꇒQ >: Rf6 zp@8,t;=|>ᲃ&C H\S`a Ŋ@A4nZOl°&ɻz<2$V)C'ʏ@>.X9#0%"GK>֡7Q_Q[PDLBCEQT~MO" Q$ [" tA\,n2ZoY`C( PLQD P|*e0dFAq10`IB ZW1@N@TëG q<~ ;Ljp*OD  Dz$#aɹIPn4qJÒ6lF1DJ $<@!$W(CtQӦ}N;YNvv݇m;q / (~!L e!@Dٖ>RDO`1B0FI $IM}TS%&"uȇ o)_4Y Qh j?K"H*=9&0B0D2Mk^Y M>`App0B D Jip XATuF8)&u+;,VBbT*A /ɧ'u=#ǜD OڨQDŽ""|ET?'W |P($,WT41}9Gc6}'t^I9&$ė= PEs' J4AE EXdZpP-]5+A‚"zS_~tU_P_yWGf8[$?ېFNUVpؒ)'ψ@ G!PB*M= Xt"̨FIB"I/O/r: ,<#0F"@@HDKHpTXA!qu@a0 Cp= xL$@ 1x`} LϤ$+eZ:0̠V((cRR_xP)Ad e?D@2 F7&F"R H+T6)RT_l0[PNh . h!l RhKD>=;H6 4H @(MRk@5@5R!x^_YnSۧOn={t 3'8E`a$m;" x^N'" "Ax|fYl'Gwާz@@v,B1 ?y@j aA .8a(С3HaAEOj|pƦ/lbUzC#,6nJ h!&] k`&Q < I}d"͸J(A@ Vj p r!\%Ϡ U1c@LP#1M B@ F(sųZD91Hc6 "cQ *}A]`Gr.y<WԆu)邟G|!Hz"nlF7(@d/62b1pQAm@-PE+yK:`B_0L$ A@$ 0 TЦ qUUx44 yyb ~adByy0 `b\-=Z_0@ arQ?XJ7= pbp>dFhdJ@-{_D?4 1,hH/@`FA~4ѿ ͌Yl`Ў 0 (XGl4h}c`/y~B|.B/!`rC\m{=g ACRDG(Q]N p$(E'^=eΖ>XLC (d TA 1EPPJ  ,i9N@J5D[e bZdIUą - $jW@@ CHXգB4ϨlS\LpçOA4#jR',q +QwXLG^F 8GbJxa*Ta,C$CXAb!(ȎgȆ>]&0ġF(J4yh2q@@ A Q< 2h:A4_?\|HG7oT;x =tD AP#Bx#,*1?>D$\@?(Eʡjq~ii ;R5[E%ɓ^ht9p%v9j 0&$")l CM^K<ւf(K a#}`Q KG# &q?q MRU@)}feFU<㙃z=/N@H&2CXB LZn}0+d Nе-X`y'kn`i iNmو˘d5<(0X 0BnqPDMm<Ԁ:ҙwg-eA'h|53zY GYOf Z[h‰$D"/GP Ӂݭ%u×ŋ8 T_ΒE yv\} (A@൤7Q_&%aCD&,* ϔ{G / ق:It{ <1Ų?003U;䐏WȀ/1(ruT,0,HE@EBIDЪ!e;;F|ȥx-5$C}EābU@M`S/fAǩУ4PdR ٫*rd1R\xlaGU 7`2 * n9\ҽh('vC]8 C4|<(=5,,!я8ۃǫO:ҧ&:|nNdVUկuץD&ߋxCʕ hA4t0.ҫZ&3Z(dHVhvI J9 @0jPJZ0Pq. QAWG-ZPWֹ X C(GSJj,R":BqBjG(<:dT %%u#)CteKA]V-@MCw9($6h"(AVX>jҙ!/׻mg4`gJYa}kNgz^Dy8Vh K؄9y_kol$p_?q 2G$` @8F!'Np2<` S| _YZ, ONFt@I^m>@yKr5N!ˤHAtĜesI1X[~c \8C{H@JrfB%*Wo"is&@P i ]j EZR&vOCa)Ĭ^Q[J$+! BcJA T_l43O>8\\f/A%8 @>BrvxP q[0>b&P}?9,/]PLFs@[c֫F?|,a#m12q*H5 @@@gN:`>CO t0΀ v/7@] OZ +T0*VR?KL[ T> CXӘ/pz4q$4F$ Q_";H= [y$̎[}xͧ N=`3h ,x N W38ʜ d `D(H~ Ӱ ߰8Ѡ,5iYYL@R#ZEj@ ͭ0>B@zdS Q(? !*{ +\J@8g<$U*JjН 4 bCT @:l *0.5kG I)K IڔM|"|[fWZij]dd rk/` a(wb S( $__ v3 #;wlݳ}zxZtXh F5L%?'&ߏbf 1+ 4|$`Qq>Kʽ`@Dyw<@9TPVܶ@v@u DS[P  b0 4B%9 d }[[_0 8 <jAGAHև`3_`^]Ÿ0` A0)@(c33 +d!gqZ ު`˟/`~haG EG3#oݑ-Gp©FX*Q>:Nc` 7_ !E/@%)^9J,h~&Z9}T1ÑqTPȪl>"Ap`Th D%E)vV@7dH #DCpHz! C$Q@ QBB(Hj.wf>IMRYڨ@B A/EB"FF ABɈSVw/@@ LW|zm m6Ͷw;wlݳG`΀At.iwNr`"+JB7E 9$HS@_`9»cCp0|@(  )J1cAB)P]]*R-@?_WTAGQ"I䕝 (@=\| @P((8.tiIDyA09/zDt,BfATX. 2`T!K6cl6;;wd9eq% $8 Y@a ‰H Q#%Ʊ )#% &JN:tNmBk ^` FT/!Q"B/7@ RDRC(( 0  ̆DkJ~p܌@~G$ PPE*9\X(N;08N K ۂw B Rώ 19lZ2TAR K4pJ?ILZeH1|'(P )0EizX vV%PhM,d yydH6`bn\@\L@  Tg(Nƈ  Y*1YXQP@`=ffw@lY`cL !($v ѯ>ˀ,Wf Hx-PfIc`aɍ.*@ So+-Z@>QA B 0@SWhJ9hn]c0@:1re`Q%tyu-g r w*0,Ei4#I#3 +1%ϫۡ2m |q׈窸1]y\x>3@24`&dJ00AĒ*4m d '<X+ǔHr򢯎~麀sc o;*~rc,JOV@1%(zZd #9rFv}jmMlZb"Ûbl2ts `T _@B?7;, @[((%z;:>?)&^ٱ[HrݦޫsBw?cAsVl@ЉKqN~AP&H- K,Cy BD[*OP 4gӴMKjSaUV4XSd7 OA;38ydi Axڅ.4t 6\>hΧc#,s0٤fMg4JJ-@BIr`["N是|@ъ3cH'@4M%J@T+ME(Bh$UÀX= TA F5h:@(JCh 29C(-QB9 T3 +,bsE5"@Ev&J@u}+ZZ;j9VM8QA@`C8< ']Mw䓣g. `I4"Šӱ~A"tV#\#g:ޭoUHKkr@S3QD Zdba)_A"թ+_(l|>"R4<(+j@ |"L ̀5gx3SlF )$DHsX Ύ%b@ jF )dPzEBԤyL Qި@, <"@uŹ5 R'%L$(Aq(y&(Í JjOE 7$؛g`pƣ#S%KU,tkB)Bj R_,|TT;h23dLnnd$=\E g$Z RTHxODRRQ#F @Q- !5bBCni9"4B[SqaB(>YANЇ-jrG , R_DT%T_|;ڇa}mh0XdAl^D'V.*jm]k톘%"\ $Dj}mu4(s-W(!NI(@_ausF.D+4@"Pi A$Q!`R,8YhKzvRh|+iG:b1ZVIL 7- S!ŴtiI\N}$j)Q4 @P!!AH$SX@!UR:|HVbꤊJ`@C8}SOu]dxpsci* I0ʢ apHex JUSb> R4Vh"#@% PGhij6EI 6*d3D H09gձs 5G(bQӪm񣅑J(wʐa#* $:nx^n m @lH̞R1آMʻ9JʩNZ/p Ⱥ$F Z RaZG,!9U(Bp UH2U6b!E+2.wVHHK!Խ "`cOx #f@!I("\$\A ҴP>=P -P#|$C?"ڿr %CS:5{)"jaE'gA(JHTh=Ia \VN"SZ[/!P@(@ Ddn,7I$Y.i- +rdBe@O"R)ƾXǍhuS5əPt7y :3 vڗyCؐ|C]n"ʠ)(=@I(q ')`$J‹+$5 ' t`4 (Qԉ]'ħ]4V`9R"#*ZE2o |Al *y? yvF@(OC $ # ްy΀H 4Ėt=>$ýBlP44A=B A?,zm% 1!K~^?,۴Ʈ<g !Ä!K̅C+`J?@TPf8}i7OPS?(!8 )}# @ /\f ǺD$jw &m =0 d2 (z⅔ @"3F y:!2%)@(Q( " 0I  *\>L B-$)@":}GF t ";4P'#b@gqL,=kjy!6XAIcf8.0Bpf}n ` C퀈ǺAv4)g}j2[ѳ) 9K?V`s9aH8؞ ]gŚtWG CAHl,0(1薒(FR7M/+Z/=&%5lFZ5+$\vL@˭µXi_?#UAd@xxM?(Ap>`5@fr{SÂ˞$^Dp zxR||䌋OZ$($0X8 ;^OR Ƙ ET? M_JT !HQRNHhDZPVEN?Z{:GzqPH9,I&Dc 2@ ;Zz{R_b!XDH\_帏vu,o@d 6ހr31a!TOabC$#d送!>(xjz|0:"tX҃)*0 G"i`HGDIN cK`$x1|jb+e)Bp_B>EAAR4Tq(AZH"qJ 4@)g (} (Pk(?U ce P%hQrSAL. @0AI 8 ^Z!xncߟ  ;on 4'^<B@x,*0 s!PZwԕAY-lV@Q3=T4> O ˅aIY 0QC Cp YT pUipPkKlXWi۸p>Q"5\blŒyQ0B j^2HT,A`{7ZԠ|x/)] P/ YTyu-6a$C rD$= ` !(\πA{@*(C@+JH, X+J-h(z4P}A |9I!*$xЕ'E47aN9UA)`e{ɁÙB#w1, TCbrAOP}""4_0ut%,&c@s "8hCttX $z^!MH<@:Xč06R"N(GM$@QAOM:MBw<@mAd(rH|Y!@ z"tC)Cל!ey bbIU%*10 (\ T#?- 3PǗ  <@9^BO<EmD?p`Dsb ; !yZNL  *a eFzQb1@? PX&tfР2+ F 9==p7B vJcU Pm A0&Ry0?h2$ w ># ]:GiyB*~vqO!B? {͏x#( ج fU +aOth4-gIFL?.`G W 0U PBi@Q?K"cՐ'n"Ys<"sF+|\+Wwv2?j@+IyP$5g *@#;"2Ec€#K@Wc##^K}⠎~ J'Zx s@%@ z< (^6p zBH.(Pt P@s(dɤLCH΄-Z@Q`J|#BqHMB}9w(P]N^Ǣ( XC"F'Q!PAgy-UFٹB0 nJ#K)|LԘ,_@5RuƘ+1ql\JA6g=m؉T1",Hb@Bt~NPA/!"HLL@$D8D6A T@=@h +$5Hj+A -DǓGHjj5@Q'p9G\Hb A8hZ7B MW~$SQ}p@R)!mE߷+< ˀ"E#G1 tW9 0s#@%FaKH8 qDh-"ar$(nzHPZ`_K.FD H3rdBzrl@LVdwL<H&A &"aFdQrI>Uо~`գ e ZR0PLyƒ) 3@ zDO$B$I$៝A?E#@PJ6MO!ܚmJ .  KLc ~FG b\IJ Ze?K[j1x @ \*dcv`?@h€¨ᰆss0ŀ@Q iG~1Q(h) cqcGԎ$b!~(A5Lm8@i !)ñr  t?@./@t\`Jev/!sho ­B$%ЦP*ų_`,PVӾ[)aZH4X@Z `q 7HGxPm q_61l яhF(la}ckhl7K4>EW 5!x8z4mbxM 5E+! F'#Cj!!!!0PQ  (aa/7߄aKxSc)3a~SȌS̸@ b{X#}~O@i3z@V)FR֘i!tM=:Q G1tCH``4`%O:-v Hk3O*?$@B~H44 sP)D~C"P(c`ؠ2#,0F\%(fvx݉0km*"Q?ϓim0s>U:H/\LA 2 7~f7 8L@ߐ !<^B #t  +;XQy"NXZ(4Y;<P$p<ѪVj6!1oq@" 0Rb/ |b/6} O" % p 2ȏ}BSx*(0ZS9@`B-,+e\@;zp&nZЎB0# NXjAB¨-CCRzѭ ,y Y1R TD r hHP +6)O^IUy܍@(Q,ς(*00Z h4P7(8`$.&AHL Y3ЋGa~C J& m?)˄!T"1yk"k:q)#BҤ0`p+F`BX1=&!Hej  0xyL1E*IH&2I̒DTQ0?%QPJáb= EG]>> > N+P } {ާU" IQ5"+|P7X)k$h̅CAxXK„Pq'd<ՌR|{wSܨ4tpC:TT Dտ7ʺ WS\ 3p@hoтfT ;XzaDF;Vl`0e W Ѕƞ%IY^dYhSh4T"J*XU*B(.M$(hY HXM!#AFC(hƌ~p*n(Ez.Ұ0A׮A[" %<MHH~1}`h:z8 !z$LJWR@Mn G.zZ\J@ Z=PGZIK@ HA4ABbLF_o>MS% lrwUA%1B ?r~ 1Cp^Sɉ&z2H@Aϲ}o EwNp5+QQA#XIQ-/ Hvˆ@HAp&"yihLր%7ʀT?F 44Q[ LD5tBX`S-Ԫ(HBP5>H=+0 @UD?C q+PADFF>9b |(@xXTiT~ЌL:5/:dޱ rDFN0Ę04 FRO .rK"̑"Im߆ժcTbB*$JV~M uY 'VD*2T,&CXbN 26y\"Z (S2g YwU4x,(- CE"xnEE62gA&KJ228kPa&@VR`T ӇK(,UO ԋ:8>RVf S~4*/D 41(M2_MAL3?#G8c@-iJ+-_r8Cɴ % t &4ǖ!y wU\K|%$B/#ȡp($haQ!YKrrBQ U_4 @`E eg@ d %R0X4v$$CPN=xX yc)EGhPH$2TJ$I4@ )T9"r(q  :AH4@He8 PRR@3S) Q(#E! PG, ("C x; Pϑ,@@mBzpGw@ػqK7.1,1бh "9V@0)"/`@Oe  p~jQ2CGˆhq@5(TqZ/4 J0փl?FH!C 8v3*. Zuߤ6A~RzPE_*}$;1HB7:xlgƀ 6@ci(ųĉ \ &H&2^:^8rI )pUp?/\ 'Iih0󁯨wtjPCCQ2%!!?efbR`*Ԛ""j_bʄ2 ZaS?4+L 0 c#YJ 4&A6)vQ8g'eYvF|-H8CǺ~0@t9GEJDiǠ&78F}Ҡ G `Bl#BހQGi#D#Nq J#bgjqJP 6^CB* mX;2@5@d4b$Sހӿ̉ o`Q:aQq A91$[3["َH ŤQV?0`I h8 J%~Y(&$&7}hCZUP*?h7‘ƺ! Cx$#t"y.AEX:&n$8V1#5`F⹡@m9A7+@A) ̀<id">69S`&2օƦt&PE,B)(RB^4P^TUnO5ͱ"cɳ&ҐAS:J:FnNP† Xd@ (OIY WP_QMAjTBv UJU#=p98=ގ‰ `n!hܛB] _`;cgPWQG$0@@@E*ǔe)"4RyybŋThti@]%)d#*@((80$PH )IU]\A$*Nky,@=d"N W_?S X :D HO[Ǜ>0 qp\hLbCŃhI2*y ܰ,A`$ #@Ag] *<I-x0DrK!<""+.@p!;NdT @h,JΩKyYS@8V2R?P8IPCV5fPCU]Q[|+?lN?iȧ4'8` S?݄`cvNLQ 0q EgNF\JJ G0v#IE;QLJ( pWq; #| hxBTFD 5aO˜;(bPDBMb %r* ir_s: aK.VN")Pj14B$*HQЛPJU@6J"A l[()@(*::P$@_WBQ/vłn]h;G GFV P&x̙\1?)i  HI1GQ!]JPZ@5/ABl ^OBL/!.s^p,Fj=! {9(@!"ňJ)BnRR`2KCYVP{Eh#-cڢX(9b0>-A ?N!`o~ v偯R1QBKAV%WbTR1bxQ' X#!{,DDT1#šL @]EVo!U7&\~%&r6< )1v JC JZ#w䬠 !ι!+a/y^svohB5ED]9~%Q*2̕Qk30U/P$ V b_}VR`D? W%:,aETrZ" S Ta VJ 1E$BE"  1c@0DQQ(Q&AgY@ehb JgӘBOJ0R֤BQaD (1$a84V  :$H1"A`z,GP(}BxnIb7ؕ *X1S-8Ua7 sr+QJئLh냸ҁ6"5 pE֔$ Z(Êr-C=JDcD-!]0!ij^,+s]AcjGBD&ƏP/E}** b$dr9? ~c U V#%⨧ (q#G HYL-yz_OY,#:b{MP傺ȌF@| 0KH vFԆ0#uPRVhduGQ )UC]C{4BA"ʌ4(bX>L)"]9I‡*v<HeATbTx $QJ1Ϝ+˦F+X⥋^|ʀQ|pv=*eXqk ¢^0I/ԬH8 @"4q@щ'FJo|2"JJdJ[oKH^ыnW( "."iE;_($]-RrP@eT5 24C#P Mg@]HdW ԖS\U,y+h-d~0 @5U[PA h #CQ4H@DOi`B娇{$D$-*< .Vؘ|J ?m]f>:Eo/uD+u%po1zR(qt^C,`1 SHp&~l SJ*12hIr_N?CmQ@(­#eUۺ0̞S`9נ TWV4s]8LۣKpNXXw1$ s_lq(ӮɈ#N`gN+r88‚I4ߜJq!WDR;ƔaH@W|a[TbGOš`o(,Bkp,3zeaQl H~cx$3 oUɤa ~I9g*Q w}a8`}'^*Hf@ }>P< a6"&D5. Y ňAՊ!8IUAX4="bS~Y~; FD($U#̆(AJb UJ(pM`UH'EKPAzXc ,[?s 9 STj)"b֍\0iRтC 9H,e(@2 zLퟞpL`TlE=i6*%a0d aX00*˃Cf dO#%Xpc 6M**V}_MiirAQQu01(`sCqD$r0 !Z-AL`hh@F2+R8zxu_^$C|?$ 5I2˔K#!iK2g$ CQp&B @\PTWb'ʈ (- $Gz! =` 2pc?L[z ȑ~ 0x##ɐ|x9p6@,WXt藈 To :=? H$= N PqL@K\VEh$1eF "5(A "8;HIa0(״X]vp"Az=@he/d_Cl\R8e -paO(CR ̘ s'px : W$|?S/a  ^Â)!@+0h0ʰSkEBjB? }~y|*! V" E" EBkBEr(gN!SSyKG4Fn%8d_Pj ̈ yPEr4K3hKwMI?Ѹ5'p7 [9sP]9˷ |Ȱ`W[>Q@B*@+>c ju,6x `,@2k$iOHz )U )6G0õ'Vm#|? 7/-ST.Ly! &Y!f>!,9ڕ?Šƛ(ߍ0TH5A4ap G1,w_8yh'nE,`TuIQ|0d0|Pgǀ' 1R)E HH UP &> " yNF `!$RHE*|n!!!!!Ogm!Z \UA & Gʨ$ht"J+9m>X k 1[LSO@( +P"u&$FJ[`@YL,m#  Y`1r9YpwLZ>sAk3C,2`$i  @ t)H5">VN^BDAAA1 z AH P tqf/G:tT=/~n A]rY VI !Ei D.˿B ߏ5@$S7av@I1.z9/T\p, r'qsT))MDq j"~H0{$629wf$l @+`3 ,|XK,!G1G`1siCCP.TChCJ} 45uqꖐ3Y-$ X a+y AHd $|zzgaJ Fʪ]BA'd< Hjd9A fHB"` A ɥw(@XSǢϒ+FD Dt]H$B>X( 'XO@ PD@> =C1,>g ^\ @4F%<ҘԬDFbB餰P"0P!pShJr!RƸu]X0! q @ťN?hqR? ,bK<$P `X@aL` "HZh~ŵ8x8aL | D8 \ F/  "D3Fxe$UꨔhNd (: 9it(@v@*GQR_AIeN,ד J"fx$:!R@g K|0CAA_ P` FupBWA R U0H|GHQ% +'Sۄ=G&@?6K;o&ri@ص1_xQ@\Ɵ(7SX#0l} B 0!H,8ARޟBdHYpZa‚(\ػ0 @w(?$ /f6Ux @' C< D8B\5 W,x( z&'  R@0R SQLL3l2LOz CAĥ (dR?4s֡I] EhA„3"w;ŠdqR,b0WJZ(o =i#6exFXB k4 +'D1(n~'5D$X5pGtH& [ Fb@" 918B#P/?O!styW#xcP!gUf{-0ä"$G(DLDt.Z@¯_gȋQJ#HVy D&ށ8i2bάgM' 4zBz]M& $hpe~&GALiD)xR6@} 8 H1r \$IvQm;*zC 9 0TB( @$ dc FC!XEz^:ـNG-kgL23C*M 쎏o7Ԑ\h ׿ YVu!\@`X !O;dIAYCC@U'܋ (Ae4RB42*@1PP84!ļ.Q1Vz82$R  ~%TE! -U@HZFӗu3ZBA6XM,CKR/Bh4AM_0aZBz ƨά9(:MQLVs%hЖFX}芇 t!)dCMyt A *|X7cU?*VU@nV^j(h;taU?‡ٰ! F]0^V8 6!bݤE? )H<(NfH` plB=!"?"" ܀/ILh8v JH05 - ly(BĠ` e(@`*$W`)v mMZ% ŒGSG b@.OhMO f] -*썢 $jl sGh ނ\w=]@4@`|C/ G)AL? >_X3h4C: h %L0( Q713vupTUD3j؂!kb "ǐ(k7S *[XA'5K<289;3)Wα MF.<!KZ*ҳsX $V$*Q*ViD3(2CDrh $BKA5 }<_)^ b+CЁuU!ږFj yc1%n=$U%D;ZD4!4D(eOa@bFEȔ`l& mg^!TUE#3P-~сtAypAJUNuG\? * Z2Qw0S[BPq20l\cZ%b$(B AB%"le GP9 GZd/(J!Iq*KT!^yu9+O5SS.|*;_@шU R&TA 1Zc$!ǜb0 [$Q+W $A(9JB (.*!J8 1DL8,y 4 6Q!2ȎDK􍆔(BBgI q%(X"3M!#Q `Fp@l(4+ B@h`)ԃHE HxA tl%䌡ePDc)JЌ҈H4UAlv0TVrkG[!|I@Yܤ傴iQv=.#TaDDvjMjR1@K* d!J` X(VJo!60%QL*;3d\i'dNM-UBP&*# &TFP_CaC W CU"()?6=1=\ʱFQI2lӝ&Zcϋ;Pч$HsUT~4 !(Py +4Y-?BET, yiP骴FPa3Z%(B}꾑XaJڕkl2V It~^|9$Q!O`H>3@P"AG0(A*j٦ b6A#L5 AՀdT)GTG8j!&aF@2xX@ʤ :B JT)A`ht|T $b@"X,,$|8 **,%HB S( Sa>O _* h%l*??bO1$ : #/t 5_~B C`f/FH-D#2HEX}o?lS0? (jд$b [A# FT^D_@Q:5$CB©J8]𩀬M$MAE xQÒ2G>O< ,d4 $nV;bd4G8',GNJހ@Ë ^@Oo;179v#\)$$ mGa40WPp0Qwq_ Q.\y* %VX`l> \0`#ДN^i|r_,9V?'i@21eTicF#E(wQ Ezғs33 "!UuR#?@@`~@^#l CUAR *=$M(Aj/#Gt%90@D2(JT 8cTZ4 B=˦Ut;Y!x\QW.CVnTkSc Z N@f$؀ 8,H8TPtRcX(! ŐñRdαQ<)/.W)r $/U;B"nDU (2 ,G#%R!! @+:~@0N!G51pQŒ(A" U]c`1O98}@ `yHZ5JAn8 B(V#$2 !vQ @DXDdz@DJ{)S%c)@rp)<+ʵoג Tu tVL:WtT j-1x  "b;0R0Q b(`Ӕ"z  {CEXI),R?|ULBaBF+LxgG"P`8i-(K|ٔUH_o36(}6FX D> ":Rz 'jh@iHǤPR]OEt sy$6bXb *C&5 $2Ux&tQRRrnAhRY!$p\A%AtXqv`c-5(zd,:O J hH?@* &#Aĩ-4q:!c4bJCRrzWtHV!"ԩ!{*($fA̕.RV:@ %A@QJ! dX;01 S|Xpv/З[k/.c`8qINGS,dZ2^yDɧ^j9clr@( $BD`i+B% pr @t4 o4S%beykx_q e. CG\0 D@8Pm z $  p&/[)1(H @QX/GHKD: C.-TRD! &D2(9Qa4#$4R`lLBM]$"B/ׯh!ICR.lĵ8^Uz9pqɔM Q"2,ZHʢg-ZlF^ ::nNYWI7}o`X!iZtP8.t! EP<@٠DAC(T UIH?A-Zb4<ʡCa&)vH˽nPM=Cnl-r9v0><ApD@E 0$@DRVegh X CNXDxn)f#"R .\$*axD 89ژ o>*UhYv$ 3Ì`]U0$ GNi*,R⃐W)JXPV H} :ꪔקŦ!]&h!:bB#STo7‰ n bk˚HT$3D T pQbTe GHţDL`D "!DaűL Kh`) @M4IQR HE,$PzH $q@ R 2(fáT (FhN Zu箜!r/ 6z<]hzRs ,̆DFOX`lg`2o(HC QkXkH6PdT@LB^ LGU%3K+N ^lS0U0]h(=q6@h!PѤ,(QTB$Ic@E -(@46ȝ .@ @68">a! @tX"gԛH bEA*P2IEADL+83$i @s24P8!XFfu_O]zu:zJrjP4V<<ބt_.$OG 5WX*4\WTU`h1Zf”5jCٴ3CHRyj܇u P/iDf˭qͫz Pw1eM%R/%vKfUt"r|Q h&p!s@!@4C0F!LL١爃l̼hlB!# ☂ D|'A>@o  B!X/j@5%FJ"S;%"4gdb`z)A`{),xEg`MBдV.@BhUQ,Hi@4q#5en@B/  @A?>hx-D단ҏ'FUA!K0r$'RT#aWW؇d D!I@oHt̂G!pK8A-b"MDGzEʿ04Sz&(L=@JVq R%^bH'hSV h (T2$@6 !Dh\*Q %aR4R0B\@JfEV!"qhĂqNх ui/@EŊ$4ՏTh{ge,dH.Gx#1R)R,G5 Iy+E5s(kb9։stw=l%K5 ի[@G6l:(h qA@FJBzQ1"pHLrCFLD:r% aHkLe$W>`6SBxGxY_R\& `)`@'QKMcAZF[y&]ɻ7)i SBjV(v-+XK[ֶJՁȯ1( fA@Pjj : >R*쿢" R5Ȼ:8B|A+x:#gQ!_˶Q(]QU/ԋ$'ΓPpj%kݣn i%h ŢZ|8 z=F[ MEEg-B9GpX@QK|kXK?i-H*4 H( HE   JBj[@4,"EXȭfQ"B4Tu7!|Th"$ F'.:~ RvPl W?}U':.ԟG˯CgѸ2uxpiٰ)@Q- pb71P! ء=c0(wGpǟ ? !"#IX)Й-5vH6.Nxk Q6bRR1x1ꕉ~EuB@C C4 WAY{_$S4` (Ռ: Wzބ [BV)gdaZc2K[ ōAk5pejҥT$hF'ձc%ȹyd%P]*!ꔨ{DžQ-P0M2 I(3r(0Wp61-y9ʻ]pE/{> aD_f.=0i=7i˓k=')~&襡v]"HJ B^iR+B9DBH'(mQvdB(JiLst)s47`,yp%1EYQE=V#5.D`(ʢ\V^K AХX9DV=^A `B<hf;{FA7 d# !bfkX!bQӰY"A$(‚X!L4j*V4@P!HA$IPb $BAdiĊw.SCXhI %h!YQc0(Qd1嫑!nÆFƄƣ@i|j$*e$F$ QceMPO$V@h~($~;xavĐ/fBGQ"g3C؛& H<C8N 8 ,@ @8Ro` 8үcHWͤ<0sV|f(4.&0h@58`IA G!u0= E (2 Aai :PZ~]5߈5^`qgZT-p5Y1Rח-SFKN/}9 >)zr `=ӁM0fw t B&!@!P`o1mPaW bq* , %LD"%lK`,ߜ@" Z@ ( %J"UsUDPoV1*™SHQ_A&ϥHc f P~8dvs1_kOislAif `N J@T҅%銟 )2n&/HRz$Șcm"z44hbd .* b*K r!Sg $#$uKʲ\Ir K⑎5ƛ`F1'^q8,(D%A`iI ST Py -@RZ/W&3 RH%@LT!M:QZ:$&(bB A@5q$I7UͼDYckQK =7 "B<D$k+"+W5ﰿW#raC?S1,4(%rg BSB;lC@e^i>&yn`23@vA\Zgr QV7@@?Br-YJ 2 } (NU@ h]6]>@0H:-MFLe- GJ@^~F@A 8d$=&N-?JLD!D`/@hqvR@8?*`5}jcH($v 5SQ E*>H@vAbp'| aABpnA%B(-j (%!@YWB P@Pm*I@["Z`}L ''l@4P|EIvRPp#DIg95R4 0(.U==E8J?P~9 4Kǥ]3 a!$:śzJ_$nC ӰB rd=J`7  FADA`aF#BZ#,kt*Ki|@k.qFh% CZ$upi\m4 bAG}F$t @6L5|!-ڿ#5撃w^I}jR!.TWdrna8K)*6X/ ĢGDXTb#d@B NXS q"zBaQ8zɤ(@)Hyā2!036 d+A@]9!H":cV݃U]s4+ 1 ǐ-8Ât@Ll)o?!QNL]cW q0)q4yyr n4%N*俯o@Mm =4;ZlQK-k[Y fZGhqb0C@$ 2(ș> /t0 K 0`I*`gKiTE t0y8BE9*8CL4:IXH@Ҍ  " zH3Jh}ر8sTFJ_* m[YHAHAeAD!HN@Щ h̀ W:+F)H`;UG221@JR1JKkm7Pf|.t́5 |M Жztp9@h&4(F}F(V@SA4N.&4SRIƃ$GB tH!A%B4,JRmX@V,X*0:@4f T BBzQ -@d@UAdn"BR@ZD6LQ@DjD*DJ@X= O"CcI2`5P\AOAy35P &-(J:@ JC*`$xP'Z7?PA@͟S@PYAD(˽6@;D6(OA Hjȁ @$@LZ 9HH;XFg y!2 L FH0Kv0)/ .(15T5G X{0?60 A;,bA .G| j'@ &j ©:@ (6}OhH @ q *K]Hӽd2_H#XU$whۑr 6 W@qVtX0G$DEAJ;bZD(B JF0  Tp %k݄W I2FnQ\AG D4k=!d|CuC#Aq8AkI(;9$&Ld،Nu#Rb~HYW"+&@W3D$$A.4 V" l1 q;jq V&39#fF$+{T8Ŋ R1/)yÊBT"TR8; W=rZ2GXb(5kWaiDVF$*;ƊƊV.*p!GPp&>¡(@ҘHbG(.o4(0"}cF!Р;L|),H! NKxd CyS@\ǠJgP CA$.-t"߯$e6 be#a*2IZnKfTDqȦxjÆ^-Y.% )IhGD"X*8G bXE!*btwVMc̱|X.$av" ;Ic^[䱚2: U%d J$cAi,Y*UX#n?-ң8E(QM7:_ؚ*Ğc4\qt̕XZ8\#F 3(Ni-ax Q+FPEֆ1t4N/K &vc? 2Q\쉄2@T!djFH p yvA`"S+ȆR}JNzBH0@ h䂃A vfb4x~Fq 2z4U '0!ȡ.%ƒ+ABժ@\h# ,?{˓7%g)HKf#H1,#mׅ4FC!Y- f߆I&"eC1@@a 1ɐ!baC5X3h}xFd# scp\AR#@ zUO w]܄j?\4v'9A2&/ѢE& f9]r#ʻ m $rZ5"m (a(b dPx<#Y:y#IU*c ") Q4k hr44 QH,ye4\/ @LV`(,Q M!\BdJPPAխKr 8w@HRCHc% Ak1ubpa`Nc5Ueu;JgV&hΚBHt$B)PMqG*00QJ(H1(@iDAB)K򎘬V(2WKraZCiU4B+*Ie br%$l3 2D) .v] lU h e4k4Y@0,A厂_@HSJP5̾]ӤE`B "UJ1kM  jhREDXTQ1BcZ$PBϐk9czR4ϐSjYXH,I!2#S88DF K0%A+BFJ\y`$CbA &P@xT-/]BI%5 #4#TH,ADDTє.jo٢P&J`(qYp6L"t|}aPdt#J  ERU"uqRc;\Pŋ1-^tcJP*4Pfj F9բQC(ҖV0Frg^~GhTBH ;GWhE 1` ](I (] o}DۄĢ$Wz>RD7#X8"O9hf7܇7R$bQ _ (8`()xP F Py(!1@hZB+X  )]""Sv+A(^?׮"y\$yy $|#&""B1mtݖB ji.1kJ.H'Lϛ0D@8#lA UB)qT@x @!PРGnXd:1?(q]S8Caok Z+jc!b@rE@e&-R*M :H4&v0DH@7!\n tPjtE#XHŪ:ӻ;v|wrDtj|6烋5ԫreDNS@lL褪  E? PЫRh,1@M)2B@4Ji %&FQlv)Q M6x ֘o'<#ջ搢:\%+E6%-QD~g r;Tb9ʫaAqO#1*Un%;K"U& 2P4^nXɁQ`  E & i6E:+/,tt:: BE7/HxgpBsjyqYܘL;mVÔCL(@91G@?KVmntt  m 5S3SP`Kju Ÿ@ H J}h* GHC/.F 4{(,IHKɩa^C^֕ϖ+G+ B W_B 1F(ٝbyW D c=]M0a9"+N N,EFY9iHR?g 2| *ФUu#'`r`<D<@5BAp/@b\[ d7usxt-nPsh`6ߧ]>A􅨜 H" 2b""Ł2e$Ġm-UK)1DQR3a5-jDHWngZnj!V#p#D)C/:_VҦeǓq1* (B28C AdtH^UPeRq+LAtd) FS-XZ<9.4Z'0Mӫ 0 Ab(*S jƎ@EaU$@ ꔡRoS`t"PJ2@(: CSIHvE 1A,Kv5 -Av-U\ *hUuu< q%(AC(-CСar1BgC1A(>@ACEqӒa qrAJͧ]Z8Sġ(`:t  @ hĜLAp!uZ$_0HPpd(%/jR@sqS1$D+HvFh1MMV(@8\QnƊW9QG:?X0  @ D>3G308A䴯E|P((%AR朣x&7 9rqST%G]*K$;zQ$ nA"EQR, QP6@kAq'py"!ŽA! ]:&l,.@CJzT<&DJ(P@(t%!!p~% 4B~H5C(a@VS[ _ BAIUF |s`eNY(,AYܢ˜NTR? lC+1R  ,BΕb! ej[ZՂHB({MC^ hv.VeAT'ٓts]S3KDfjX  ( rׯ_UI"D կ ,xoP{lqMd7|i@rgI"܎~׫*wkB:1hXij3: ?<UTœ @J-(A LZ&U!m-5+hwZCB1f w|/H\b;H. )Pp qCI%#Jc!ZR%E*tB_8p(ICLda@6KR4bX2JB:P+MV:HVJ` $@BsHZ05W7R% GVxis8!,G$$]=.1"`>I  i,i,AXKF ԉI``j@h4AHYbaVaJ<̑F@$_4@qopq4+IΨN{qBĂ 05pM7LW3~FsF(HľqXQ#ԴC9%qꊬaňl!gJBVKT1F}LqР x>:!#_XZH!_5@#?7@̓ [lexޠ]@Bh(e-/U8ԌORI( (Z:"7UbAZ@ 5@i]q#+ !nk9NCoCU0A`DŽEs+&D*:Ox31tVWB (WHPXhQY+C.pHK#߀,15_k:,%~_ 2N% VqBlT[r jB\ ZT!POK-mAWxHe"!Py EdơG4 L\R@ ?6P<h/LFMT r $=]vmʿӂ`<6O,A$A X@b4B%|S3D; g86 E PIj J>#CWI+ 1S@.a(,?d>U~OѼk40 (07)XH!*^@z&L!K7(^PfꁠR[8T)cD+3,$Q)!ֿȐK*:EHA!C*Q* nsbLr*AT&_ 2@nNrbBK%0_̫zz",=-*sq3<2S™"ÁӨiWk2i >oPmG ;C ?{ P`PFל, 5.M\ȝI-؋E[ϊ 5Oa  ʣ,\PÄ(H]B  _$@FBvF,qmH ,w@N(B1PI]Pvv!} :A$D݁(@ J`q(- H X J@q*2JUS%LT xdg!B AA I!: !^H\9wP˒-?1H;GѣbG6"/y !u(x(\W K_pqBwgR@jewAƔ,N,%U;@fѐ(EE(a`F\ hfD(OC/a}~hy¥K*3:2bQ L8CՒKGi+ G B]/hg")N)!h+[HdAaV- LH AĖ |1B:_rU[p-(xdZ`d~Rd|AHJ,cO(4 _i<K2{|&!KG_BsЩRKP,Hur bLA pд0Y-$ =@=pPQ\jZX2? 9 1 R'O@QJx2%7[uJAftqDE5'PL%kU"{w N\(hgvXjhBe$4~<0!o rQ OQYn $zHpRd $yr)% B J:B>T399gPCVЂ-  K|K`Lh@P0VY9k# If@ @R+ r^HfW\),NPv+ "c F;F|tɜP. 53šasT$dE$bk`Cr!PA aJ|%KVzT9+#E+A]h6U)p8b;H;lHNB+Ph dbgeⴄ]|F!}81dA0> /B贚9ljPay@-ez$ IFZҢzd[ 3sT$ʷdU,QM]XJEV<OH,"L^i@5V$8<4TdR(( Mq^H(JDA(y 7hA@A UJ Pb  PH Ti(*2$[UV !_.+D/h+4Q5.w ='_Zr/<"#gF<\iUs1+HM9Acя==lñ(MVPgjV)p}bs|@>  (k[KGy'E&J)d`[I-PgEIxJd,JCG/kkߝME*3U5 }/ OP^V((6L4!@r:THaEPhm 4cBZEe0ĭ(=PCA@:_MA0h5ttւ+RQ+ڵTpGxT|N C DACAxP6~*ј"|XpEx8R'!c9Ad"wDڰooojʆI#h@a)zy" ("dG$y^#ULzjJ2oB 3#M 0ބQ. AA;JHf!zag*TM!grHHT>zN$B8A*荬 "!TPE%$4}(@#Nl +K}JDɹ]_ 09O °"`Dr V{":W†do )>zDO@v]= Z]i", UN)hqY"!/bbM1LQ܁-1 "2&R"05BA^(\R Bݿ{e7 v(fRd)>$ WzHM+fR"0,5)gEY`DIEOX㲌< 80R zN>q%q i,?G c_ e7e_Q\xU3D";׮P .t)!STsrD%Bc(aiAn$% rBP p"1aI:5/)XƣP,U]j,JnӤYQ}/R H9F<!,"\1 ҍkh 0*< khx`S1DM jП/< "!o Q3$ Ogg#H- G 8WL JJD&Է򎽂gJ 2RWQX``)G"b+m춈E &48@d`L:GQLmj[\~0YǑm@p)J"wئ̺ǐ1ȄbJ:yjgPPVգEwI-(J}4+ʝNLRHD%)E/s  *ϳj5*d] hDd1, %w".pW $Jj0 @i тF" ƯҚ)'dy Ў?LT!~:$hJB4bЎ@j*sadV0*DR刅Hb`t^}X'@gExwwt45w*@I52T0#.(Ѧ` GJ="r-.&EC~FjJ@ 1ZP9bRC#R0͋HWDӒbbƚ:4)V QQZ(]t)5i7!Tbxtlx T.jrPǓ[, (g&[$2PҌхDsdhhU?ɐ8*q>Fux]x% \##p.MMO Q*܇deA"Sn)\Y̼26%Ghf =\щCO+(#̐NÙQ)>iV(Un|A6RMbhn>[^*,!&bW4 1^8#za1B 3`pV-* `\s}B9dfL#1xZ ga !'(O"46"m|/@:JAA7Jd'b!^Z@0R$@Xg  -YY ~ZEiV<4 5 'UZH!Bi*y0kkCʇXe5wHȌf.,|+ơ+|-2P̋&%H"Kk2pfkp 17wZ @` ):D% XRDְ(JM)Lf38fxgN8+JD%(ybDc¶BҪjMP ),$e0S`%А&m-7$<{jz9-bY-YR0is7˘+ h50YZ?Y"T-~ _:_7#fb  IxG"K(' !`e(E'JFOv Nf}CE $PKQPjzщa $ $bD8qkG?(@@MYx&`c0 ߨ9wC'yIp֠+K L? F4 BY Y $_2H rp?‚zC@#8@@D @9N” '`c@P -XAd$vUAj~F$!nw.r, Hw:L#_Yf!;f!(h$$ QphPe)"4V !&}ɂJ.rZI0'j*JR m+G!֊ R(\>QLiE܀HI.  L 5bq Q*̌~))$S ~h= _&@(wdX0T1H R Y@cD@M'+J @]@TM:P`tPaH2DIeQNPЊWʱ^<Q`S[JWPX#j$-~ q&D(a$q li0 b #ǰ EkVP:zHaGP 1P{YlwhEW4 = AܐJ@CE_Lb q M4 r`MSJ7,@ C4P 44k GRX,1^  b H$% TŌݫ6~'嬒X U,'UJp> EB4#acc$Pm PA*ІMj!BH[\BZ#hz mD%CE rSs Hge0+H~b=_ޑkqY TU;<`_zD9$QAOJX"NPyAp*DG͈[F+`D/Mz1m}fAD p[KU _%1EKgKL$ytJbhZcO) ;HǠc~'.YI;B0ΎVp*+ZtɪqDEtѢ;@c @]HZ+,jPP7L("PhG&;$,tz` !Q:IvxIy@j09U R R h%A R Ph BFH6 3B4C֎,6 Qj(j3IumkF\O*Lb.B>*wuHYMJU?i )Ef$2L$j1 dcH\ $KxYi9 HɦfS ?ՠh)Ҕ;+  ӫSBDLQ>DO" \qH 7D Ăj]9wvBh}B`B.F>E FWț $)JdQ ?ԥ@<8T7WԿ'Z݉̚Jdk%2IjL"H۬ES@y:@`(yEJH_S0P*KP 8t" -+Y\AOAQY'GqZl6_[P,[,zm !Rf `@ r ʦy@,HXE"$ &ӁŔ$. ddY J$GƠ b=l |  ,kXFS0̌3cTjc;1W#F%hH"C.(q!00Ae40ILJ$XKJq#L):HOUβ- Pa&!z8jcHbHΘ Odsg㌔Tw&,(IOw`4KreH5 zi:JGF(2HV QZu? Bp@ʡ ]0A&~ )&;G/T1 :P(Lf{&L2s¥ҏ ,&uEtB|jѦHi1N5P1$5gh3##$}=@MR]x]V PCKxGP![nvh/,FD"]g{:!G 2PKby !CJ 41Y0!T *1`+*g$` ,<$D?wo<(Q@ G 0dm2i b0c uڠ'Ggh 3U F  @4ED1Xiԯ I,4Y͐E_44ZI?А*,1 R,XDҥnl<:lW <( !d$P'4Ag~eZ^ʣ[,i1$Ua%B5ADo:O< &xV.N9HA]N`l6 ~`jnx_ n=[S/hTR`&j))RP% X/~(q6_B@ hbzu*$ Hb ]XL"3@Abή*|fؓ@.Q;T@ϰ `!_`p64Q^tjd (LP0'l"SkG%{ U @?Y`H ( ,0  APe }~ d,J* q8k֊b&-24Ap`q)i@6qvJ2\SA BzYQ "B#ajCtajCtBԆ RD-Hm!!*@wA_B:_nL<-Ps,t~KVY:THQ@4@nj鳠~>? ʀ#4Bi> c]? vR?ҝH'tˤvC1Vs2c?G%e, r\ÀI,D@@aP`U hAZ3B2Jv 7#!_<0JYox`ࠠ ,dC/^"\^ ,!nC0(AƎ[g`$ %@hHOr19 AO~F@8`Ü,Q ^`Ţh )}8J $ QiQ#A_E~ Q$ P%GC %! _zH )j} 4\-7|j)_O31~]4 ?ӳE(4~NwMGlKcDY NaVuߧhHLEs`(Dt JQ/.4kӅ$A~c>_,$kP!Qr 1ZzF,oG`6w @ Hd H$^1 *=!D0E'HDrICw"n*c[qB?oV K/$P[JH/݌a=ʀ傅0`#s $EK  Be?VۀP,Pc0F~C0 R"(x#Cn"&b%$T %=?2$($[Pb I XhP>8+0=!!C J= }em+ +ϰwG"W@%RkeF˘΅ :bӄPSix)%GװE`p(q:C@rl?@/{pAB]($ٌ:.HP,3dxHه`Fi`%FqBI05p8r,HGDpZ3+#ѠS" jNG_L+O*1 7䣋-\("=`& ^ ]p0^% t!3v@e/ij!d@QSJ!Za0ڌA54`Mo 6F#I.K  L*.HJTONL ^6@r? FV4 P!QPGD}|.4_pz~B(BJ(E3|W'g2?0 G8_B쓜4B?|@:!' 3ViH e"Yv%DUHkvG^H+@( k_f"*A<P&,a!An &xjAk" Jgv$BC֩&ݣ֑2Ȳ 9<, 9oHQ/bhLFrrp{pW;F O@ 6MH98w ?' Wm!Bt0? dA*^\*q-Mq#7pP}!LUfbim?1%#T_i<R Ѱ4 P֐@ @dSk(,8%HȢ@zѡF.,$aK yB@PUt4RF#`jT2 +` #)P(& !^yP|Hx BRz&}ӧU$Hրh01M6Z/ZGꀖg6q48Bk?E}D5S @E)26B|1Zމ:~T)%JH=/A^:Uj԰OzY"?}p:{ "tr~3A #t1X"zQVCH<S<- YD0L~uXrui EbN/jHmOI0((`$ H PmA O[AX, i53/E@,FDY0O)ɍ K.Q!B !!JaS)߂b lAFԔ@ /f A0$K|fEbҟ, I {'A A rvF g@ HUǑMH т ˍw8`vE^FȐ1/i(:j 18`$LQՅPQ+(EbaN&S(GXE=ɍh\vEY s<|@}4XUyHGCnyT%q$w4I@A24QĦ6TZ t %ڀ- ;eurh=rP)ɠa I JJ!BAh"?͂t|BbYVhtR4Jd!X|- &Mm@ eQ !X-B<i*>A(?!K%O dԼZ@d:߇]sx@a ᱉E3 | c@soS$Ul1Wa(6a @dx)6*I<g!'Za4o VJW=Fk}Xl($ADJN#`ELaotJY7@1lHDp y3z e(k_'gʇaY&(\(+LkQ!Ƴ0J(BD 00Z!N TywLubW-\u\9[Me(Y1TF֦.V0LN9BykO(ATH#AjoN) v $ Od`_uFQJ:u qHOYyQi肝^]`S2TbGR@Tt޵8xC,D8JDF>HQ'?i0^8O.(!Bj0էrg)W#t9P30LY>HMQM=EO6z$4P%WY(i!1k.0h6Lr$Ve3W𡮰c.1jm$bɀl8p }!rgFQ`$agQeM5K}#« B е+ ŏ!Uu,LBN`в P"h"A !8n!JZ mv(䡑̹fF砶x7iHW$!F#lhLkH[Z%DBHBWGXV?e,Eb> b KNLEǕ,;I#Q@J++fs+ΌƦ@-ЎNV%%:$LㅊPv~j1T*bU\Tf))qKa=@ /o(p#( qcb@701]7)c\8@RB-<! _ P ¡yZ>|= xS3BPfi0h PH`Pb-` $FxHT`j42!xd^:/ *:@TTXt]Nq K*ȡ(Q$2,FPX@Ih @V L!E@;F P&@6< V<:x3-@P\"Aˀjɝ@"qd,S4B@kTmP->SEiʯk^R 5$"#kSdB4팸"CzAŪQ-x*%9P( lAH d] ܠE/7E ~.%; T!@rBd\iE)^B )A e0mV^NJiU? )~ `4HbA$c)H3kw P+S@u1w h$@ PDl7VxErBԏ/hnA@ { ߒ4}/ ]xOq!Di@8B %  D@1K($1^AJgg)ߠ [ A@[ `Ly/ #D xt+ӣ1&+Xb(;Av+E+U{0(pu`(`<+&Br fph$8:Fhr4p3@DЀPܦڎZAJ=Fhp#z ЧKl3?RK2(x&"& K9h6NMPhE $}P(JRIq*f:(PH1D{rP1J +S" PZ ^kNB E# TaƫB(e1LD?D1We|ZI@\ᒡꑟBܠ *ˌH`(C򊉂S@bÕh[(M, 5|u҂=1f_1wR+@/uh O9(,&z3;^"hY)QF#G|+!k p@DUe2c ANRQ MK Ii1Q I0&WJg"&գT  'V)*,!A=?4@-܈`_Ԫ!yȂufAoX$l-J,+c>w&zQK@(tCb!OIGQ( `2 sHSt' `sׄ`aG&Ң~GUӚl?Nk0MXjM24)G Heˬ wVdPNGш\.Yc\r:LF i,'~ j9ƳEe%li($ p( qj E'Ql2R\Ik{ejCJNjY$?P|w!? 4Ru6>C)GnFh"(L䑥DT0s8 }YFI)/.3S3b" X (1#E ,BA1p& =c;eN Ú8˖|Q|0p}/N1UtCw{ .B{&b56Q{0y 5 `A%5ΐ%)DHA#r2>۠ DkUA{-h.ցX{ׇ &r U D :BcA(fx.Ri+M]`ygXuI5-s?H9D"b%YȠ  K9@ji(AM%2,W#֜4Ult|#?E<9?E]>S@+By-l Bk_RD+zcB> r8}x3oIH]<=CKh pbX<%*BLt1KCCm>=HDo'~\M$ P ޮKwsڰSH+ &M(ZY tK^YvDхR) /"]( wC 6ؖ9۵;dʆvs3 2"!bDŽ2@SaBt J$IR:Dڱpe"£!!x)G4sf B+"Tgd2+H RM?Ő(B?`hp+" 8~1"g<ɠand3҅Thx8y1d>&~ba 0G̖ <(L#Bt[y0W[|^J̟ZC\Y#INO"PV^x&"!,$=i?3-s>CCqTxRI'qq**Q"hP`ŤsbH o^FaLS-~b d>Oz!X )$[T#%bzf2Y4& }̹4>&EKDOtCYCJ_(caL %9H жW9x ; 'lO'gǁQ(& kr}aI0j5eB Q &2С $E{PuU,`up[\RV!E!MdoZ"=2Q auJv´GE13ȣ [?̵Rz3ȤNizE=٭d*~NHKuWW Fb+4 I22BC: BS0:-OL9\!-4`bj)e#Kke]HIc$]|*+u,l7%J%1%pOSĬ%#ۼj[BzbZnJT0@  HrF! scȚbXJ\ yX}Vej8Yd*? ]esn.&wePTSp;}!n[pAkkQ&*_"A; ]B!,j3$DcI(RolS@4N1C.FIP {P z0 hSK3CE!Cơ?:?ai5<@ XnɊ !k4 *rFRJ @4Qū:¡RJ(꠲y%ED$dǘiJQΰ8i*2 IhPxQJ$ +J8(QGDFA 9T5 IQE'!Z)H,%;@P4;谦`kBr<)r%AQu1 ?la҂"!aIJGZt֓C^gf.`ٜ˝ VYx?-$%dT$?iDb8 =3 ȃ!à K% \0 tw11b!r|(:CRd'$C'} ɰQVNnY$pP2qȷ*$D]Io( E]`Swh_՘huaO:v`Är B} [ !!jY٧;Qᔚb3E-*_D܉AEPt@yE3 `$vJVeQH_U⶛?»R%]wh %/.,P1I[ %R%Q*r5ВZ瞿_>)u[DԱyvE"{0DG8#D!b?,fR ֙?\vsu͜v0ʏ$D "MY#P/-IE8VAS2v%*3)S!5.G1FZ)!Z{OFy' IQ0'f՚%@0B F+*a 25#(ZJ-J24H$͂)@ BiFqe&J{}0,tׅ0MhP  )hJycPojbUň Fm1l};%+K"ZfcA('hiEIf,"--a$!OQCBn'H[=u"ŲE)Yd{4Io@{o| 26 Z旄fS$Z ˢUM24ތW`.Kq)68i2 `, PB  A,h?usXnU8C$wCiƎPyIVӨR)|pG[敓FO{Lc#%Kq&%A:,DZ!"/c( nm SW|pzisjT*jQ7f)AcYA!踖U;Ul\>2JQ`AzZO(yp>>;1+'k7$Hs< -O\ :$㕮t{㌼QVIn L EJ5l( BD, XK1#TXBQBSUHQga,ո f|&8:ejԊ ÙJ8Q!@2@x[E"R@m$JBѥUgPKQ$`v*Χ#"TU0`AMj\9D!VsbxΊK, K֌ *0a EZtQ⃋p;ST J3ȏ!PX`%ҩ,` ?6?9,&X$B?c1h#bPG=O!iXE$ =ƿAJܞ8.S)(QԎ0x(d2#}<-jŪTMbp'c“! 0XԼ:P餠!ap c./&#'V/D ^mzb!\)e/oN)RC8tpȂ8S ɉ@o'(L`]oE`*Rc@HZ+p5J)bH$H %E]|d@ؘ%cz a օ"x)da^}Dw3ȋd!sN&n͙`m*殷2pW_DI8 Y6癈pxJ,M/3qKN'a~ǫ2!6 (`9# 6_!">r-‹Q Zڅ"35ɤX&1{g))̣"}6)o> =gP-g i#` xeI5 zG* )QqOKGC3eɗedڐC $$lj  5.:(-==)s`s棡 (|ײrp +rgQ;IR[ffF(f?j"yMryhּtM;.L{͑Hc =*Q$RP9|I, b\v+s6 =,;Fw{NCf.*#1m#s&ֹIM& ՚ 0) #CJɡ<J*R5:@b!6z `Y.,4l)D1E,җP. h U X5fP+E!JBU%D!f$D!8ATW!jC$ fp!F<^!UAf<b)*T/iQhc'B_FWE|%{KrzPd+^u֎H;Lֆ"EZF#aXf_]tLU1h! ^":N/WsrFLHbLVtP0:* tTCBQs2ϊBƏ_VJ$!UJT& +> ZdڒDϘp>ZR q 5!mLbʨ, ??cELbJ ,4&WB P:eL9Hf`a1'Tf ـ" q,R8ȕKԓ$ %Hg$ZLS6mR'2JN$b SuA#iPx3R!C!;XBAV= Vz ٠PCf`$Ha*5SG Kp (} e|>@q!r<8 8ONe!5t,FU$RS$MO+5EJ !Q$8$@B2HD ) H0{8[cCRHPe5c,y@B B:Mi 3ծұ/Ys xZp9qG2u5Yv-_`E/v%` @ RQDY8 7&ʻ Pj<J*IYzJT=* H*`:ƠzHya*`UEiuLAeq9' *dtxA# z9Xxe|[,^4\Ӣ+TG @2v!)0vu3F5[ 3 1"cWR)C%D1Q^"b,NDB(̀!$étjA CeΆdH3Ll 9##LEbrC)mp< TxEp%n 60*(%xnPF^e!N:HSSU"su2w 6~D{\JA .b/+#cCsA6c[ȅl M2o;) 4%iaCh"3%l;K hq`|b$88BuOlC xaèt=*! O*kC$!P &(!$ 1u' <[[V IsZIηAFs @zj $cFJ*]J Y6e.]^K <@0M~AJR+k ֑RDZaVB-Z;-zBNĚqi3Jx?($Bv^<#hRȑCVKA+` BKȖ "B/b4xvqhMUV )B]@*Lҁ ЉHB"4dEy v @%HH%]8=Axj RqU ^_G^@(o\#QHHbRZ^JEiłU0%B1q' AC DR0 HAY_"|#x$5u!f<fXlAgXb D~^򪸓(0¿N+tme›.o d J_I|<So`hQ\K|l0@QH !*WJ@ I@w`!puuu>N" H;`DLr2b P:xifaIaFqZH!IW E  Q䅖N>""Jd5@| :*/> [%g` h|e26H%H" ! |dB(`GB:_HSғAc,hiha[0Aޥ3 j{IKx@G "Xу` ؼd"Ù%/Fޘ+Pyv@ `)G(,ʄ҂Wu3y v?R>:4/:sM&E/G$@Q89*򤯊yA:BR)iPB<w>`A,J $0<&HB#A;@@2@@C/1Y'IS (y`%AFUIb`L.:|;8Hh)6i Q%UB窉R)8k.|t֛P`pbDluCk] ,Pq% !Nmѡytz @[-#Xhb~T 9T <Ձ'Ѣji0UB EҎ= Jz "`؂DށűD,[i@X!yŃ/.,(AC(jIAׇ`ԣBD,Hij&ZUU/XLO 9/p ɉaPkL!3R91 v;1\XE,\,X;Ò@pƊ' 9Ble5QA F1^>r!`Ụ FcI@BXkS!BE"QDr3Ɯ ӥ0YW !΢:3d9 2!%2+͇JU*@.DH!%2Ū#"|/@$  YW:vǙxQ$-8d඄Z[V KA5Bѐ4F0KSya1g%{yYO^xOf 9!vWIq'#ʂI .*,HP$B#AI{{aiamDC4կ_ 2Rx.$~8W! T]#Rg@I,!W bK@hFIE*d(AA2+7qdP3uĴ-qi N|&~:I"ZkH΀?u0PБr7 0Lt#@t`"#%!*$4zJ:j,Xuf)ñ !5f1j#IJ$h`Y$HuS R%@ɴ!Ԇ; `f/` 6 DUC02mL%X'i dT!bdL3ꎚGiADR*.MI T `ZؖIq@ {LHe[E "Jj(鎄e?Ɋopt 4ED`c@<إ@qiwʛq bHK0?T䦖LC`Ve:!H^^ u=1aI(QK2-w0wPH $‰`)R<W42@Du8YtGṑKE PpRŒ*sZCWF)}}&N`R? OUNOUv@H]$#-Rw mnw_L0rPn`quÜ?DF N$ C9(er;b4aݩˀ",H$C _b вF HB? H1Qe>1oOT/l  a0 Jp[\Z): l`+F<`)xJ<@2~`4ETbG`X]xwLВE?},KF3h,4 @ tJPЬJnQr[㒄 TW3"ɜz,Q-xZ aآBH-,h@H>ÔC{xcDW0 Xq$@Ďzr~A| B8Z60x0k`Od@G_΀0v r?ʑ!D#M1@ 8V?U>jG~bpPjDHX҂rt-N>@)=>WP%QE/FgFX 7XQdQG̜# ߋHTJ1 $# pHp·*aւi "DI*?7YYrX+@)D)I<ch#+06?,ӥ.C|DQ(3  U>׷+J)# ɼoW0|/KgN#|Qx)mEJ$nXcg&0 N5נ za5~5>5ßdkyPٲ$ Bp "= MV R5]AS܀e-QXi@MUҕJ(tZ`ii:EFӫNKԀXiKFbkTQ zpDd`@hO 7 >0 mPIa%H?T@zb`/05@, %_$|yBAgыG/81!srqRMPF=ӌa@hV"J-#|CH?+?@YAؠJґ _xᙃE6a-)!BD@e..,%@cާ MB(\ u\boE(x d9U bAƒ 2CJ!҈iD4-XWPIڳBE 2 gBvT>Q""]@B` paŐr!HJ#@[`cL~ADATB0$3![hԑH 1"u0`O=NA* t} J hS Ϩ 3 +xCNPe+E"T;MjT"ؠT|X *0BV(! h y+p= a RHe!:!AńVH +`DhPB*dҧ(MlZ%U䜒髤$cB2&HBH)$ L|U"Ml*lb`h(@Ő,JD)Ϗf,4TAjLHOjH)eň@CCBd (Cx&b`F~MP^AL#J@]%?J?BxI'ա $ -/&h+wLrDf o6eDJ&L? p07́3@ L)5 7ǂ;'a~NxD`!(.ғe骵Wo A@Rt߇`gPbd"4b) ,R ?V]U9 rF^F $@P [f&iVP8n͂(TIG"#B e)q& 8- A24[܀e,.++A51AM_[ۮu@#OlGa.R3M\ a0fV0&@Μ(A&5<sl&t@_)xI 9<,_>M.:: I@&4+C ,xi]4Н  hev!dx|8Qͅ`*02C( ::t>/Ҁ:!T Ȩ. Pi7 Qi0"tL4Q@$b(PQ44/ @ & 8cHAtІLO0O4 ε[`0/Z&R?h! qR$QLKY kPt}r VOc <O"ІXP(!S2Z8|#`HH`3Au5`U7:\""4d;HaX, E!J#|> Py@,r^0C4غPCp&~Pl)Y8zZZAU/ 4XB^ZGh*_(d+<`^$CyB!P& @lACAXnZ] *20Q$C )>E?R%7ҐF"UGJGZP ;/`ODo5&o˿bfDɄüw$_-11c@sЀh̟CC4Q4tDdqk0řH/-J&~dߴGgD?-$F"@15ZFz;J,(*ihkII $  h*hZ.iOP! $M^dd ZA rAJCDP:c? DD4Q$qeb=hf~ B\_5!* Nƕ QFVj#Lq.b*S,keBVjLĠ,~X%r1@J]cA' 5gV00ha X фAUP  @z@PT AUt@gn ė PKbH5Nh\P0/P 1eBmxxŌ!疞K1t**;Ÿf][? q S}w@4\^^^"0 ~G"XY YwM裓  yD%Bk/pl\yPf#$5k2@`N]Q":i)Tq.E~)h)P`2_ h I )ESSDt^BtZm gfFZb A~Ø|AEYP RJS$+ShH$FJ*D6D9X H2%J*T$t5HH",\ԠQGT-PK&s ,.@$"BfHFh %`?vCyCa `9H*i<_/t 쀲m4W~ 4H4i!Bۿ PSLzͽpsb@w K_2bT0֯e Yu@ PrЂ'=ATI `| 5 L%< 1$99$2%[ DLxJК0?"A9Dx@I'ࡀ'E DI K  $C =0_~q耞7 @-EVw` PPheh]oC BB#U4iQxM5mϋ^mH`=@=ba˕.} (QIV*uO%,Aw$𐡈 jA^ } \y^03D(P /+j4x,P\"P_}$AzE$Z@ ?IhicqCFcO3(" DP++oqϙ_g`$3D0f?M`UtK_ 8g0ץ42_}% YQ`R38$ 9eA ʡyA//) ];Т GVZv2EװRZ8RIqV9F 8B;9>3/'Ӈ8ŏ㔄Nf!lӺ*4PNXB4CqXrԨV<u8$A B,Gh`DD (*0d`>:tӆ G)MB  _<:YBk?{> $@% /6b)}uА@h1!I :+naS _T Aŋ(J C~S( QK& ' RA@xHS,9Yѩ.0~IEHOE| , Q2٠HMH)ӿ i(r\g=RAQ-Ezc&kC؅cPWG5QiU3水. dv~ ;.EĘ"jh@@D#j,HIK}QO5(\)Y,3 @Y ?cèfC_ \T_jOM 0P pРƈ@)+F1@*G>Ïڼ< @ hWDXҵ$sP"5~p6:S9ŗ2=U@P0y`Rrt}D&vxfb9. DBl/#X]ȢL* Mj9cM @(:5 B K Q(EV0hBC$)k^Z%"K~*pz]+0JKz׆Oa` %!"~/tM$E+׊ƀ ? v[NL%KTԨ`@n B#,X9xe1ve TńT&F!Ak$}oG0a", iO V AiP̂ _K `ʐi! A1! PBta &$(J-s`E4I'G g BV@PAiN FI) A/-;!)) X),VAD)UϔGQ82 (qdH$ gUaT U\}y@ܑV(HhK 0jy_?"xDa#HF1e+)YJ8P@3@B 0!b0DE ]:b?STS!dSRјSn"LU&+? *Sƅ45+CLFɡs%͘E/Dp2*&଑ #|s)S}^ P0$,<B> c,b]/ z@, A@0f4`Y-hRs G#@ P-Hjl 9BF{%)%e| lDeE&J*(thK,&I,0!J,"PḚ4)F5Tb y&ARXéD j҈f21bŒ(PB (PB$P$EĪUG2r1Պ++ i/+YE byJ9:r"^"J<`a*Ra8j3` #A!#J{dpR,'m.^NKn#T)*JSU/kX kP& Pòfg>4FR5 ([!dXI?1>B%yd#R,B~zb2~C)7cpȲ%ȨW0ufzxLrOS#$BPǍQRyP4K%mxٍ|']WIA%~Z`0S H$sCq(4)!TkDA )"`BW)הtD"Aę`1Myb@E+'U(j3A/!̘!^Z\y%",X PBF(Pc *BCĝkBLP Hc.}F91'&.Ll0sqL9_qE)BRH3^@򀎆J"x)J=6K'NOa(̀B"Hev0lㅒMs  `H0" @e!f 18z%Ad <˽U( @]yA-$@P(PT1XIQ-q,K1ybh*Q%jp EYX$h$RRX- ۓV (#ʉ{VÂ5 !DH[13/PKB3`^H8jb0BU!kFSJqg˥7PJCW^BT(,hZB?OdF7IWca_ IC"`b{ WRQ(T-2`VAi 䤗UD9b89*BU*:/^E"Y %EU\ ra>$$lxNbUo>F"qը.K`a0"U%cG<#V FI O%(hĀ >_K`_W>!4'e&1|d9J1jkH-ڳ̙Q%YFH%y%bJ @$" (!#z:aM ZC$[$^c*N QRk `P #&ȹC)@'!`L?ˆ@8 )~8 )e0@> .H@S&Ypx$CJSr89\6 HJ SFs1j#TVPJƱXBPŋ% r@I&U:k\(²x(C9>8.r4|yr,(Y,Uu{W# S SAE͙m+@&QUa p0 d{d$2gzZjqF>(\+QIQi@$`2-DH")u$L@"RGaK&8]cP$%T  (1Q?. q$T"`Z-ˬCpL-JH ʬAtҠ Vc+Z+p(1+v;A WO'A)DU`frdc5+DQ 0 =A(B18b238)IAm!:mbfr,R&(C¤b'hJ[!C5 IF 2a*RN × 1BwI#$W鏒+FEZ*D^1B5A Ԯd+8HN2qd' 0a %@"$K9^#JX ӎQ6dd B)Hm=e۰CO!t^*uM;L2e0^@`#*?P[+ Ӏ"U 3 0DC11WY\ekmHA HBE990hBzrG dJDqB6eFQ+#?=I_\O(" P`@ XjʊE%]e< I:k+ $(  fpnMD-2$ BR%LSGQHƮQ#UPZX)b_,EKa՚f(GYC"4 U%Qŋ!(PB A@Hh-(Ƥ̡YC*y9 `} 4TξwZa [1Y(CQF< >äiBA HV4!8ۋ0eUS~a("xB```̒8[E mRp`01VZ”T j q P*!T>иE*UP $2*H b ȠQ&XӦ1bGP,A$4)(Xב( \ߧ'Bᦘ)ĺdߧEY֚9l@! ʛ$ba%(X S d! (r= DrNAQZU!@I B- ! FW`J0 %B P(-W>Z[_ MPRiNb 0GR|D6=)rap cDŽ GPR-Dyx-U\V̄(b(%2ΆNĒ+Nl#HJ)8'/|4*J]G*X}D: ܬđ@efe}-_YL B 4(&d0H9LDc(4t4vPfdC K?vxVHm5_LO( L @ >C2 : '@MU Ž6q±LH$R `t($ca%A$RT` B<gPqTL+$hò yjE V.%0c1ϐCAUXŋ(PB % 2@(hIBT#Ɉ j 4`M\hR(T圿1LrVܪR1R[Ovtg B P@@QU\Rt 4Ef pℿ)N IlPq9?j9&Suu"!H ٣f. `9zkd01" O@@ F FQh2M0.)CTy4Xx jB JvF5(84$ ##@A@QL8VLZtwXt.!A iZ鋯"KZ5v J&;TgNb@ABngMZ% Go@`&CT`PlU;karx+A%HRJM@!PPiQ٬AN=Y 5MY~PHȭU3Jr5Yldaf#Nd?vt'g9+̼6)YjP# < 3Qm @E %B g{Xq'dUһx!;y[]lz$*8v Yo nqP`<'N u d܄~k1  8;N :"pѡAΟ"4$L y04 {PxVpB@ ( @MX YA h"婓ℂPxk#,D%"-h ?$ J$6[qƟ" Lc3D{x&6dHO+ #'*T p_8_B E$DGBJ`c^PSR"qÅC$B_^2N x… Da: a@dSLjr%M>ʡ JU) Ań0Yjɖ$PbPz h%j(IG\=CH6c0Aha, D#4"(1V1Ud]pY,K%l'd#HGXBD1bp:E"N$ӑ) Id_|'EQ"80СBPM`]\c8nOct'ܿħAH- 0 a2#f]eBP9-\O ys R4@Qȃ REI2TmRIj8d_@@@ @#]e TRr1BCt!j@g @3("T$I>AcA2H!C:u_¢D+,H/ !*#-*qd FUe+ dtY%dv2pvBLB8` ?+8'}.}[:!P0P 0(P@ A(TT[3ӋCE9^JQFyyUhB'+ !BVaoTpH(8H"9KNK#ALa@$ )UA4谅Ad )CPHh.dyU02P)Q $ =YF-q¥? 'iZ>cmM6c8)ϐXQ+}5%(UE,5(6fŊD FcB5cQFJI!y#Cy;/ B  D d~׷agXM# jZC&H=vM @  )adAj@_Pr #{cH h@惮QRADc o BjEH4$* E*`@PV|Z1b * ) A&@&C.k{? H,pDP6"tiDx ( (JJ840ˆDy.fs2PAR߮ѥoEB(X+?/A'G 0hʠ V HJ'@T!a4(x?l(r VI&Q6i 9 ̋ 8FE 64,Ak ѭE(% M~@ 1x6k0 mAaL7,1"`g G!SZFl u=\` ".MpByC g8?>8ϒrLI0&t]E2 !&`%A)KrgPPk< K%\f" :?LKLo4AV J2I+0) F!" ب AF?e׸e3"G3Ɋ@$/q$D$0^ ?%'= >B9HW!%!kp}C9*5@,F3YFB / ,T@+!X*V!\I4|)j/G(H00@ `# p !JHO Z=$)+1h`n`!$YpdtR~xM- !-r>'`:2P qh,FQ= :j8;0{||gj+ɒX8Auc" `:@= mҗn)4cTZaa00*,A J @7@@x @J Rivsh* G:q2b(Y|x̀` 4G5B(tgFa_J  ,DÙx4<*jC1j&`*rqx}@$j[5  AY??T6~OuJz0 ?D'P#;ٲ -BH ?ڦZ@ &HaI Oz*.1]Tk\x 0ʭtMKa.<ؠ!pXBBE5}F )Q3hx:難: DNA֎ 5KUG 3{1qj?xZ0eEptS2d#drX=) P rF#\aXB. T`nˉ1&$Ę"LI1&$Ĕ/>Q,FoX p0 O@CF] p !#8ar'R$$$XUkWO-HD~ 2e] ("!W zO{ܾ+)Y /@h%(=dА' HLR@h#S| J e/W< %"3j@ H"9U\%zCjo0 y( P(QXvj +N;[6N ALb&i.YȎXf1@Ih$ Bp J!j:f"mTTBEQP @` 2CB)B$"L~X`A&>A|6(P T=?dCKN,p_@RB_xYh 6d2Qh'B] @ Ѥxy/8Hj81V?y T )B0B0 #}ʐl#X8QZ^izgL(B}pHmгUޙB J8A^_ /Wr.@P,DC89Q ؘG nS' ? -F/℉Gi hPZT?UizJhVH y38%b AGH&9@Ijd?kOPA,/|e"lXkLA H\âK.A(,RDr4h dQ4OCn_h>!e/'mdEf5Lн ?!1r iL1&@+E8H`mk!EyV|`EAd3Ea@HA.pCIVê >P]ԃLb8@tAdH%H$J %1ꮸG Ss D~" W5d H$WM"WQbԜXAGyX. VP(@bd  `zGzqi8@j@Ȃ %LF1\((ں-l\td @Psc 9LK >\w@hBmkx@d4DC! F,ᑨ@uGq"HŜ.I9'9Vs)X)KV{ YԬB-VJR^Z)b$`ykF#Qs'f*8iTQY+31/@ B$ (t-2,&r)T=~d s(B5u "XF@@ &,h-9n ;N/FC0! n|I6Pmb X~䓻׬<06,P]Z4yFĖQ>/1z&(?7qkj!A\! u>,x} ]?@ p怠>B#8g?Nn;5PF*j24 E!F  S砒(dI-HpZf Oˑ@R %"I|@Wzvv'aYEA%9)Cj@u:[@Pό%^ rcXLHWa"DJ# s 1 # Za0\2yGмLҤa(94$_~D!`@AA1 (ml0NG.V"r 9|@    J٠8E w`sir%(bO  h-t!@PТPAIB_D^~9{5&H_), l(P(@EJ_(x^?@)ЀL/" S:Ӻ ЙVz?P <<@|^B.B">DB _">D9P9@F2w)E`<S,:xLSry  RDD61Ο/dd| p'P(Q He*TWy?lL  `@fAHPpa@JA$ @M#@r&#H 8 a \0pP!EP~XMP  R   DP)(&P6j  0%94RNWU8P< # ł"$,S? P & t#" @b A$)YW;M$H @$0A` H@B $Bee "HA 0p㘂W섀AhB`xYAa`@@K ? ~ ZlC@dKNSLIA #{Vkr#<$ E DRR &HSHGJ .CT @C5+&g@ dNt7>Dax`(Z#X0K rr9=jCpEj)qw6`hAAY~ ,~>?%#&F Ye_B0"ojok5܅XJ,.KGG k@XtUqUh"uu6e t}[Ox N!h3? *~kAv  0 7#AbLdj Z.P F*P$N,"IY*rU&||\`GQh$ [?E+cJޗZ` AHDbBKbu"l 2 !r D(? "p@AC+}DⰈ:?5 7Q.% 7@y. -22P`.t"L1_egFP9䮁,hȢc0O:5%GhX QΦҠ9OĐ[tysDl";,{נEp($P *" bIAQ>ԅ0K$0ʲ'pP*&UU[T}ꭁKxkY)/K V@0 COW_,d@P,Z=p%BA.n7i0aM6&R߰ e H D] 2)`r"QԆAUЄƂEhf+2XmFJ qG" ڗB'# ¿`(ϊhAG9!fZSOlT`x 1x7/A(l}>Sj<"J(u4yrjhw 8 0@4Ax&TM(1bD$PI?*(Y0@? 2;I{C!_ H~5 p KC 2lĿ;FO\!*pۼ!a!a@ +tfG0XҸQ b `(|piQ\$reA}LO7A yiz+}GxV.Dv!N> TY||"U Rm *3D%BF>%|7 Cjt4SX !]`&B[(mƠJ 4QK*0X&9k@8K`A T!ջ/ GU!.,T}oM j@FM&C-{BYH)4-'Ł"4R2jARCል$*E4@Go@"mD#?& kaڂq 34Hˬ1!ZWP_@u0HEG^~/? >\ܿ@  'ET!@})( .@ktEO /U\B]-[_q.w@,*(ȆBBD ,BPƄ@;J" (rj%8z)ZHzDEH$Da!*,Xb P'P 6L>D8*5 EIA =&";8ݒQ=ܴ yy F8$)@(*&jVr_U8L#-xTZAJ5b( 5BۄDڎ\rrWVi2)z0m9 J·"`}/+8[rF|v2E|yr#@) [ Qk} { ARwfAS䚇1@lo0I.Q4#0~k@{ 'Hx{C8G'"?@O )%4l \] j1ÜFU+dIycq7 4F<ypiӀ K6{}lIw@rހjo@6q_?@>|^zjjF`!M }R1$\Y膱Q'@ AYi0CnAȲ?pM,_!%'L(/48esIQPe0.[ 8dCdCqun.D^G^>Q""""^4:@sX-3Ӥ0\GHj@AkNO(LB|/ QY -!DMqKB^i%`0XGi{(ɂq*@ C%D (4"0F)QHDL%8JA1(NE( `4{'"@$@" pT IVE D@ `ʂ 8=JWI0Ծ_IAvkyDVtp9,*QANR6ck?*]k BU5/ J (@1u7"Se1(2 ?T4T %IEqa5B5@WI`hBpziU>N((Zmi ($h<>4&$@M Eq䋔@n% @wxdrAnw"L}C[.?T@d?;y&J "{Glɍ1 tqU&h  AzBlI`҈C-%Hj`0L(D8L.""L0DHwHbK )UL!HRJA0~<@bW3 CV$QibTd r] 3HtK5 Fm=?r׵" A}k?}AP1$@PF@ .N?< ȿ =2Na7x5%8 d%`m՗-!p=H @ ^+u6WMWQBt|"tT@w 5'yep0p i>4PÙ% h&%A@DthA,A`2 b. BAJ*ʆP!@aR=% B4jjC @9+a XEa?`UѭM/ۀI:M`\6SW4MUҡj} ȽXw-@l X@bHۣLF`D!#4NViOF_*= 6`y 崑ğ(vB@(4aEკƸC 4=|x}o06bbE|G@ONa\ bTw09TGC&r5y!?W)G1~yx8A tÿ_!# ݺ #'HEgukwӊ%21ːte;_~!jA <8<`$@TT*i(Ѧ$*98SE+<}z Jj2t U">|XrC:1C.!1O( \ A* 1Oy2Qa@~li/ XTr9ZKb,/^ )kK#AZ;H)/F?,_ᄏ& kbDN‰ * 4  pG5TYpX:A8B9C(08lGh(tPiQGXU%3CiLjz|TI4`R9 xNh%v' A%n''mNM""K͢FŘTNTp_̶3#@fzHT "(mfL-9[*@EnS J79I'gyA8q $=JG`5 Py W^]C0""6lo1 <ޟ)!T!S|?[[?!YW)2V4#2fj`y!W( ^y7XƟ҄\Bsz<4$\hhBiF(?~,aٌk7a2$NnnV/*n{. קn(1ӏN h;UҤ7>a/]P" t 9 *Puʯb4"~DBG+@r頊J(X0ȸAZԤ * d@GK8f9!2iC J=J,.ѠP ps?PX( Ě-Jvm J _iQF&Tk UB8A55a)FkB [BXB!WPⲁF5_i_KU@)V/t T@tR`}X \ iA"{8G_V*Ydup:$F8T~NH e2t9N%@XCk ?Pu/3 PQH@G(bHTTt&!M@km^?^Z! N2@#NPG՚ٞ<' C CƄkhr? ds*QA1ńxk+9 $^ Pb @ER =2BU(%B?U  f@'0P0-k/ #n>!!J S< 7=(_a׀EY dbtrFZV*tPf ; *rRJ zaԪ`[8<\'@!&QG}@*u"AR_/ф+>Ki>0*M2 ?`A*PhG1A >a@(w_,#B?p?:-*!4?BU'` p  np@10㳊# +#3(B!:I? - gn0]AL5q%.LA?t, G1h+s:+`,3IjnZT T8ŕj}2)yA,%p nt c8(D3>RPDR+Ȁ!wm:oB?JTBxU$ -U H('HX/06F(@lwJ/SMP;F4%W!+_"K5HB|n0Bd4@-%ŝ@V/#C 3|.1NjY O?/Pſ1@Bda8 ( a캃eJZ #,dj0!gB9@Jb,7 @|0@44Q@0:@:&*1D 0Ui@!AkQ Ah6HGҪ׀ף69ePO0O!!-,WHՙ %)@FҋOWl|C!@,u4qC @#=R+T2/ d hψDY52Y(n "b@(0Dxz 7SE`B@}D/Hh `r*V Wؿh AZJh@+T2&h8NY F?ɴ) ]* { |?@}M=  #7gfbF^W`O*Ur1xZ o(_ʔxٛD0(N?xn@dxJA(G N~( 2PtrJiJw+8C;M5/ ^\D Zhy6*z#E R+R8>/TF`!u>I٨ @R- iShz 'LG $0!=5HY P]UE G=QL4*|Q}?&P$7@ d+6vh~ ҡV\X%hRGz|gaRGf #Pax5P->S^~ ,%,I00"'B,M%AoRR L#2C%JP:Av(` vB ꥽[,},$K$0 P$I I# @db#@@0`@8yFʅ*#%@ 0!p PPh PZ,(CL)0BU*(!a T.wvQPPЊ)G-Y ^s|tF5,ҵ"h"D *F-&Ǟ074iMH]FQ,+kKɆUAu ԼV/Ӹr < r c=TK b|_!ZČ[WXXDAg / $d:"v ;x,$Rtc HYNJ{59Ab`@g?0&Eu +=Vq؈&`aB0y-lEiDj5*XHdcm@%Lb"  h ua%P$ "!@P4:D+]Z{6VhAΉD=\bM KLʑS XBxͅ6!2ڄVbۮp,[v,OGVA=$A|Mv!$3԰% ~\ªLLA"ixM|¹wػ)ۺS..h|W0k6Y1ioD} 5?_V$w167K,ՂRQ?sOM F ,60I!.R.aԬf'2xXDJBv"YdV^7񒋿w1ů63*uI$M2oyJS: lVh(0 `9L1P %LEqXH*PDP>t,L0FXI*$ IFXX6ր*J}%4I J)BR4)*P!It$"X&X%Eٗ4@PQJzQ#3H{DV:Az 60KDT2)XGZ9Z<3c)h/mRT-]N+䫉y%Shkؓ$bv J9%XݼD!"jqcGh0`uA  $6qJYQZB5zx\0C(BJVI(Xpr &V&r3C02ܛ2'KGm=h|=C2 t3U>0 +ą$!Wz6? [ '%!܌c7_UZJ@p)h<_q@ HA(BTAJ`P ."q" @P(R41SXSBE!h $&B Q -5N :X1":1QMs0 5(i9rY+Lֽ5'uCJ˿ 5YJ%,.5tMWl0\2rVRҸq:`"@C&)-OA`HQVD\T4=m¨WՙuI 3\ʰ_,(PF‡ŗ*`hsD+]V"),4aEKFZBNPf1ÍK 92) AX@6 (" KǹBB(r|T C@,0RYgV; 9"1:3ƌU*2k3U=.[UNk H넬ⅡRErEt}*r`ٽIA`Ltry8Ckʆ/yV>bmg)Py` $Ht&!E@؂f攣V{cu4^rY8g3d:jzD!Rk@Y7"H5BI*P&Lģ@/;,E-52ME0$8$0t˖4Sʀ12IPIڹOYlHY01*]gP! Teoǣ@Ffp9$a1k/SB9)6/%A.B\|p2)RQBPz)]b-wHJ]> snI!2?5P0ትhGtV\TZ1ʔBG] qسCI!a# A(sQlrTQ N ⌭pRt Q|=g#QP1z L ԯ (Ag(BA$ECQFXHԁf QuZOViVN$XFhе$TJyC($h d)J Q(` Iya y|*'Q@$Hՠb2NO"G+ǦD$8D(|A 2}Bgr@HpPR%g0 *.*K8 VC΢'IL-B ?)JC_T$G`,EusވRArb+Abٜ#@ґ !1о:j*E,qA8@Q+"iO;ÈS (ϘqO)ka_C]QvME8Dij4WWԇ,&,)^85#*Q. 14?HE1H,DxD$"p pT( . P$u8z?ʬt Y+0-GW##(گ##4"$@R+Jj@/_h,ʿSZm#q!KE$k]KL%JaNފHF׾B#j'cH*K<" )Cg ~H& Ps ,">CLm!"I м\Eix @p`0-(/AyA QEC rÃK``a(@ `'TtG*%B|t63C! 8$,Šϥ΁&C9?Qy.=.3y (|z/Gp}@-E`BQv]QDZXI:'֑~/ʑye'Oుazō]EBON a)<\!@$X. \/?!#x^,B AiXx|d~P?(7c(\|zPoFy@  #@T8/5#"4P"(@(@! D!B F !@8n^@,J:C3ׇDQC*hS? @M(Pz!Z(O^@Y4 ^,)Ԍ^\@vF7 =L@/6dQ?gB"\A  "-PJ0GԎÇ`CA/ zi 'VP5(r,@(L XdsQ@c3`wDY aA~+p@@#E` @ "5I@*QB sFV@ Hvl N,晬F-W # 4 ddd1#Nj-&`5G'M!i*  %4'PB#)D!_爇& @ ah _0p?4 A0aK'!((AoHs搘Q%w6 K#L?\a=N94uJ@ )3APLU|$ .6(?ade 2* Fbt8@<@P5B(\U/3(})?ojTt=׌I]E\\DSA{,D[(B@T!Kf0&1?s vN jH"'etÓQxVиG@BYg53 9 Y#& 14UZ< ՠ@ hI - IB> ]y,L~0T:6m CJ0$xJ]@Xպ+g`a<n*IYBH (qܑA0 q/z5+Ɣve2`ʗ`gEA9EZҋ$5CN-@ BV4 M7(%_QE W$ P=  @2?aHgL@# "L~G(W4HNə~*#$+<V?M@@`4\B-,d/(i$iZ X@Bt``  $ D^I@< RN $tx`%@ Ҁ4n5@/VQHY]@| Ӂ*0NH DEFȀ }!b(iÕTf/hd Ac(-I`x!I Qn>!!D0D8 H¤/ ,xMP$.-X-(RtE@RdK1 :a&!* %,gDuN~r 9UɕծE_ܧ`AJʑH\9W~`W_W(]`Q^潏 |1g>Ph>" *,(Ddɓ&ij t/$DCxΎ{tl{8@\B8R>oeriD:F`<"LͰqQ-qH?i, 3a؆cEH !H)ȴ(H (Hadc8d T"1貊 T"1X1踆*Q #@"Dddd0 %!!""Ai^t@?\.(?HhDP5:1޽(u$R`Ϭ'DJ)}a,$zr:if&*+0B1tkeXB#?F@(FTJ)@EAja'#GYL?!UT6= 4<d@Dbwa s&?@?5|P`D`" Rw$r ! Zn!h h^$t%B] A^ KC"A[J3:٠Ba{ `S%h1Ά{E9Р#: gBиЩAjt  8>hh$Xdx!Zh|<<]>.JiC`LDM^&^)oen uj| oX~N( !&184b,;W#=0c{8^M )f0^ bq&~(m"Ɉirb+ 12QJTBPA* B QRHm 0%(i)쀇ݏUGڱGfsS>P[/W+W-#ZCA:9@fBET>HQ# '2mpPJ")i@7!aCGo󞧳@т]i d\V@ R]0; Zh8&H$80Z ' Q6hUYДf2" ̐P,+@`B0d"Hi UJT @Pd Ex:GyA,`K ^sii-]Sba wu'!Px82'! p,GBwIJ)Q [ɑ@P4ӆD DqwpӢvSEw{Ԍ>"y!-79u9prr" ', =@+䣳$A"ʢ 8s \bƏb`q&N3ɈxAP @b!\3J Ck@P) Q/XU`R_46EVf 2F0D8yp @&B2PtP)ChI9$BVTF34px4@T"y!jppQ  `1$kh5 dj(ŀ/TQ sH@BÜ&hs 5 sh<S44S8f(U3h>ī~2r ZPA!H 0)@ZHyV `B$NB"jR#v (!0@h(D? APP '9Hx!xEV,5F0.!@F8!Pp*` [nCD$ ()ӯ"D Wc-*(b FBA'ZYiSpATpt JD(*!PqB$z.DOD{"dmE&#N]?\)2@Ր|(ϒ'(b(,CQgL_2?HD ʠ8&\C 4jf $AĜހj>%J@6s* z92 $= X)K0XF G% qB%W))פ!(qHVJBY4)sd@E@$6)k@kiD|`7FHH t4AZzGH8@h%A  ] 2.0P!fBH)aBPY <4hk)O}XP8ro` A/QEb$GJΔ$K(HpIEt17EI($`؁ɓ/亊K`@(_h>~.J8%0LңBEwaSWB H_<'E{#,pTˈ@KUHi@vS*wfۊ#;` ^耢V)"p4b҃ˁUUY !ƀ @@Ph(&q=" l!Dq)&׿hno((! V$m ``hh&aNo)(gK̄K`(88)A:?JߣgKmW8e7LttŔ]PNeVkGq40 Bϖ&%bz^Y`U1'AE $\ko:(ք MI B{aDk++-TEe1=A 1 $賈i0*!\$`@D@K~Y"!c#PJ*u&w)B:wa(<ĺ(("[ᒐ_Ĕ)" 0-A EDPX*.#ʠ수`4(>5@Y#D⇞8etyHPp$a&R@<)_hZ H ;C xwHeH>h+: :\\ bЂ5NÆ-#/ ]d)jBlI|aGЂ>DT@,ϐT[?ang{b#ةA+ ? MED%NO`RM_,Ru30+wbCqL>+"tK74HU* D`FRPz#"yn3_q)U zJr`/0_J`+3X$?T &" Q:3/d@խ  `$@slGT BR$$ pjF (Zo$hzՠ_q Z " UGj4w$3|ܸU~=MSUtlXY Rlh'ȕ9Tv5gs%owNdbKh /*8=$OPGH0o`?|NRn~e* +k ]9fu%ҪYsH kNS'[1^s+Ve0UG X@0(:zDN@`<j5B. q~9Y: Pr@ќb ? nF91 M~""M@1 y,!APF/5 j}>}J# @-EcCڐ3t5{9p`PHh3@@p@$|vF|P x!L q $ kB$PA 4n _>C]A 6GZ%^AXaad 8hy*V( PM&J? .(=A@! o\=րS`{!urgpP+PIhPӅR-786$d? m`#&J g%ʕ\%|hAt x/ɐ_ $@$ p2ʁ  0B^>}` @DO x,4A/EЀ 08!-18hhC((!K  x`x ʧ83)@ @~H4h Ѐ  Ph(V`@4((@D"rR~}@@T )R`@$    @@ p pkA8WBb#  x(;Q"qIΚZA-)]' @DX"IlVtAUE0HTL P PhÜ@ \AКrEl^g YKu\PH#AT)Ȑy4REMC0̂wח}aSRf* *yu¬I,NkkP-# C09µq!unE2;dΆU1Ѕ0}&>l?A1^0 !P ^.9Y+0A/yI2h`cI*b9t Qg=Tpy)z>=ðp S`u$A2ttm%`,h% Uj#B4P P T@R=1D:+ZkȘOnL=}|r]Sb>R ZrULvJ#H-`VֹBӗBX"lS noǨ-S&nG;+ WnM Nf34<$IYi4J '7%S#JĻ(c(Y =bI*J %#Q!()J!̐cR^50)~RW<@*2㾱0Dk9~Ң̟x4O {ax.(0SXQJRI7^†s ]Znѝ6D`%zpgC zP*\yș` ]* R?İ0С$kD]; cX~gUuhH60V8"(F/LV Q-_zy &-N*@& ( TC*+ FVk5H8%B٥46aaRzVz'(fFJ˭Xb: -]iK) fҬ @ӂiuJ(t2P&_DRp|an(2AHF -JP`2xFh-آ)CB,y. BoȮ64R89S"I +1BPuSO L XAC 2K-)uw %/9Lf|̺jAIdTAu1 x`2`J  hc+(wLy8,bcJ-& \9*ܠS @ KIPG Aʬ`iDW"TaP h1h,Ql8zAYT5OQ {C:-R-GK4" i5JԬfGp %BB0 $z"ބt8 /qIKHh &$A%(hJ4@zND}VL4X 4k@xJɎ@I*5A:@b &P`yl)8q\L !:Plr_V!G~A[UbRH@cLR( (A  BrQ(BX$BHzic }Mq@9v~Qr!W)s<)@}I)u A #C?pF46{"*N0`s`Y9"Z sFt*LP1QS?xfℨ鑁iJ]QJS!Cy_ hʒ6xΚِVN](*ր+,nfT25 N̕*mc ݒ .@a1 i'^ %!B)X,.=0'x&68 }55oDJ2\ SU SZ !`yZMo$KQ|(刁kpdHP= QFź[R#I1(3>YU.E(ԦX!'\JP )GfBővqGQx&l)PQ4ڔufG>z9}tUi"epa5o!^8J/Zl3EEIȵzE |D9&B.`]hw@~$>,Zk^KP!FX9ʀՎDQn}$l *+KV46@5H7@4E4@/@R z]h -hOx  EU ,I X+HQт>Bp)#Hr-=0!g&# y]xb$ W$ #"tB(%ԪJ: WEPUH*J-QKJBHH)D5Dq2*&P@`?:E? fX$@ ̍ P\*hĉ .zC!`U*/T!J@?P]O+Ny2i' ?-$#O+I la@AH9@J 3rzF(P9d=Β 0*5=":]!u #>l/ wbTzH@XQa N"TLI@3D0RXbuo(U!`l*^"@` Y|Wh[XW{ ,p`p<?t01O!Zp0t%AÃM (d0ʆb(ب1G0GQV$pD$< H Az!HA=H@m@DkњЀA:!M*&*&<4b %Hi!0()OEAޅt)-P$,?]V9@ ɬ"%Y+1`TYA jVc ý ~ Q WD!H݊0JX)F G_ZF\ l ?,h0<"e]EF,l$xc< &e0pGWz89 393JOl t r w!rgK&{OW@?@?A=ByrLXNš ؀@A jUG<0e .r ((0/y?ǒ4dA ($(@"8OA@rx7Ar t$耦)v( CxMF O) 4[0@"!T,0:@GH i$%p   TfgbYo4t#q,@[3 h0(W((p @60p$琹qs !4_@0.#P) jKB aAe=$P0,ŵ"D0Ʌ(0M) Z :ȡ`,Ga醡! p$6krD@]. a?#C4$F ]e0"t`,_?8ħNN"  Q,M@_qzG-)ąT2O#%X!ن(\ey87 ^PJWM1ඎ$ t %T QT%@Р6 (  .m+HT:? &:+?W?1( 'Mp;\Zaw =nQGQͳZd(XAr0>meOpA;U8~k  )BrxGK6~lxHJ(E11@tEDIpZ9T!%I_!%P ȘQڣԡ 2 #5Wf1eD xS0`@6w_`ҕ@xV(^mHH0EM-ApuX=#SLX~сZ( /6TĴ^/u H$ Et'-,K0Mf(L%Yƕp6@8Adx/DP ڐ\B#M`sp ,_tBIm BӨmodpoQYaQ/&hJx4 2LWlHa;7(2NiAxB0 1hxABPbѵxꌥ+@fUG 8pZ 1 I`0!! AU 4N.L瀔w^V[t@Y z$ dBMBEԲsw;'}{XrnmGEahG r} !" uQEǴ-&n4O*_b-UcH(דGsBS4f0#R,ՌIʈO)EZ=X2 HAH "A :Ta\zMP GEB;@h 4iWpeoz Q5tpBȏ ĄRд%Ҡ-kF%7`xJ (c UhEHD;s`S:̅2"ؼMGs<0( %ɿZfm5(H0NU[ p6qMꀹX=##dz* ` #1D!@3F@P'Ad^~/B  K ZQBEP A@Дz_d"9t1htBN(@@ۃ PUhrR/E -5ߨ R>A(H7lBW6H߁-C< O~2> JCW0x8ܵ^zC.s3XAfh0 ?I@F)`v(ZLS>@ "\_TO& ?xI*|*_* wdXE^f˱`MT}@D5bToCAК2V"Ǵ*JI@6=p BJ&0\"ha DD Ea:Xy@.\b4P hCtx`#xFb(S pSl $cPQ1XqDRo 'sJ` y<|`,X<')e"oGJ9Ƈ P>FM (@( g@PPr-G.W]@z EQ@&U+@m db!-4"+o#DI8 %ePf_!Bl0 QO?Z? :!r9gArdO@PHP H.+% )$"" LpNp&E!@b@ b(yoBO\Ipb5!A(!k!eT4N (m aj" tpΙچ4 7@(; !T >#C%G"p0+p݊jpb"Ms"T%J cW:8YDŔO V%`H $ **a&S]BYOy+OP[OG`*> A1OSjHX O 1'7BcbM!~t1PdT ` D+d!TB$6<#}lr^Db/`eJGBp7RzP%/ 4`0Fh"8?44y$ xa`>2Wr';~V W!\r +.5vJ$,Ǘ͘8U!p!еpѡܡH-V,1k %@/,  (4EbN`PxS'W+H$LFwmhB^D?H#0ra"9l["Q]6}NmEW FD!,9do!$h&CBX ~(<J8lQDŽ$xi ?@2GhGڡrBB^(0`݀K@%#Q*?>PP0>#H _ BPB?'JP?=A[e@@Ɍ1]jA]آ%XIÉ $1__ J 4{Çaa@F@rsYz/"𨭃͡j3S A[a7'&Q0K?(G˗/XL":KЈntGj'dF9JI<W:^tOR(@Y5ha GhC^h- @¢,6 Y  ХAhg8D1{VS_L`RIIC4&P&ȠQrP@Vo}Hbt1+!,g 4j#QYd1} p,; _`7РʇD (ԟH@P_K #)%! kzif~[ACQFX)QF+A4*]}Dvq Hq$Hao@`8Y5h >oFhu$0X=$UCR! tpUQ{(Py8@\ U?}i  ԛt(b1#/ ϪtȠ=Rj(v`@2 Y` uX@N<@2E14@x:2^ZЍ V#E+F" zqq% CF.F.&*gD0]bX?( (IL ,$a1Z8"чP1"ZAQ,ߔHao Y]#ʜ(, O%AzCtڅ Kȓpr"Qq8e B4(Z1hj%F`%i(Kk3Q?Վ! xDʝca(x)%uBe A੹l%9QD o!ܸ |b 2\|l7 @ A UH!JRa ȆɆ1!n4SnʐJAEZh?0ae 4w0 ',>fZ#-Q@  @io@!yu3E)_Gӱ@pʎgd?Cg o!۲ab!O䁀DB   Pa1P! dh/A 0<tBROH+GY(PU5@GF^nnn_B\ J8Q]Rb+#q BdQпN??@OM #!~Hdn /DtE  Aky X.JLR hPH2 8pTP$BCah.P裃1ZaG-I@kO{ f)@G0@%5|HJ@Y."#H0q(brȍ !! Ѩ$"Qac$i*!@3u$POףeRBTGk:=lc\!dAʗj5w@ b4D:)U 6*ҟJke,H^A Q*qԏkMdBfuaJ42\s>A~5&/˖'1zR %HhD~6x),=c!=-߷$i}Wr >BJdcQ@Dk"n!!}iBW@M E22)JP`eL@訡)5!_pݏA,]9%Dε9gX1&ʘ:fRB;,)  !R!I@PQTV  tVy1W u$myxm$4础Ej(S@F,j\Yh +C!XNȮVr%kN? o8:B2bﮥKMdJ1F+Rtus"0@@AEj PbBF*J#Ɖ/NZ~|9w( "%BPG (ZƀE. dRpA^@ y4P^R%<)JP`l&} $(+:A o$"հAH,q/0FTP< u4b e)(s5ĸGƙ#HNͧ<1{'̩zpoEWa P+ .',wV`Asi5P&d"\J˼|eE£&s?!&XcP3` ݩ)!'H!(j4V |lG) ;ĖJF/(M=[)F GLTb}icEcC0 "K RbP>V4yDN0SWFK%b1i0p9tv AB9@*Q?(U8r!x"F@AHݒ &XON4ij4@gF"(Vanj)0̸c@aJ+ ec  AN(3/2)`Uˮ_i,'ȭ*遛0\)`1Yr;)4z};C )!$!S]\s}) w}@H|sْ8YXB!_XCOv t0B4HЪv  `&>xw! |hfp\4bH$"R,++ŶxO^x[ɨ\hj~Pa†Q?#.C\-#?4Hb )?lם8I{aToHFNrZ >8jk r4}:~ue=&>dcfJ{@Jg1-@]M@Mjh .4)@M X5ZіR.B L.&!@Le9 E}/CpCcHAE OiqBQ2y*?HI8*%1,$H  JQZK1͏g X3Fl<\sF E BUN;FGX "@00i"60q(^,>H6ؓXЌWL:[3נT 0i!dI $4CI%RbBD4>yU:L $  @d٘ P` ʲ H-*BAHtIIREP @@ @C3R Aq@%TȀBl@#$ThQ0U(!` ~8 8hnAh4Ka@!soN $ʻL0,nD$hbRD8nK` Ɵ T„ r p8ZQyٙPn@$!KQQ΄P 3Ğ@UTcz"A4HjȲkx @UPˈMwJam.PvW99@d(%{+P@9 r'$(Ġ#DR)81 u) BTHPk&[3j@L mEQI*F0 _0DR*&i'@3g1p QTCD@nAT2&4ZB(B Ɇ@ȳMX"2 ) ,cb{sIVI Ae>|X T!tO@l$`ť PhT H`|/FȣNFOóvv;;;;;;;;;;vvS:uO ~=@A A PH" Wy"@$I0x#(%(}P0V ht['zwl(4@NECJ8w"f~4b(0 /?}f~C@tANY Pj0!@t&ܠ ?]=PPQ@$5:@%BUYs1( EPw]@ꀈ<P.I*T) Td(BN tδfħ'S"(q!d@0~@<!@0E ' )K'a0H$L ؀ '!b} >`x0Q1+Z?|+2MHJ wZT 5@u $G - h! e&%Eh8QJ8Xi AW^a.YCZ:-%R Jx9w!WTА0FU, jb3!@,?ؚülM:Fg)0A:_FPS oHR1Ixu|*HC$K#`%S S ‚0kӱ#LQB'NA,`bUq>Zu䀞#)!X4Aж(=J h (hw~%DJV0|$^}  @="0CH b % D3E Ғ3X9 ?.WBXO[JYb!_zu Yqr@A|Fa_TRBWW'nC60mQ>U\C>1G7hiTk+ "Z)ptS 08b paq zĮ橘Љ~@cgs':'e콗2\q&$k$ ""iNJdswM E}4GJH"V%מEF-YںFF Qs5K15 ,UXPdti f>o2He68Y.5Т f8&*ۍ@h44Qoj5FQ̀?@HX" 8-l$k&IN]$EE^\X8BW!EOGͯ Xc&0{П.IJFDZhl D6#Kgu*pg"hNmEum#@0$r WzUf렆VG` =@$٦tUU- AwCuJ(Hi!S- (Z*h)Q j RVI|4(%Jo2SNt%U@ (.]D`UO'E䜓bLI1%ϒbLILc Q|20`1:%!dQՉ1R%?n1+x<.IQ w:LƔUx׉E|)Jro, BJR,`!Al@Pp[ dbA iV(Ђs(BD'm' &Ij3`C@P !Be]?)Cŋ R @E&C Q LЖ^! `2 |jdjM&81ɀu#TWP P@$acjzɋU ,Dɍb@B1e:FTyť* i @D/I`Ig^VJ!H 7G  `ԅi ~:#Hĵ (& ?>JhC?-,^G?Ner?DDHOһEfVm[p9c@(PI#PBFG̒VE"|\xL -A-̀?mخͧo?yCy @bbG!)Ԁp.Ftֹ#?( d|+_dv.m2$)^ M )w+ s?ZSHANhih=]PG&E!74s/1"A<@M / LUP?Ŝo(Di^IN j2nlPFL4`EBAV*1PQ)Z.i$di .sD?.z@YV P FԕKbgiw :`TҖULΆA=\ F0 $!V$[?WW2;1ii">fX\!"'Jp;X2 b*20("%'͒ ]AP( J$h%v.-(@4@`T) !0@RAiQIE1ꠢU}8䘓"f\˙s.D̹"ǀpA!B J j$Nv(b PW!R*Paj(%5Aί/p8>+O@^` ĭO, ~BO!GzX< dXh^ b! `U͋99`~i!܆O3dZ2#̞ Qɂ!I chGBUv]dF1EQ:p9Nt& nZPKB\iB:P$(EtPfABdRipj5Qj4 |@DH(6Eİ$a֠/@Q-RĠ$ɈKR@xR !$cR1KMv (LgL) C;=3 up9P=P9f24T P< P Fn`PF(A~^7 P ijkCDQ:`G%1"[oۧOn=ZyV0P `!@B#Q)$T_Pq~7oRx@SwU-7i=b`~8 xINpH(}Z@_BX ea!Z‡5ea)ap4EpP P-ZOhK??$H+)PC YQhQC07NNGASp,\ $2Pd 288`0<&'c?` 0$7TL@Zv$ʢ364bX Dh~S,ިQA:Cj9K%(Iv ]> C - A'􁢭CZ G a 3P_{:׀{-7GSaC(ĖdqSnꇒQ >: Rf6 zp@8,t;=|>ᲃ&C H\S`a Ŋ@A4nZOl°&ɻz<2$V)C'ʏ@>.X9#0%"GK>֡7Q_Q[PDLBCEQT~MO" Q$ [" tA\,n2ZoY`C( PLQD P|*e0dFAq10`IB ZW1@N@TëG q<~ ;Ljp*OD  Dz$#aɹIPn4qJÒ6lF1DJ $<@!$W(CtQӦ}N;YNvv݇m;q / (~!L e!@Dٖ>RDO`1B0FI $IM}TS%&"uȇ o)_4Y Qh j?K"H*=9&0B0D2Mk^Y M>`App0B D Jip XATuF8)&u+;,VBbT*A /ɧ'u=#ǜD OڨQDŽ""|ET?'W |P($,WT41}9Gc6}'t^I9&$ė= PEs' J4AE EXdZpP-]5+A‚"zS_~tU_P_yWGf8[$?ېFNUVpؒ)'ψ@ G!PB*M= Xt"̨FIB"I/O/r: ,<#0F"@@HDKHpTXA!qu@a0 Cp= xL$@ 1x`} LϤ$+eZ:0̠V((cRR_xP)Ad e?D@2 F7&F"R H+T6)RT_l0[PNh . h!l RhKD>=;H6 4H @(MRk@5@5R!x^_YnSۧOn={t 3'8E`a$m;" x^N'" "Ax|fYl'Gwާz@@v,B1 ?y@j aA .8a(С3HaAEOj|pƦ/lbUzC#,6nJ h!&] k`&Q < I}d"͸J(A@ Vj p r!\%Ϡ U1c@LP#1M B@ F(sųZD91Hc6 "cQ *}A]`Gr.y<WԆu)邟G|!Hz"nlF7(@d/62b1pQAm@-PE+yK:`B_0L$ A@$ 0 TЦ qUUx44 yyb ~adByy0 `b\-=Z_0@ arQ?XJ7= pbp>dFhdJ@-{_D?4 1,hH/@`FA~4ѿ ͌Yl`Ў 0 (XGl4h}c`/y~B|.B/!`rC\m{=g ACRDG(Q]N p$(E'^=eΖ>XLC (d TA 1EPPJ  ,i9N@J5D[e bZdIUą - $jW@@ CHXգB4ϨlS\LpçOA4#jR',q +QwXLG^F 8GbJxa*Ta,C$CXAb!(ȎgȆ>]&0ġF(J4yh2q@@ A Q< 2h:A4_?\|HG7oT;x =tD AP#Bx#,*1?>D$\@?(Eʡjq~ii ;R5[E%ɓ^ht9p%v9j 0&$")l CM^K<ւf(K a#}`Q KG# &q?q MRU@)}feFU<㙃z=/N@H&2CXB LZn}0+d Nе-X`y'kn`i iNmو˘d5<(0X 0BnqPDMm<Ԁ:ҙwg-eA'h|53zY GYOf Z[h‰$D"/GP Ӂݭ%u×ŋ8 T_ΒE yv\} (A@൤7Q_&%aCD&,* ϔ{G / ق:It{ <1Ų?003U;䐏WȀ/1(ruT,0,HE@EBIDЪ!e;;F|ȥx-5$C}EābU@M`S/fAǩУ4PdR ٫*rd1R\xlaGU 7`2 * n9\ҽh('vC]8 C4|<(=5,,!я8ۃǫO:ҧ&:|nNdVUկuץD&ߋxCʕ hA4t0.ҫZ&3Z(dHVhvI J9 @0jPJZ0Pq. QAWG-ZPWֹ X C(GSJj,R":BqBjG(<:dT %%u#)CteKA]V-@MCw9($6h"(AVX>jҙ!/׻mg4`gJYa}kNgz^Dy8Vh K؄9y_kol$p_?q 2G$` @8F!'Np2<` S| _YZ, ONFt@I^m>@yKr5N!ˤHAtĜesI1X[~c \8C{H@JrfB%*Wo"is&@P i ]j EZR&vOCa)Ĭ^Q[J$+! BcJA T_l43O>8\\f/A%8 @>BrvxP q[0>b&P}?9,/]PLFs@[c֫F?|,a#m12q*H5 @@@gN:`>CO t0΀ v/7@] OZ +T0*VR?KL[ T> CXӘ/pz4q$4F$ Q_";H= [y$̎[}xͧ N=`3h ,x N W38ʜ d `D(H~ Ӱ ߰8Ѡ,5iYYL@R#ZEj@ ͭ0>B@zdS Q(? !*{ +\J@8g<$U*JjН 4 bCT @:l *0.5kG I)K IڔM|"|[fWZij]dd rk/` a(wb S( $__ v3 #;wlݳ}zxZtXh F5L%?'&ߏbf 1+ 4|$`Qq>Kʽ`@Dyw<@9TPVܶ@v@u DS[P  b0 4B%9 d }[[_0 8 <jAGAHև`3_`^]Ÿ0` A0)@(c33 +d!gqZ ު`˟/`~haG EG3#oݑ-Gp©FX*Q>:Nc` 7_ !E/@%)^9J,h~&Z9}T1ÑqTPȪl>"Ap`Th D%E)vV@7dH #DCpHz! C$Q@ QBB(Hj.wf>IMRYڨ@B A/EB"FF ABɈSVw/@@ LW|zm m6Ͷw;wlݳG`΀At.iwNr`"+JB7E 9$HS@_`9»cCp0|@(  )J1cAB)P]]*R-@?_WTAGQ"I䕝 (@=\| @P((8.tiIDyA09/zDt,BfATX. 2`T!K6cl6;;wd9eq% $8 Y@a ‰H Q#%Ʊ )#% &JN:tNmBk ^` FT/!Q"B/7@ RDRC(( 0  ̆DkJ~p܌@~G$ PPE*9\X(N;08N K ۂw B Rώ 19lZ2TAR K4pJ?ILZeH1|'(P )0EizX vV%PhM,d yydH6`bn\@\L@  Tg(Nƈ ?? ),QP@`ffw@lY`cL !($v ѯ>ˀ,Wf Hx-PfIc`aɍ.*@ So+-Z@>QA B 0@SWhJ9hn]c0@:1re`Q%tyu-g r w*0,Ei4#I#3 +1%ϫۡ2m |q׈窸1]y\x>3@24`&dJ00AĒ*4m d '<X+ǔHr򢯎~麀sc o;*~rc,JOV@1%(zZd #9rFv}jmMlZb"Ûbl2ts `T _@B?7;, @[((%z;:>?)&^ٱ[HrݦޫsBw?cAsVl@ЉKqN~AP&H- K,Cy BD[*OP 4gӴMKjSaUV4XSd7 OA;38ydi Axڅ.4t 6\>hΧc#,s0٤fMg4JJ-@BIr`["N是|@ъ3cH'@4M%J@T+ME(Bh$UÀX= TA F5h:@(JCh 29C(-QB9 T3 +,bsE5"@Ev&J@u}+ZZ;j9VM8QA@`C8< ']Mw䓣g. `I4"Šӱ~A"tV#\#g:ޭoUHKkr@S3QD Zdba)_A"թ+_(l|>"R4<(+j@ |"L ̀5gx3SlF )$DHsX Ύ%b@ jF )dPzEBԤyL Qި@, <"@uŹ5 R'%L$(Aq(y&(Í JjOE 7$؛g`pƣ#S%KU,tkB)Bj R_,|TT;h23dLnnd$=\E g$Z RTHxODRRQ#F @Q- !5bBCni9"4B[SqaB(>YANЇ-jrG , R_DT%T_|;ڇa}mh0XdAl^D'V.*jm]k톘%"\ $Dj}mu4(s-W(!NI(@_ausF.D+4@"Pi A$Q!`R,8YhKzvRh|+iG:b1ZVIL 7- S!ŴtiI\N}$j)Q4 @P!!AH$SX@!UR:|HVbꤊJ`@C8}SOu]dxpsci* I0ʢ apHex JUSb> R4Vh"#@% PGhij6EI 6*d3D H09gձs 5G(bQӪm񣅑J(wʐa#* $:nx^n m @lH̞R1آMʻ9JʩNZ/p Ⱥ$F Z RaZG,!9U(Bp UH2U6b!E+2.wVHHK!Խ "`cOx #f@!I("\$\A ҴP>=P -P#|$C?"ڿr %CS:5{)"jaE'gA(JHTh=Ia \VN"SZ[/!P@(@ Ddn,7I$Y.i- +rdBe@O"R)ƾXǍhuS5əPt7y :3 vڗyCؐ|C]n"ʠ)(=@I(q ')`$J‹+$5 ' t`4 (Qԉ]'ħ]4V`9R"#*ZE2o |Al *y? yvF@(OC $ # ްy΀H 4Ėt=>$ýBlP44A=B A?,zm% 1!K~^?,۴Ʈ<g !Ä!K̅C+`J?@TPf8}i7OPS?(!8 )}# @ /\f ǺD$jw &m =0 d2 (z⅔ @"3F y:!2%)@(Q( " 0I  *\>L B-$)@":}GF t ";4P'#b@gqL,=kjy!6XAIcf8.0Bpf}n ` C퀈ǺAv4)g}j2[ѳ) 9K?V`s9aH8؞ ]gŚtWG CAHl,0(1薒(FR7M/+Z/=&%5lFZ5+$\vL@˭µXi_?#UAd@xxM?(Ap>`5@fr{SÂ˞$^Dp zxR||䌋OZ$($0X8 ;^OR Ƙ ET? M_JT !HQRNHhDZPVEN?Z{:GzqPH9,I&Dc 2@ ;Zz{R_b!XDH\_帏vu,o@d 6ހr31a!TOabC$#d送!>(xjz|0:"tX҃)*0 G"i`HGDIN cK`$x1|jb+e)Bp_B>EAAR4Tq(AZH"qJ 4@)g (} (Pk(?U ce P%hQrSAL. @0AI 8 ^Z!xncߟ  ;on 4'^<B@x,*0 s!PZwԕAY-lV@Q3=T4> O ˅aIY 0QC Cp YT pUipPkKlXWi۸p>Q"5\blŒyQ0B j^2HT,A`{7ZԠ|x/)] P/ YTyu-6a$C rD$= ` !(\πA{@*(C@+JH, X+J-h(z4P}A |9I!*$xЕ'E47aN9UA)`e{ɁÙB#w1, TCbrAOP}""4_0ut%,&c@s "8hCttX $z^!MH<@:Xč06R"N(GM$@QAOM:MBw<@mAd(rH|Y!@ z"tC)Cל!ey bbIU%*10 (\ T#?- 3PǗ  <@9^BO<EmD?p`Dsb ; !yZNL  *a eFzQb1@? PX&tfР2+ F 9==p7B vJcU Pm A0&Ry0?h2$ w ># ]:GiyB*~vqO!B? {͏x#( ج fU +aOth4-gIFL?.`G W 0U PBi@Q?K"cՐ'n"Ys<"sF+|\+Wwv2?j@+IyP$5g *@#;"2Ec€#K@Wc##^K}⠎~ J'Zx s@%@ z< (^6p zBH.(Pt P@s(dɤLCH΄-Z@Q`J|#BqHMB}9w(P]N^Ǣ( XC"F'Q!PAgy-UFٹB0 nJ#K)|LԘ,_@5RuƘ+1ql\JA6g=m؉T1",Hb@Bt~NPA/!"HLL@$D8D6A T@=@h +$5Hj+A -DǓGHjj5@Q'p9G\Hb A8hZ7B MW~$SQ}p@R)!mE߷+< ˀ"E#G1 tW9 0s#@%FaKH8 qDh-"ar$(nzHPZ`_K.FD H3rdBzrl@LVdwL<H&A &"aFdQrI>Uо~`գ e ZR0PLyƒ) 3@ zDO$B$I$៝A?E#@PJ6MO!ܚmJ .  KLc ~FG b\IJ Ze?K[j1x @ \*dcv`?@h€¨ᰆss0ŀ@Q iG~1Q(h) cqcGԎ$b!~(A5Lm8@i !)ñr  t?@./@t\`Jev/!sho ­B$%ЦP*ų_`,PVӾ[)aZH4X@Z `q 7HGxPm q_61l яhF(la}ckhl7K4>EW 5!x8z4mbxM 5E+! F'#Cj!!!!0PQ  (aa/7߄aKxSc)3a~SȌS̸@ b{X#}~O@i3z@V)FR֘i!tM=:Q G1tCH``4`%O:-v Hk3O*?$@B~H44 sP)D~C"P(c`ؠ2#,0F\%(fvx݉0km*"Q?ϓim0s>U:H/\LA 2 7~f7 8L@ߐ !<^B #t  +;XQy"NXZ(4Y;<P$p<ѪVj6!1oq@" 0Rb/ |b/6} O" % p 2ȏ}BSx*(0ZS9@`B-,+e\@;zp&nZЎB0# NXjAB¨-CCRzѭ ,y Y1R TD r hHP +6)O^IUy܍@(Q,ς(*00Z h4P7(8`$.&AHL Y3ЋGa~C J& m?)˄!T"1yk"k:q)#BҤ0`p+F`BX1=&!Hej  0xyL1E*IH&2I̒DTQ0?%QPJáb= EG]>> > N+P } {ާU" IQ5"+|P7X)k$h̅CAxXK„Pq'd<ՌR|{wSܨ4tpC:TT Dտ7ʺ WS\ 3p@hoтfT ;XzaDF;Vl`0e W Ѕƞ%IY^dYhSh4T"J*XU*B(.M$(hY HXM!#AFC(hƌ~p*n(Ez.Ұ0A׮A[" %<MHH~1}`h:z8 !z$LJWR@Mn G.zZ\J@ Z=PGZIK@ HA4ABbLF_o>MS% lrwUA%1B ?r~ 1Cp^Sɉ&z2H@Aϲ}o EwNp5+QQA#XIQ-/ Hvˆ@HAp&"yihLր%7ʀT?F 44Q[ LD5tBX`S-Ԫ(HBP5>H=+0 @UD?C q+PADFF>9b |(@xXTiT~ЌL:5/:dޱ rDFN0Ę04 FRO .rK"̑"Im߆ժcTbB*$JV~M uY 'VD*2T,&CXbN 26y\"Z (S2g YwU4x,(- CE"xnEE62gA&KJ228kPa&@VR`T ӇK(,UO ԋ:8>RVf S~4*/D 41(M2_MAL3?#G8c@-iJ+-_r8Cɴ % t &4ǖ!y wU\K|%$B/#ȡp($haQ!YKrrBQ U_4 @`E eg@ d %R0X4v$$CPN=xX yc)EGhPH$2TJ$I4@ )T9"r(q  :AH4@He8 PRR@3S) Q(#E! PG, ("C x; Pϑ,@@mBzpGw@ػqK7.1,1бh "9V@0)"/`@Oe  p~jQ2CGˆhq@5(TqZ/4 J0փl?FH!C 8v3*. Zuߤ6A~RzPE_*}$;1HB7:xlgƀ 6@ci(ųĉ \ &H&2^:^8rI )pUp?/\ 'Iih0󁯨wtjPCCQ2%!!?efbR`*Ԛ""j_bʄ2 ZaS?4+L 0 c#YJ 4&A6)vQ8g'eYvF|-H8CǺ~0@t9GEJDiǠ&78F}Ҡ G `Bl#BހQGi#D#Nq J#bgjqJP 6^CB* mX;2@5@d4b$Sހӿ̉ o`Q:aQq A91$[3["َH ŤQV?0`I h8 J%~Y(&$&7}hCZUP*?h7‘ƺ! Cx$#t"y.AEX:&n$8V1#5`F⹡@m9A7+@A) ̀<id">69S`&2օƦt&PE,B)(RB^4P^TUnO5ͱ"cɳ&ҐAS:J:FnNP† Xd@ (OIY WP_QMAjTBv UJU#=p98=ގ‰ `n!hܛB] _`;cgPWQG$0@@@E*ǔe)"4RyybŋThti@]%)d#*@((80$PH )IU]\A$*Nky,@=d"N W_?S X :D HO[Ǜ>0 qp\hLbCŃhI2*y ܰ,A`$ #@Ag] *<I-x0DrK!<""+.@p!;NdT @h,JΩKyYS@8V2R?P8IPCV5fPCU]Q[|+?lN?iȧ4'8` S?݄`cvNLQ 0q EgNF\JJ G0v#IE;QLJ( pWq; #| hxBTFD 5aO˜;(bPDBMb %r* ir_s: aK.VN")Pj14B$*HQЛPJU@6J"A l[()@(*::P$@_WBQ/vłn]h;G GFV P&x̙\1?)i  HI1GQ!]JPZ@5/ABl ^OBL/!.s^p,Fj=! {9(@!"ňJ)BnRR`2KCYVP{Eh#-cڢX(9b0>-A ?N!`o~ v偯R1QBKAV%WbTR1bxQ' X#!{,DDT1#šL @]EVo!U7&\~%&r6< )1v JC JZ#w䬠 !ι!+a/y^svohB5ED]9~%Q*2̕Qk30U/P$ V b_}VR`D? W%:,aETrZ" S Ta VJ 1E$BE"  1c@0DQQ(Q&AgY@ehb JgӘBOJ0R֤BQaD (1$a84V  :$H1"A`z,GP(}BxnIb7ؕ *X1S-8Ua7 sr+QJئLh냸ҁ6"5 pE֔$ Z(Êr-C=JDcD-!]0!ij^,+s]AcjGBD&ƏP/E}** b$dr9? ~c U V#%⨧ (q#G HYL-yz_OY,#:b{MP傺ȌF@| 0KH vFԆ0#uPRVhduGQ )UC]C{4BA"ʌ4(bX>L)"]9I‡*v<HeATbTx $QJ1Ϝ+˦F+X⥋^|ʀQ|pv=*eXqk ¢^0I/ԬH8 @"4q@щ'FJo|2"JJdJ[oKH^ыnW( "."iE;_($]-RrP@eT5 24C#P Mg@]HdW ԖS\U,y+h-d~0 @5U[PA h #CQ4H@DOi`B娇{$D$-*< .Vؘ|J ?m]f>:Eo/uD+u%po1zR(qt^C,`1 SHp&~l SJ*12hIr_N?CmQ@(­#eUۺ0̞S`9נ TWV4s]8LۣKpNXXw1$ s_lq(ӮɈ#N`gN+r88‚I4ߜJq!WDR;ƔaH@W|a[TbGOš`o(,Bkp,3zeaQl H~cx$3 oUɤa ~I9g*Q w}a8`}'^*Hf@ }>P< a6"&D5. Y ňAՊ!8IUAX4="bS~Y~; FD($U#̆(AJb UJ(pM`UH'EKPAzXc ,[?s 9 STj)"b֍\0iRтC 9H,e(@2 zLퟞpL`TlE=i6*%a0d aX00*˃Cf dO#%Xpc 6M**V}_MiirAQQu01(`sCqD$r0 !Z-AL`hh@F2+R8zxu_^$C|?$ 5I2˔K#!iK2g$ CQp&B @\PTWb'ʈ (- $Gz! =` 2pc?L[z ȑ~ 0x##ɐ|x9p6@,WXt藈 To :=? H$= N PqL@K\VEh$1eF "5(A "8;HIa0(״X]vp"Az=@he/d_Cl\R8e -paO(CR ̘ s'px : W$|?S/a  ^Â)!@+0h0ʰSkEBjB? }~y|*! V" E" EBkBEr(gN!SSyKG4Fn%8d_Pj ̈ yPEr4K3hKwMI?Ѹ5'p7 [9sP]9˷ |Ȱ`W[>Q@B*@+>c ju,6x `,@2k$iOHz )U )6G0õ'Vm#|? 7/-ST.Ly! &Y!f>!,9ڕ?Šƛ(ߍ0TH5A4ap G1,w_8yh'nE,`TuIQ|0d0|Pgǀ' 1R)E HH UP &> " yNF `!$RHE*|n!!!!!Ogm!Z \UA & Gʨ$ht"J+9m>X k 1[LSO@( +P"u&$FJ[`@YL,m#  Y`1r9YpwLZ>sAk3C,2`$i  @ t)H5">VN^BDAAA1 z AH P tqf/G:tT=/~n A]rY VI !Ei D.˿B ߏ5@$S7av@I1.z9/T\p, r'qsT))MDq j"~H0{$629wf$l @+`3 ,|XK,!G1G`1siCCP.TChCJ} 45uqꖐ3Y-$ X a+y AHd $|zzgaJ Fʪ]BA'd< Hjd9A fHB"` A ɥw(@XSǢϒ+FD Dt]H$B>X( 'XO@ PD@> =C1,>g ^\ @4F%<ҘԬDFbB餰P"0P!pShJr!RƸu]X0! q @ťN?hqR? ,bK<$P `X@aL` "HZh~ŵ8x8aL | D8 \ F/  "D3Fxe$UꨔhNd (: 9it(@v@*GQR_AIeN,ד J"fx$:!R@g K|0CAA_ P` FupBWA R U0H|GHQ% +'Sۄ=G&@?6K;o&ri@ص1_xQ@\Ɵ(7SX#0l} B 0!H,8ARޟBdHYpZa‚(\ػ0 @w(?$ /f6Ux @' C< D8B\5 W,x( z&'  R@0R SQLL3l2LOz CAĥ (dR?4s֡I] EhA„3"w;ŠdqR,b0WJZ(o =i#6exFXB k4 +'D1(n~'5D$X5pGtH& [ Fb@" 918B#P/?O!styW#xcP!gUf{-0ä"$G(DLDt.Z@¯_gȋQJ#HVy D&ށ8i2bάgM' 4zBz]M& $hpe~&GALiD)xR6@} 8 H1r \$IvQm;*zC 9 0TB( @$ dc FC!XEz^:ـNG-kgL23C*M 쎏o7Ԑ\h ׿ YVu!\@`X !O;dIAYCC@U'܋ (Ae4RB42*@1PP84!ļ.Q1Vz82$R  ~%TE! -U@HZFӗu3ZBA6XM,CKR/Bh4AM_0aZBz ƨά9(:MQLVs%hЖFX}芇 t!)dCMyt A *|X7cU?*VU@nV^j(h;taU?‡ٰ! F]0^V8 6!bݤE? )H<(NfH` plB=!"?"" ܀/ILh8v JH05 - ly(BĠ` e(@`*$W`)v mMZ% ŒGSG b@.OhMO f] -*썢 $jl sGh ނ\w=]@4@`|C/ G)AL? >_X3h4C: h %L0( Q713vupTUD3j؂!kb "ǐ(k7S *[XA'5K<289;3)Wα MF.<!KZ*ҳsX $V$*Q*ViD3(2CDrh $BKA5 }<_)^ b+CЁuU!ږFj yc1%n=$U%D;ZD4!4D(eOa@bFEȔ`l& mg^!TUE#3P-~сtAypAJUNuG\? * Z2Qw0S[BPq20l\cZ%b$(B AB%"le GP9 GZd/(J!Iq*KT!^yu9+O5SS.|*;_@шU R&TA 1Zc$!ǜb0 [$Q+W $A(9JB (.*!J8 1DL8,y 4 6Q!2ȎDK􍆔(BBgI q%(X"3M!#Q `Fp@l(4+ B@h`)ԃHE HxA tl%䌡ePDc)JЌ҈H4UAlv0TVrkG[!|I@Yܤ傴iQv=.#TaDDvjMjR1@K* d!J` X(VJo!60%QL*;3d\i'dNM-UBP&*# &TFP_CaC W CU"()?6=1=\ʱFQI2lӝ&Zcϋ;Pч$HsUT~4 !(Py +4Y-?BET, yiP骴FPa3Z%(B}꾑XaJڕkl2V It~^|9$Q!O`H>3@P"AG0(A*j٦ b6A#L5 AՀdT)GTG8j!&aF@2xX@ʤ :B JT)A`ht|T $b@"X,,$|8 **,%HB S( Sa>O _* h%l*??bO1$ : #/t 5_~B C`f/FH-D#2HEX}o?lS0? (jд$b [A# FT^D_@Q:5$CB©J8]𩀬M$MAE xQÒ2G>O< ,d4 $nV;bd4G8',GNJހ@Ë ^@Oo;179v#\)$$ mGa40WPp0Qwq_ Q.\y* %VX`l> \0`#ДN^i|r_,9V?'i@21eTicF#E(wQ Ezғs33 "!UuR#?@@`~@^#l CUAR *=$M(Aj/#Gt%90@D2(JT 8cTZ4 B=˦Ut;Y!x\QW.CVnTkSc Z N@f$؀ 8,H8TPtRcX(! ŐñRdαQ<)/.W)r $/U;B"nDU (2 ,G#%R!! @+:~@0N!G51pQŒ(A" U]c`1O98}@ `yHZ5JAn8 B(V#$2 !vQ @DXDdz@DJ{)S%c)@rp)<+ʵoג Tu tVL:WtT j-1x  "b;0R0Q b(`Ӕ"z  {CEXI),R?|ULBaBF+LxgG"P`8i-(K|ٔUH_o36(}6FX D> ":Rz 'jh@iHǤPR]OEt sy$6bXb *C&5 $2Ux&tQRRrnAhRY!$p\A%AtXqv`c-5(zd,:O J hH?@* &#Aĩ-4q:!c4bJCRrzWtHV!"ԩ!{*($fA̕.RV:@ %A@QJ! dX;01 S|Xpv/З[k/.c`8qINGS,dZ2^yDɧ^j9clr@( $BD`i+B% pr @t4 o4S%beykx_q e. CG\0 D@8Pm z $  p&/[)1(H @QX/GHKD: C.-TRD! &D2(9Qa4#$4R`lLBM]$"B/ׯh!ICR.lĵ8^Uz9pqɔM Q"2,ZHʢg-ZlF^ ::nNYWI7}o`X!iZtP8.t! EP<@٠DAC(T UIH?A-Zb4<ʡCa&)vH˽nPM=Cnl-r9v0><ApD@E 0$@DRVegh X CNXDxn)f#"R .\$*axD 89ژ o>*UhYv$ 3Ì`]U0$ GNi*,R⃐W)JXPV H} :ꪔקŦ!]&h!:bB#STo7‰ n bk˚HT$3D T pQbTe GHţDL`D "!DaűL Kh`) @M4IQR HE,$PzH $q@ R 2(fáT (FhN Zu箜!r/ 6z<]hzRs ,̆DFOX`lg`2o(HC QkXkH6PdT@LB^ LGU%3K+N ^lS0U0]h(=q6@h!PѤ,(QTB$Ic@E -(@46ȝ .@ @68">a! @tX"gԛH bEA*P2IEADL+83$i @s24P8!XFfu_O]zu:zJrjP4V<<ބt_.$OG 5WX*4\WTU`h1Zf”5jCٴ3CHRyj܇u P/iDf˭qͫz Pw1eM%R/%vKfUt"r|Q h&p!s@!@4C0F!LL١爃l̼hlB!# ☂ D|'A>@o  B!X/j@5%FJ"S;%"4gdb`z)A`{),xEg`MBдV.@BhUQ,Hi@4q#5en@B/  @A?>hx-D단ҏ'FUA!K0r$'RT#aWW؇d D!I@oHt̂G!pK8A-b"MDGzEʿ04Sz&(L=@JVq R%^bH'hSV h (T2$@6 !Dh\*Q %aR4R0B\@JfEV!"qhĂqNх ui/@EŊ$4ՏTh{ge,dH.Gx#1R)R,G5 Iy+E5s(kb9։stw=l%K5 ի[@G6l:(h qA@FJBzQ1"pHLrCFLD:r% aHkLe$W>`6SBxGxY_R\& `)`@'QKMcAZF[y&]ɻ7)i SBjV(v-+XK[ֶJՁȯ1( fA@Pjj : >R*쿢" R5Ȼ:8B|A+x:#gQ!_˶Q(]QU/ԋ$'ΓPpj%kݣn i%h ŢZ|8 z=F[ MEEg-B9GpX@QK|kXK?i-H*4 H( HE   JBj[@4,"EXȭfQ"B4Tu7!|Th"$ F'.:~ RvPl W?}U':.ԟG˯CgѸ2uxpiٰ)@Q- pb71P! ء=c0(wGpǟ ? !"#IX)Й-5vH6.Nxk Q6bRR1x1ꕉ~EuB@C C4 WAY{_$S4` (Ռ: Wzބ [BV)gdaZc2K[ ōAk5pejҥT$hF'ձc%ȹyd%P]*!ꔨ{DžQ-P0M2 I(3r(0Wp61-y9ʻ]pE/{> aD_f.=0i=7i˓k=')~&襡v]"HJ B^iR+B9DBH'(mQvdB(JiLst)s47`,yp%1EYQE=V#5.D`(ʢ\V^K AХX9DV=^A `B<hf;{FA7 d# !bfkX!bQӰY"A$(‚X!L4j*V4@P!HA$IPb $BAdiĊw.SCXhI %h!YQc0(Qd1嫑!nÆFƄƣ@i|j$*e$F$ QceMPO$V@h~($~;xavĐ/fBGQ"g3C؛& H<C8N 8 ,@ @8Ro` 8үcHWͤ<0sV|f(4.&0h@58`IA G!u0= E (2 Aai :PZ~]5߈5^`qgZT-p5Y1Rח-SFKN/}9 >)zr `=ӁM0fw t B&!@!P`o1mPaW bq* , %LD"%lK`,ߜ@" Z@ ( %J"UsUDPoV1*™SHQ_A&ϥHc f P~8dvs1_kOislAif `N J@T҅%銟 )2n&/HRz$Șcm"z44hbd .* b*K r!Sg $#$uKʲ\Ir K⑎5ƛ`F1'^q8,(D%A`iI ST Py -@RZ/W&3 RH%@LT!M:QZ:$&(bB A@5q$I7UͼDYckQK =7 "B<D$k+"+W5ﰿW#raC?S1,4(%rg BSB;lC@e^i>&yn`23@vA\Zgr QV7@@?Br-YJ 2 } (NU@ h]6]>@0H:-MFLe- GJ@^~F@A 8d$=&N-?JLD!D`/@hqvR@8?*`5}jcH($v 5SQ E*>H@vAbp'| aABpnA%B(-j (%!@YWB P@Pm*I@["Z`}L ''l@4P|EIvRPp#DIg95R4 0(.U==E8J?P~9 4Kǥ]3 a!$:śzJ_$nC ӰB rd=J`7  FADA`aF#BZ#,kt*Ki|@k.qFh% CZ$upi\m4 bAG}F$t @6L5|!-ڿ#5撃w^I}jR!.TWdrna8K)*6X/ ĢGDXTb#d@B NXS q"zBaQ8zɤ(@)Hyā2!036 d+A@]9!H":cV݃U]s4+ 1 ǐ-8Ât@Ll)o?!QNL]cW q0)q4yyr n4%N*俯o@Mm =4;ZlQK-k[Y fZGhqb0C@$ 2(ș> /t0 K 0`I*`gKiTE t0y8BE9*8CL4:IXH@Ҍ  " zH3Jh}ر8sTFJ_* m[YHAHAeAD!HN@Щ h̀ W:+F)H`;UG221@JR1JKkm7Pf|.t́5 |M Жztp9@h&4(F}F(V@SA4N.&4SRIƃ$GB tH!A%B4,JRmX@V,X*0:@4f T BBzQ -@d@UAdn"BR@ZD6LQ@DjD*DJ@X= O"CcI2`5P\AOAy35P &-(J:@ JC*`$xP'Z7?PA@͟S@PYAD(˽6@;D6(OA Hjȁ @$@LZ 9HH;XFg y!2 L FH0Kv0)/ .(15T5G X{0?60 A;,bA .G| j'@ &j ©:@ (6}OhH @ q *K]Hӽd2_H#XU$whۑr 6 W@qVtX0G$DEAJ;bZD(B JF0  Tp %k݄W I2FnQ\AG D4k=!d|CuC#Aq8AkI(;9$&Ld،Nu#Rb~HYW"+&@W3D$$A.4 V" l1 q;jq V&39#fF$+{T8Ŋ R1/)yÊBT"TR8; W=rZ2GXb(5kWaiDVF$*;ƊƊV.*p!GPp&>¡(@ҘHbG(.o4(0"}cF!Р;L|),H! NKxd CyS@\ǠJgP CA$.-t"߯$e6 be#a*2IZnKfTDqȦxjÆ^-Y.% )IhGD"X*8G bXE!*btwVMc̱|X.$av" ;Ic^[䱚2: U%d J$cAi,Y*UX#n?-ң8E(QM7:_ؚ*Ğc4\qt̕XZ8\#F 3(Ni-ax Q+FPEֆ1t4N/K &vc? 2Q\쉄2@T!djFH p yvA`"S+ȆR}JNzBH0@ h䂃A vfb4x~Fq 2z4U '0!ȡ.%ƒ+ABժ@\h# ,?{˓7%g)HKf#H1,#mׅ4FC!Y- f߆I&"eC1@@a 1ɐ!baC5X3h}xFd# scp\AR#@ zUO w]܄j?\4v'9A2&/ѢE& f9]r#ʻ m $rZ5"m (a(b dPx<#Y:y#IU*c ") Q4k hr44 QH,ye4\/ @LV`(,Q M!\BdJPPAխKr 8w@HRCHc% Ak1ubpa`Nc5Ueu;JgV&hΚBHt$B)PMqG*00QJ(H1(@iDAB)K򎘬V(2WKraZCiU4B+*Ie br%$l3 2D) .v] lU h e4k4Y@0,A厂_@HSJP5̾]ӤE`B "UJ1kM  jhREDXTQ1BcZ$PBϐk9czR4ϐSjYXH,I!2#S88DF K0%A+BFJ\y`$CbA &P@xT-/]BI%5 #4#TH,ADDTє.jo٢P&J`(qYp6L"t|}aPdt#J  ERU"uqRc;\Pŋ1-^tcJP*4Pfj F9բQC(ҖV0Frg^~GhTBH ;GWhE 1` ](I (] o}DۄĢ$Wz>RD7#X8"O9hf7܇7R$bQ _ (8`()xP F Py(!1@hZB+X  )]""Sv+A(^?׮"y\$yy $|#&""B1mtݖB ji.1kJ.H'Lϛ0D@8#lA UB)qT@x @!PРGnXd:1?(q]S8Caok Z+jc!b@rE@e&-R*M :H4&v0DH@7!\n tPjtE#XHŪ:ӻ;v|wrDtj|6烋5ԫreDNS@lL褪  E? PЫRh,1@M)2B@4Ji %&FQlv)Q M6x ֘o'<#ջ搢:\%+E6%-QD~g r;Tb9ʫaAqO#1*Un%;K"U& 2P4^nXɁQ`  E & i6E:+/,tt:: BE7/HxgpBsjyqYܘL;mVÔCL(@91G@?KVmntt  m 5S3SP`Kju Ÿ@ H J}h* GHC/.F 4{(,IHKɩa^C^֕ϖ+G+ B W_B 1F(ٝbyW D c=]M0a9"+N N,EFY9iHR?g 2| *ФUu#'`r`<D<@5BAp/@b\[ d7usxt-nPsh`6ߧ]>A􅨜 H" 2b""Ł2e$Ġm-UK)1DQR3a5-jDHWngZnj!V#p#D)C/:_VҦeǓq1* (B28C AdtH^UPeRq+LAtd) FS-XZ<9.4Z'0Mӫ 0 Ab(*S jƎ@EaU$@ ꔡRoS`t"PJ2@(: CSIHvE 1A,Kv5 -Av-U\ *hUuu< q%(AC(-CСar1BgC1A(>@ACEqӒa qrAJͧ]Z8Sġ(`:t  @ hĜLAp!uZ$_0HPpd(%/jR@sqS1$D+HvFh1MMV(@8\QnƊW9QG:?X0  @ D>3G308A䴯E|P((%AR朣x&7 9rqST%G]*K$;zQ$ nA"EQR, QP6@kAq'py"!ŽA! ]:&l,.@CJzT<&DJ(P@(t%!!p~% 4B~H5C(a@VS[ _ BAIUF |s`eNY(,AYܢ˜NTR? lC+1R  ,BΕb! ej[ZՂHB({MC^ hv.VeAT'ٓts]S3KDfjX  ( rׯ_UI"D կ ,xoP{lqMd7|i@rgI"܎~׫*wkB:1hXij3: ?<UTœ @J-(A LZ&U!m-5+hwZCB1f w|/H\b;H. )Pp qCI%#Jc!ZR%E*tB_8p(ICLda@6KR4bX2JB:P+MV:HVJ` $@BsHZ05W7R% GVxis8!,G$$]=.1"`>I  i,i,AXKF ԉI``j@h4AHYbaVaJ<̑F@$_4@qopq4+IΨN{qBĂ 05pM7LW3~FsF(HľqXQ#ԴC9%qꊬaňl!gJBVKT1F}LqР x>:!#_XZH!_5@#?7@̓ [lexޠ]@Bh(e-/U8ԌORI( (Z:"7UbAZ@ 5@i]q#+ !nk9NCoCU0A`DŽEs+&D*:Ox31tVWB (WHPXhQY+C.pHK#߀,15_k:,%~_ 2N% VqBlT[r jB\ ZT!POK-mAWxHe"!Py EdơG4 L\R@ ?6P<h/LFMT r $=]vmʿӂ`<6O,A$A X@b4B%|S3D; g86 E PIj J>#CWI+ 1S@.a(,?d>U~OѼk40 (07)XH!*^@z&L!K7(^PfꁠR[8T)cD+3,$Q)!ֿȐK*:EHA!C*Q* nsbLr*AT&_ 2@nNrbBK%0_̫zz",=-*sq3<2S™"ÁӨiWk2i >oPmG ;C ?{ P`PFל, 5.M\ȝI-؋E[ϊ 5Oa  ʣ,\PÄ(H]B  _$@FBvF,qmH ,w@N(B1PI]Pvv!} :A$D݁(@ J`q(- H X J@q*2JUS%LT xdg!B AA I!: !^H\9wP˒-?1H;GѣbG6"/y !u(x(\W K_pqBwgR@jewAƔ,N,%U;@fѐ(EE(a`F\ hfD(OC/a}~hy¥K*3:2bQ L8CՒKGi+ G B]/hg")N)!h+[HdAaV- LH AĖ |1B:_rU[p-(xdZ`d~Rd|AHJ,cO(4 _i<K2{|&!KG_BsЩRKP,Hur bLA pд0Y-$ =@=pPQ\jZX2? 9 1 R'O@QJx2%7[uJAftqDE5'PL%kU"{w N\(hgvXjhBe$4~<0!o rQ OQYn $zHpRd $yr)% B J:B>T399gPCVЂ-  K|K`Lh@P0VY9k# If@ @R+ r^HfW\),NPv+ "c F;F|tɜP. 53šasT$dE$bk`Cr!PA aJ|%KVzT9+#E+A]h6U)p8b;H;lHNB+Ph dbgeⴄ]|F!}81dA0> /B贚9ljPay@-ez$ IFZҢzd[ 3sT$ʷdU,QM]XJEV<OH,"L^i@5V$8<4TdR(( Mq^H(JDA(y 7hA@A UJ Pb  PH Ti(*2$[UV !_.+D/h+4Q5.w ='_Zr/<"#gF<\iUs1+HM9Acя==lñ(MVPgjV)p}bs|@>  (k[KGy'E&J)d`[I-PgEIxJd,JCG/kkߝME*3U5 }/ OP^V((6L4!@r:THaEPhm 4cBZEe0ĭ(=PCA@:_MA0h5ttւ+RQ+ڵTpGxT|N C DACAxP6~*ј"|XpEx8R'!c9Ad"wDڰooojʆI#h@a)zy" ("dG$y^#ULzjJ2oB 3#M 0ބQ. AA;JHf!zag*TM!grHHT>zN$B8A*荬 "!TPE%$4}(@#Nl +K}JDɹ]_ 09O °"`Dr V{":W†do )>zDO@v]= Z]i", UN)hqY"!/bbM1LQ܁-1 "2&R"05BA^(\R Bݿ{e7 v(fRd)>$ WzHM+fR"0,5)gEY`DIEOX㲌< 80R zN>q%q i,?G c_ e7e_Q\xU3D";׮P .t)!STsrD%Bc(aiAn$% rBP p"1aI:5/)XƣP,U]j,JnӤYQ}/R H9F<!,"\1 ҍkh 0*< khx`S1DM jП/< "!o Q3$ Ogg#H- G 8WL JJD&Է򎽂gJ 2RWQX``)G"b+m춈E &48@d`L:GQLmj[\~0YǑm@p)J"wئ̺ǐ1ȄbJ:yjgPPVգEwI-(J}4+ʝNLRHD%)E/s  *ϳj5*d] hDd1, %w".pW $Jj0 @i тF" ƯҚ)'dy Ў?LT!~:$hJB4bЎ@j*sadV0*DR刅Hb`t^}X'@gExwwt45w*@I52T0#.(Ѧ` GJ="r-.&EC~FjJ@ 1ZP9bRC#R0͋HWDӒbbƚ:4)V QQZ(]t)5i7!Tbxtlx T.jrPǓ[, (g&[$2PҌхDsdhhU?ɐ8*q>Fux]x% \##p.MMO Q*܇deA"Sn)\Y̼26%Ghf =\щCO+(#̐NÙQ)>iV(Un|A6RMbhn>[^*,!&bW4 1^8#za1B 3`pV-* `\s}B9dfL#1xZ ga !'(O"46"m|/@:JAA7Jd'b!^Z@0R$@Xg  -YY ~ZEiV<4 5 'UZH!Bi*y0kkCʇXe5wHȌf.,|+ơ+|-2P̋&%H"Kk2pfkp 17wZ @` ):D% XRDְ(JM)Lf38fxgN8+JD%(ybDc¶BҪjMP ),$e0S`%А&m-7$<{jz9-bY-YR0is7˘+ h50YZ?Y"T-~ _:_7#fb  IxG"K(' !`e(E'JFOv Nf}CE $PKQPjzщa $ $bD8qkG?(@@MYx&`c0 ߨ9wC'yIp֠+K L? F4 BY Y $_2H rp?‚zC@#8@@D @9N” '`c@P -XAd$vUAj~F$!nw.r, Hw:L#_Yf!;f!(h$$ QphPe)"4V !&}ɂJ.rZI0'j*JR m+G!֊ R(\>QLiE܀HI.  L 5bq Q*̌~))$S ~h= _&@(wdX0T1H R Y@cD@M'+J @]@TM:P`tPaH2DIeQNPЊWʱ^<Q`S[JWPX#j$-~ q&D(a$q li0 b #ǰ EkVP:zHaGP 1P{YlwhEW4 = AܐJ@CE_Lb q M4 r`MSJ7,@ C4P 44k GRX,1^  b H$% TŌݫ6~'嬒X U,'UJp> EB4#acc$Pm PA*ІMj!BH[\BZ#hz mD%CE rSs Hge0+H~b=_ޑkqY TU;<`_zD9$QAOJX"NPyAp*DG͈[F+`D/Mz1m}fAD p[KU _%1EKgKL$ytJbhZcO) ;HǠc~'.YI;B0ΎVp*+ZtɪqDEtѢ;@c @]HZ+,jPP7L("PhG&;$,tz` !Q:IvxIy@j09U R R h%A R Ph BFH6 3B4C֎,6 Qj(j3IumkF\O*Lb.B>*wuHYMJU?i )Ef$2L$j1 dcH\ $KxYi9 HɦfS ?ՠh)Ҕ;+  ӫSBDLQ>DO" \qH 7D Ăj]9wvBh}B`B.F>E FWț $)JdQ ?ԥ@<8T7WԿ'Z݉̚Jdk%2IjL"H۬ES@y:@`(yEJH_S0P*KP 8t" -+Y\AOAQY'GqZl6_[P,[,zm !Rf `@ r ʦy@,HXE"$ &ӁŔ$. ddY J$GƠ b=l |  ,kXFS0̌3cTjc;1W#F%hH"C.(q!00Ae40ILJ$XKJq#L):HOUβ- Pa&!z8jcHbHΘ Odsg㌔Tw&,(IOw`4KreH5 zi:JGF(2HV QZu? Bp@ʡ ]0A&~ )&;G/T1 :P(Lf{&L2s¥ҏ ,&uEtB|jѦHi1N5P1$5gh3##$}=@MR]x]V PCKxGP![nvh/,FD"]g{:!G 2PKby !CJ 41Y0!T *1`+*g$` ,<$D?wo<(Q@ G 0dm2i b0c uڠ'Ggh 3U F  @4ED1Xiԯ I,4Y͐E_44ZI?А*,1 R,XDҥnl<:lW <( !d$P'4Ag~eZ^ʣ[,i1$Ua%B5ADo:O< &xV.N9HA]N`l6 ~`jnx_ n=[S/hTR`&j))RP% X/~(q6_B@ hbzu*$ Hb ]XL"3@Abή*|fؓ@.Q;T@ϰ `!_`p64Q^tjd (LP0'l"SkG%{ U @?Y`H ( ,0  APe }~ d,J* q8k֊b&-24Ap`q)i@6qvJ2\SA BzYQ "B#ajCtajCtBԆ RD-Hm!!*@wA_B:_nL<-Ps,t~KVY:THQ@4@nj鳠~>? ʀ#4Bi> c]? vR?ҝH'tˤvC1Vs2c?G%e, r\ÀI,D@@aP`U hAZ3B2Jv 7#!_<0JYox`ࠠ ,dC/^"\^ ,!nC0(AƎ[g`$ %@hHOr19 AO~F@8`Ü,Q ^`Ţh )}8J $ QiQ#A_E~ Q$ P%GC %! _zH )j} 4\-7|j)_O31~]4 ?ӳE(4~NwMGlKcDY NaVuߧhHLEs`(Dt JQ/.4kӅ$A~c>_,$kP!Qr 1ZzF,oG`6w @ Hd H$^1 *=!D0E'HDrICw"n*c[qB?oV K/$P[JH/݌a=ʀ傅0`#s $EK  Be?VۀP,Pc0F~C0 R"(x#Cn"&b%$T %=?2$($[Pb I XhP>8+0=!!C J= }em+ +ϰwG"W@%RkeF˘΅ :bӄPSix)%GװE`p(q:C@rl?@/{pAB]($ٌ:.HP,3dxHه`Fi`%FqBI05p8r,HGDpZ3+#ѠS" jNG_L+O*1 7䣋-\("=`& ^ ]p0^% t!3v@e/ij!d@QSJ!Za0ڌA54`Mo 6F#I.K  L*.HJTONL ^6@r? FV4 P!QPGD}|.4_pz~B(BJ(E3|W'g2?0 G8_B쓜4B?|@:!' 3ViH e"Yv%DUHkvG^H+@( k_f"*A<P&,a!An &xjAk" Jgv$BC֩&ݣ֑2Ȳ 9<, 9oHQ/bhLFrrp{pW;F O@ 6MH98w ?' Wm!Bt0? dA*^\*q-Mq#7pP}!LUfbim?1%#T_i<R Ѱ4 P֐@ @dSk(,8%HȢ@zѡF.,$aK yB@PUt4RF#`jT2 +` #)P(& !^yP|Hx BRz&}ӧU$Hրh01M6Z/ZGꀖg6q48Bk?E}D5S @E)26B|1Zމ:~T)%JH=/A^:Uj԰OzY"?}p:{ "tr~3A #t1X"zQVCH<S<- YD0L~uXrui EbN/jHmOI0((`$ H PmA O[AX, i53/E@,FDY0O)ɍ K.Q!B !!JaS)߂b lAFԔ@ /f A0$K|fEbҟ, I {'A A rvF g@ HUǑMH т ˍw8`vE^FȐ1/i(:j 18`$LQՅPQ+(EbaN&S(GXE=ɍh\vEY s<|@}4XUyHGCnyT%q$w4I@A24QĦ6TZ t %ڀ- ;eurh=rP)ɠa I JJ!BAh"?͂t|BbYVhtR4Jd!X|- &Mm@ eQ !X-B<i*>A(?!K%O dԼZ@d:߇]sx@a ᱉E3 | c@soS$Ul1Wa(6a @dx)6*I<g!'Za4o VJW=Fk}Xl($ADJN#`ELaotJY7@1lHDp y3z e(k_'gʇaY&(\(+LkQ!Ƴ0J(BD 00Z!N TywLubW-\u\9[Me(Y1TF֦.V0LN9BykO(ATH#AjoN) v $ Od`_uFQJ:u qHOYyQi肝^]`S2TbGR@Tt޵8xC,D8JDF>HQ'?i0^8O.(!Bj0էrg)W#t9P30LY>HMQM=EO6z$4P%WY(i!1k.0h6Lr$Ve3W𡮰c.1jm$bɀl8p }!rgFQ`$agQeM5K}#« B е+ ŏ!Uu,LBN`в P"h"A !8n!JZ mv(䡑̹fF砶x7iHW$!F#lhLkH[Z%DBHBWGXV?e,Eb> b KNLEǕ,;I#Q@J++fs+ΌƦ@-ЎNV%%:$LㅊPv~j1T*bU\Tf))qKa=@ /o(p#( qcb@701]7)c\8@RB-<! _ P ¡yZ>|= xS3BPfi0h PH`Pb-` $FxHT`j42!xd^:/ *:@TTXt]Nq K*ȡ(Q$2,FPX@Ih @V L!E@;F P&@6< V<:x3-@P\"Aˀjɝ@"qd,S4B@kTmP->SEiʯk^R 5$"#kSdB4팸"CzAŪQ-x*%9P( lAH d] ܠE/7E ~.%; T!@rBd\iE)^B )A e0mV^NJiU? )~ `4HbA$c)H3kw P+S@u1w h$@ PDl7VxErBԏ/hnA@ { ߒ4}/ ]xOq!Di@8B %  D@1K($1^AJgg)ߠ [ A@[ `Ly/ #D xt+ӣ1&+Xb(;Av+E+U{0(pu`(`<+&Br fph$8:Fhr4p3@DЀPܦڎZAJ=Fhp#z ЧKl3?RK2(x&"& K9h6NMPhE $}P(JRIq*f:(PH1D{rP1J +S" PZ ^kNB E# TaƫB(e1LD?D1We|ZI@\ᒡꑟBܠ *ˌH`(C򊉂S@bÕh[(M, 5|u҂=1f_1wR+@/uh O9(,&z3;^"hY)QF#G|+!k p@DUe2c ANRQ MK Ii1Q I0&WJg"&գT  'V)*,!A=?4@-܈`_Ԫ!yȂufAoX$l-J,+c>w&zQK@(tCb!OIGQ( `2 sHSt' `sׄ`aG&Ң~GUӚl?Nk0MXjM24)G Heˬ wVdPNGш\.Yc\r:LF i,'~ j9ƳEe%li($ p( qj E'Ql2R\Ik{ejCJNjY$?P|w!? 4Ru6>C)GnFh"(L䑥DT0s8 }YFI)/.3S3b" X (1#E ,BA1p& =c;eN Ú8˖|Q|0p}/N1UtCw{ .B{&b56Q{0y 5 `A%5ΐ%)DHA#r2>۠ DkUA{-h.ցX{ׇ &r U D :BcA(fx.Ri+M]`ygXuI5-s?H9D"b%YȠ  K9@ji(AM%2,W#֜4Ult|#?E<9?E]>S@+By-l Bk_RD+zcB> r8}x3oIH]<=CKh pbX<%*BLt1KCCm>=HDo'~\M$ P ޮKwsڰSH+ &M(ZY tK^YvDхR) /"]( wC 6ؖ9۵;dʆvs3 2"!bDŽ2@SaBt J$IR:Dڱpe"£!!x)G4sf B+"Tgd2+H RM?Ő(B?`hp+" 8~1"g<ɠand3҅Thx8y1d>&~ba 0G̖ <(L#Bt[y0W[|^J̟ZC\Y#INO"PV^x&"!,$=i?3-s>CCqTxRI'qq**Q"hP`ŤsbH o^FaLS-~b d>Oz!X )$[T#%bzf2Y4& }̹4>&EKDOtCYCJ_(caL %9H жW9x ; 'lO'gǁQ(& kr}aI0j5eB Q &2С $E{PuU,`up[\RV!E!MdoZ"=2Q auJv´GE13ȣ [?̵Rz3ȤNizE=٭d*~NHKuWW Fb+4 I22BC: BS0:-OL9\!-4`bj)e#Kke]HIc$]|*+u,l7%J%1%pOSĬ%#ۼj[BzbZnJT0@  HrF! scȚbXJ\ yX}Vej8Yd*? ]esn.&wePTSp;}!n[pAkkQ&*_"A; ]B!,j3$DcI(RolS@4N1C.FIP {P z0 hSK3CE!Cơ?:?ai5<@ XnɊ !k4 *rFRJ @4Qū:¡RJ(꠲y%ED$dǘiJQΰ8i*2 IhPxQJ$ +J8(QGDFA 9T5 IQE'!Z)H,%;@P4;谦`kBr<)r%AQu1 ?la҂"!aIJGZt֓C^gf.`ٜ˝ VYx?-$%dT$?iDb8 =3 ȃ!à K% \0 tw11b!r|(:CRd'$C'} ɰQVNnY$pP2qȷ*$D]Io( E]`Swh_՘huaO:v`Är B} [ !!jY٧;Qᔚb3E-*_D܉AEPt@yE3 `$vJVeQH_U⶛?»R%]wh %/.,P1I[ %R%Q*r5ВZ瞿_>)u[DԱyvE"{0DG8#D!b?,fR ֙?\vsu͜v0ʏ$D "MY#P/-IE8VAS2v%*3)S!5.G1FZ)!Z{OFy' IQ0'f՚%@0B F+*a 25#(ZJ-J24H$͂)@ BiFqe&J{}0,tׅ0MhP  )hJycPojbUň Fm1l};%+K"ZfcA('hiEIf,"--a$!OQCBn'H[=u"ŲE)Yd{4Io@{o| 26 Z旄fS$Z ˢUM24ތW`.Kq)68i2 `, PB  A,h?usXnU8C$wCiƎPyIVӨR)|pG[敓FO{Lc#%Kq&%A:,DZ!"/c( nm SW|pzisjT*jQ7f)AcYA!踖U;Ul\>2JQ`AzZO(yp>>;1+'k7$Hs< -O\ :$㕮t{㌼QVIn L EJ5l( BD, XK1#TXBQBSUHQga,ո f|&8:ejԊ ÙJ8Q!@2@x[E"R@m$JBѥUgPKQ$`v*Χ#"TU0`AMj\9D!VsbxΊK, K֌ *0a EZtQ⃋p;ST J3ȏ!PX`%ҩ,` ?6?9,&X$B?c1h#bPG=O!iXE$ =ƿAJܞ8.S)(QԎ0x(d2#}<-jŪTMbp'c“! 0XԼ:P餠!ap c./&#'V/D ^mzb!\)e/oN)RC8tpȂ8S ɉ@o'(L`]oE`*Rc@HZ+p5J)bH$H %E]|d@ؘ%cz a օ"x)da^}Dw3ȋd!sN&n͙`m*殷2pW_DI8 Y6癈pxJ,M/3qKN'a~ǫ2!6 (`9# 6_!">r-‹Q Zڅ"35ɤX&1{g))̣"}6)o> =gP-g i#` xeI5 zG* )QqOKGC3eɗedڐC $$lj  5.:(-==)s`s棡 (|ײrp +rgQ;IR[ffF(f?j"yMryhּtM;.L{͑Hc =*Q$RP9|I, b\v+s6 =,;Fw{NCf.*#1m#s&ֹIM& ՚ 0) #CJɡ<J*R5:@b!6z `Y.,4l)D1E,җP. h U X5fP+E!JBU%D!f$D!8ATW!jC$ fp!F<^!UAf<b)*T/iQhc'B_FWE|%{KrzPd+^u֎H;Lֆ"EZF#aXf_]tLU1h! ^":N/WsrFLHbLVtP0:* tTCBQs2ϊBƏ_VJ$!UJT& +> ZdڒDϘp>ZR q 5!mLbʨ, ??cELbJ ,4&WB P:eL9Hf`a1'Tf ـ" q,R8ȕKԓ$ %Hg$ZLS6mR'2JN$b SuA#iPx3R!C!;XBAV= Vz ٠PCf`$Ha*5SG Kp (} e|>@q!r<8 8ONe!5t,FU$RS$MO+5EJ !Q$8$@B2HD ) H0{8[cCRHPe5c,y@B B:Mi 3ծұ/Ys xZp9qG2u5Yv-_`E/v%` @ RQDY8 7&ʻ Pj<J*IYzJT=* H*`:ƠzHya*`UEiuLAeq9' *dtxA# z9Xxe|[,^4\Ӣ+TG @2v!)0vu3F5[ 3 1"cWR)C%D1Q^"b,NDB(̀!$étjA CeΆdH3Ll 9##LEbrC)mp< TxEp%n 60*(%xnPF^e!N:HSSU"su2w 6~D{\JA .b/+#cCsA6c[ȅl M2o;) 4%iaCh"3%l;K hq`|b$88BuOlC xaèt=*! O*kC$!P &(!$ 1u' <[[V IsZIηAFs @zj $cFJ*]J Y6e.]^K <@0M~AJR+k ֑RDZaVB-Z;-zBNĚqi3Jx?($Bv^<#hRȑCVKA+` BKȖ "B/b4xvqhMUV )B]@*Lҁ ЉHB"4dEy v @%HH%]8=Axj RqU ^_G^@(o\#QHHbRZ^JEiłU0%B1q' AC DR0 HAY_"|#x$5u!f<fXlAgXb D~^򪸓(0¿N+tme›.o d J_I|<So`hQ\K|l0@QH !*WJ@ I@w`!puuu>N" H;`DLr2b P:xifaIaFqZH!IW E  Q䅖N>""Jd5@| :*/> [%g` h|e26H%H" ! |dB(`GB:_HSғAc,hiha[0Aޥ3 j{IKx@G "Xу` ؼd"Ù%/Fޘ+Pyv@ `)G(,ʄ҂Wu3y v?R>:4/:sM&E/G$@Q89*򤯊yA:BR)iPB<w>`A,J $0<&HB#A;@@2@@C/1Y'IS (y`%AFUIb`L.:|;8Hh)6i Q%UB窉R)8k.|t֛P`pbDluCk] ,Pq% !Nmѡytz @[-#Xhb~T 9T <Ձ'Ѣji0UB EҎ= Jz "`؂DށűD,[i@X!yŃ/.,(AC(jIAׇ`ԣBD,Hij&ZUU/XLO 9/p ɉaPkL!3R91 v;1\XE,\,X;Ò@pƊ' 9Ble5QA F1^>r!`Ụ FcI@BXkS!BE"QDr3Ɯ ӥ0YW !΢:3d9 2!%2+͇JU*@.DH!%2Ū#"|/@$  YW:vǙxQ$-8d඄Z[V KA5Bѐ4F0KSya1g%{yYO^xOf 9!vWIq'#ʂI .*,HP$B#AI{{aiamDC4կ_ 2Rx.$~8W! T]#Rg@I,!W bK@hFIE*d(AA2+7qdP3uĴ-qi N|&~:I"ZkH΀?u0PБr7 0Lt#@t`"#%!*$4zJ:j,Xuf)ñ !5f1j#IJ$h`Y$HuS R%@ɴ!Ԇ; `f/` 6 DUC02mL%X'i dT!bdL3ꎚGiADR*.MI T `ZؖIq@ {LHe[E "Jj(鎄e?Ɋopt 4ED`c@<إ@qiwʛq bHK0?T䦖LC`Ve:!H^^ u=1aI(QK2-w0wPH $‰`)R<W42@Du8YtGṑKE PpRŒ*sZCWF)}}&N`R? OUNOUv@H]$#-Rw mnw_L0rPn`quÜ?DF N$ C9(er;b4aݩˀ",H$C _b вF HB? H1Qe>1oOT/l  a0 Jp[\Z): l`+F<`)xJ<@2~`4ETbG`X]xwLВE?},KF3h,4 @ tJPЬJnQr[㒄 TW3"ɜz,Q-xZ aآBH-,h@H>ÔC{xcDW0 Xq$@Ďzr~A| B8Z60x0k`Od@G_΀0v r?ʑ!D#M1@ 8V?U>jG~bpPjDHX҂rt-N>@)=>WP%QE/FgFX 7XQdQG̜# ߋHTJ1 $# pHp·*aւi "DI*?7YYrX+@)D)I<ch#+06?,ӥ.C|DQ(3  U>׷+J)# ɼoW0|/KgN#|Qx)mEJ$nXcg&0 N5נ za5~5>5ßdkyPٲ$ Bp "= MV R5]AS܀e-QXi@MUҕJ(tZ`ii:EFӫNKԀXiKFbkTQ zpDd`@hO 7 >0 mPIa%H?T@zb`/05@, %_$|yBAgыG/81!srqRMPF=ӌa@hV"J-#|CH?+?@YAؠJґ _xᙃE6a-)!BD@e..,%@cާ MB(\ u\boE(x d9U bAƒ 2CJ!҈iD4-XWPIڳBE 2 gBvT>Q""]@B` paŐr!HJ#@[`cL~ADATB0$3![hԑH 1"u0`O=NA* t} J hS Ϩ 3 +xCNPe+E"T;MjT"ؠT|X *0BV(! h y+p= a RHe!:!AńVH +`DhPB*dҧ(MlZ%U䜒髤$cB2&HBH)$ L|U"Ml*lb`h(@Ő,JD)Ϗf,4TAjLHOjH)eň@CCBd (Cx&b`F~MP^AL#J@]%?J?BxI'ա $ -/&h+wLrDf o6eDJ&L? p07́3@ L)5 7ǂ;'a~NxD`!(.ғe骵Wo A@Rt߇`gPbd"4b) ,R ?V]U9 rF^F $@P [f&iVP8n͂(TIG"#B e)q& 8- A24[܀e,.++A51AM_[ۮu@#OlGa.R3M\ a0fV0&@Μ(A&5<sl&t@_)xI 9<,_>M.:: I@&4+C ,xi]4Н  hev!dx|8Qͅ`*02C( ::t>/Ҁ:!T Ȩ. Pi7 Qi0"tL4Q@$b(PQ44/ @ & 8cHAtІLO0O4 ε[`0/Z&R?h! qR$QLKY kPt}r VOc <O"ІXP(!S2Z8|#`HH`3Au5`U7:\""4d;HaX, E!J#|> Py@,r^0C4غPCp&~Pl)Y8zZZAU/ 4XB^ZGh*_(d+<`^$CyB!P& @lACAXnZ] *20Q$C )>E?R%7ҐF"UGJGZP ;/`ODo5&o˿bfDɄüw$_-11c@sЀh̟CC4Q4tDdqk0řH/-J&~dߴGgD?-$F"@15ZFz;J,(*ihkII $  h*hZ.iOP! $M^dd ZA rAJCDP:c? DD4Q$qeb=hf~ B\_5!* Nƕ QFVj#Lq.b*S,keBVjLĠ,~X%r1@J]cA' 5gV00ha X фAUP  @z@PT AUt@gn ė PKbH5Nh\P0/P 1eBmxxŌ!疞K1t**;Ÿf][? q S}w@4\^^^"0 ~G"XY YwM裓  yD%Bk/pl\yPf#$5k2@`N]Q":i)Tq.E~)h)P`2_ h I )ESSDt^BtZm gfFZb A~Ø|AEYP RJS$+ShH$FJ*D6D9X H2%J*T$t5HH",\ԠQGT-PK&s ,.@$"BfHFh %`?vCyCa `9H*i<_/t 쀲m4W~ 4H4i!Bۿ PSLzͽpsb@w K_2bT0֯e Yu@ PrЂ'=ATI `| 5 L%< 1$99$2%[ DLxJК0?"A9Dx@I'ࡀ'E DI K  $C =0_~q耞7 @-EVw` PPheh]oC BB#U4iQxM5mϋ^mH`=@=ba˕.} (QIV*uO%,Aw$𐡈 jA^ } \y^03D(P /+j4x,P\"P_}$AzE$Z@ ?IhicqCFcO3(" DP++oqϙ_g`$3D0f?M`UtK_ 8g0ץ42_}% YQ`R38$ 9eA ʡyA//) ];Т GVZv2EװRZ8RIqV9F 8B;9>3/'Ӈ8ŏ㔄Nf!lӺ*4PNXB4CqXrԨV<u8$A B,Gh`DD (*0d`dYsCBZ 2$Jiѭv@@BГ"h(=Tcx3+K&$d7_UJZ{ViDIVQ*HzVg*g8I jptGCijYŚH\{II2l.SR=W5#@P˞_S<\}KҐ 3S)$8-e&DF2w1:7:*rUDBl/#F=}/!p 6g* "(A CV-P:ihHuLLp Qh(@u (Ys1@2h #b2"+>}1Xa 6( h;>DtRE ʈ4ς v>E_J yzPGBXBU#FEB

B U!;^N"tҏ0WkU4 *]`s-VSCoѐWN#CԈ(ԓhQ"k2G̳iA[2 B ~aNҟuri06C FrA$5h<JWz62Wҟ)g8~Y0~ !k}pKwЧ3"(ξ. z7%:WXWJ% :k%R r : HD(bl, $ `QU;IT0pQ$Zq̌Xd&rI Ә <ՙ!n20\ z\`TG ksNE , !Ӱ Z  @ )JcH CQ@J%W"9˗ ֬PK,WP VTb* jҥ_"B1@,q$$ ( yc s kW/)t%Y$i gE1$z%@!T!dmҬF4f3iIlMID<)ykCb/ ]1\M$F#Q k1%8L8CTL/ C % AMdr!U X@ S=EXAvG: BcBD+#|n#3 s/RU%,9J9+CoCLKgPqPI qr)&i_< )CgkZ: B{ҘtLS*<<{AiW[aw.ha MJZ 5*IMGGQT預DU0KFI$%HInA(ɊZJPU Fym#Lr8PP y%#^(JoÀS;Ta^~QÅ.W&q0#1%/3@$`PRI:氥AG2 <8vtȣõ,љp& Hc2fSFAMC*aTT*24Ѧ#%Lv%G788D2U;!QO@BC + !✣%Y[\E`(4IP.x |3>5!YTf!Д!LC aKr ]a/}'$䜓`LIu6HOPp/Ac@ ^A .CaPV%dl"%zuB8ɐ.?Nxh%+sh)rh,֖֡![8%@-T}OpP|uIDFhZ"\PFȔZ+ݣ#Jp|\KdR 'Ȍ7 CL'0,T6ʚ)= uMo$u`E~NGh*> by=P*OS0R6Ki?" 0y'Z':yjRX//,CJ;4P3EV]nW_$V@!&>LS?]Űʓ瘻#FF2{ UA_d59 A#"IHBUюKYx*)!l [*3!xaE$*/LXDq*0("ѥȼF(1 vШ-YxpI$$?؟Е#GQ\bxIa%KM P(`PA! a102S ~8b<*|Oe7C,"<>*ľRP\)T^%RmѲ$ "frO A?ځTYxSD7~M!%L4AdHYI$p}-db^}Yh2kDQj>a'!#$pnfkIMhI QՍA2dSWD fH$")<[hȐEӱ׋JY YL`x}C("O\Ǒ]چc(@9I<b!=1YqΎבFk1N+"`ZYň;!]~;I2( uwR$|KOپQ;2 :QRH+̬@i68fByq!1",aU P%Ug*`EROѲP"k]~:&@<>4U}WִƱB܍8?`¿ځ];HH$sCq F`C2,JPТ*QuJFDѢ(!ryHgNTB)DItז$\BuR<Ɉ "ǐRgҪ!)Yͽ3$!C<F\ fFvSyhc1RVcȂYEYhJ/X8B5RA "%4 QG<()J: Vg#`Hi3&"RIl  X :-S>d #\eҕYΊ))4rB2UӰB2MP #9~-ZIKEJ+$84BqRo+xF=ҔbW)`3cHd0,%RON> `j60J i%,nqAٌ4SQ5 j9Ā# 5r@ 0HY5@@d# PY"H .@`U@ u lȹJ @ER$\tQD 1KR44:CJu $ҴRe1cŀ *@ew Qi ZDaT1 %JԿ/$ƺLĺQkybXZFq,c)/HBZC%DOE]<2G R"?JP"E&=-ӄJU+hXlD%vvo%P*YOd@+:[i8^QN VÂ5 !DH[13/PKB3`^H8jb0BU!kFSJqg˥7PJCW^BT(A2VyXg0M@)QXv, C(&Tca+@,ÐAN%Uq9G r` Ar 4Џ M$JHGZ^]dGhƜ%qWca_ IC"`b{ )u(*Hm0P „rRIEukN@Qbqe*Hi",DגG.O906A#sB TcWNcDF58qPEQ4BEDpJbjVjXrK]9l)R;~OTJdDɇI%q9g2/!j*Y'K ) w((2mgh3l [&DNjGWF@׼tQh3LTW90c :(cu}'gB`vQM @> .H@ V "Dv.(J$ B1)NGrFJ %!(3Nv0[pQƵ5QZ@R+ǐ0 $B aVrDgM&peOr%LօDa!٣EC tESG%ULjfR5JDF0e(JȤtXJ*3TJWcYH%,@A"-ȗk\(²xaF 0{Ư=+rE*8Z<*C- +5MFzFR& -CGǗ!…WOZ0q2)- cEdBZ5Z)#!$"ڽ\2d".HPRBQ&X"5 J(P,GN Zܥ+7$Ў)P$D=i1N:Ɋ+@+LMN%U`Ir.-+QIQi@$`2{~frQ(jTvƒˤa'5fACN@ "Yd8 Z HB Vs1c8U"B""!tZX`J^CJS( !aK&8]cP1aj8XZ*1UԾ"JAjj bHArF.|(lb.FܑВ-IQ~D?AĂlX (+UF\glHɊ%!EUm0lBnVbH]L">d<ǥ$ie 2 ,8CF+jRgbq3)rO:=;.H9̉0l^N_ôٿ_ E#K!5JAb cBC.5 I$C!\֘K0$Y?Hm&cѕ }$g 25ni ۓU+/R5Υ9[Nq6f夘/a/a&@gOc8aF zQ#]i5L+\@2>xJagjUim `}A4Bj&K!JH(:\*y.4ΡWR VHчd9ԋ9G g\K"`cW J5UЗ+0)9HYJ8$E@P'QHQT%GV1E2gp  AF iW4buD!֔92J5_-JgTkɩsQ,Ƅ #M04(XH$M$ B !M b2+ZcLJ.45WAbXʭkJō@hCcF[[ -H08G5 @X,>5Dņ%q@©j%Z޷89&ȂJ i" @%4 ^HTҠh[\b8ElZW:ǎnvHjOq vl4MD)(ff0!ZGNgTx߂bL Y`8FR]bJc6;;lī(J+Vvm!\^m r(tq(ƙ51Z*$PL(L!=A`DDH9Z4 QBer,I sU Q* H+ZWM q"s:Yg aPN&eցP&T hPIgE( 5cjz$xKVgDBR cRP@S˒$ uc2b|ctbBQ]u5aG(qJ09'r/ 6b,%ڬ4qe0fyK$^5!7tkʹTcX4N<,i%Xԁ !a.C(J@YL #Pi*Gy(J >aR#!C_ # QJΧټ;}h,N^qEV@4"=3uO9^S @z*)- @jLT3$9Rz5!?C6T|7Zjb0 W*Je$gM8#0`z|Է3 ЬeG@NW>p\Ffcrȳ,V Plj$;ij%!1qGye@^r1j•JalwAi̟\.΄'%r3K-] 4MPHXG 2X0DMݓu NRJDExpeեSQ7 Ű0فNČVVg8~BTC&1PHry~\\XL&MA DJ+`H"Z p|Uǖ%E;HR e8RDkFV%c9Vks :2 / 5P&9򓔬bb B>\S36ٱ!O r1r =(A/~!aIBZLaR WAdpɼ` =HkBM`f]&}EnԄ3($iBIy&E cU) Ań0Yjɖ$PbPD`Mb44A‚D `q&!t$f(B qف#K \v8U(ys`*E#+]9L|r(SH!% agWDw;Cne">6(,P4Œqa **b+0X\[/Q"*$R~ܒ 廵b02pvoYđfMWBBбBbfyc 3Yf;Xx@3AHp{m߅PUp dGϤ¢*AC:q *r l55 qVc(dΒL5@ @/|$ː$u* ! !:M BVPqj4XmBHE E+C$=S8y`DBJ`J hZLLG"y+[5c R!Z;/-1  3G#y8y~XBR(XHXE( cYBP&Hc 6)H!PM RJŏ&j҉N6,ȄMbj"):WP"XPCPR#-qϚk / !#֐0ےu$tBdN2i:2^A?WZ[QHX(8cp~ 2Td`in AF FL-> Ȧ8):Wk%\ lvPW%=&H`j P .uaCl7QR$:A QBx9 ;CѬpkD# Ibg9c1@ @( @$8QEp EiBjGZC `rWCE9^JQFkFV'V]jy+y*B*c! J/ˈKGfǵAFDd!*i T?O SV!oa*i ̘KGujh4BX1'ԪF U`B\ eDhe8T]3ʪ 9kA4谅Ad )CIsTˡaE(+BE+-0$rf. p¡uSCPMsuRX dc<D'^PCWy#LƊ Ek v1N @r3T,. <@tBVsEb TA0IVh#*\Dy0c$O'B$ 4С1+pDD]1oY(PJ9@1k!J.fS\VUJF4ljO*Yɯh'IFHSbMCp|Y?"d`cHp8 8:03Y ڇ mIԀQDŽ](2L{}ڭڞ+,jPx= !(^Ԫba8XSKҤPӔpԡ% R % ( TB@Qƫ&2K0R,(GJv/)`LtOP&IfƑaHֱƘhL_(U<K$ObfuW 4 d3ibRN@ "TH4Y& H"r!RC TPkU1c$UZD,"P.Ee1´$r %H`,@0G3ZQ*E51L^egJX' Z#&>bcٞ`g= " Dô",[uK]cG%%Qek?C3`XPҵx Jfd7rr(1I [ HJ'@T!a4(x?l(r VI&Q6i 9 ̋ 8FE 64,Ak ѭE4S\$yPށY b:`xY hNYfh qJԉS0 xaeC$Ĕxс E6b?j8{XQ3`BlP3P(A@JBA%VCif5C E(@&]BRJ U QL//L$&"@F> 7 ЂqwhA̘`$*ţ)L!Z q,FQ:$`HuuבH==!%uZ"U,Y j3J⡱H\zy8 ̹B9UWrf߶/,!ۄwa2!ɪ !9 x^P)؆^_F/R!bYp??Q2h^b, EBD1ψ@vB}( h.nH@l~>F QXPHH\R9^c1!@SnQTK+*8԰$ZhfN?(%P[NW,`gV!ESr8+,b5sv@^A5d\I `0 XAB}'dr@ӡ`Te䲻תK]&l̽0V, ehHʜ UMTZz,j@D \.CK@*,)hhZ U @߅# yP\ªE#ѭaY I b4- VBGE8yg#i ƂoyJ"4 UJZ(, K"m*QEQWX Y!yL`%UAN$.A2 Dr9HPBߞ5ŶXZceH %AO"@l0 ,AACSx>j?8@g6_a"]Q氲DCIl,YMWVvX6c N0`= (HPJk7Y/IGL;H,-)xobTe x1hUf!Bo"$^=2;t"d$P$ @HDH #^XF"C"d L8\PbbȢ $H$V-cY(B*eXJDr0 Z,p+&A-e$@RB_xYh 6d2Qh'B] Q#! :@kSKpq b@h/<@AiTaljˆH#<(@aBt~/NВAMy@1X%B5^9!P!@c4( 5Ԥ!H` w/-A*+fQ@*؁CȴyQQFK5q+ jT0`F<`YUFSzDc'8N"qD'8LX BF'@)p? CGA v?"$8JD q#nÜkx$9Za'D0 % Eæ!F}v5V";g2 6iJpJiPVXj)QKLcHW18f8e[%X x'bLIb1 @±0pRQ(T?% <&2*G&'V@I-KIr| R%B_Z"ZfOtBs(e T(Aq<uRPco(rF FXVL-n 8FpG) F1%CfD^_2`ÀBs.cZȪ$ e4QRP(PP9^c  @ EA!l#%*% ,fbVļq@:ybb FdPJ@( B%jseJUFjJe^P!NB3BX_~M晰( AɃDs-rn@a@@"F$+~A@ @$P(( @ P{4@B`73@m2%$uDJ;JAACE)nFZ(j"@>8 H\aٳg`!D |'wo !!`408  aH'5P PPE*<藍k}@DX@ B#@&$P((Q@h[9.熺տpAth `fN#I K5Il AD@$ ""Ēk0gՏ ْ9B8G ;Aħ%= ak@"OE01q$0 Af< {P (U*AF݀;zY$ Рױ " P  zC NI4X@CDm7 F`G|@ 0h@F"aJX1 F#|'ޏd 8Aq3Z\? A@AQ @`,E @@@!^XJQO@E)V| C, P$ 5PZ>B@ב F(|ztJM'OXA$ۄ!4T@@< 3ZbBP̉bJBRZp&x2>N>[ #JPA$dI@Qœz48@`X"$>4B ZBFa (( :es@P4M>4R͋Ĉ9@a$}G% HC.cxPD YZ>J@@BUYɠ( M:5#ɐJ J&I=d 1dcԤŪ51HJBP@ B ;Cs%W+W#A ( G<3Z~0 ('E @0 @PU3*PD{PPPE)FXX1 !poJ  A @P(((QJVύʋx 4;"Y?'d.O:$$"@3@ f`bQ(dK"YԤ'1)hI)@0 ` : b''S G1 [;uK|P E2_1l@$ P((E*ÍAxPPP'R!P zC"/ D@!Io@HN"y?#@(  )Js@Pb5}@.BIG1+T9p|0pF%%[ŷ- HRB>`@! B"F ~`2̖O_̯in(@@` `@,ڶ7@A9d!8$ QKYP xP(4#>6d PCbHPp"D?TdS BDhu((*r 8:iH84Q6((?`7P1!FGl`K-!D| BA`Dh_9H1X<(  xg} <<` X2@)'43 @M4ƻ$A@ P((QE/rqdxL't_ԡp`q9L/B_2<$6@ qEKGtw7.2 D9E`T@( T F$@Ph(UxPCh@P %//BȆ%` AzAABR@P4: O^10 O8@kX@@>@n`fQ(oЧd%!E|1@ 0AbDL `g A$1E?RE{ @<@ $ pKaIi?6@P mJ{8 * p@`|(@F՜f%JHBP QK'VU0 G)*50BB1)hKB !(I !1BD|@Acd,>$v C#D TʑQ"ELP A@!:u̦V?%}̜0!D?q5M6 ,!O@ A AABRoT:4֠Enр'$ t J.$@D`= Fi%8i.#r0"bd+[+fh3&T Ab!0s01l}'8bA4@;%$V_F0 (@P((PVhAѣJ )U (8@ B3@&$@P N  W$-$- -.,QP@`,ffw.  #.  #.  #.  #.  #.  #.  #.  #.  #.  #.  #.  #.  #.  #.  #.  #.  #.  #.  #.  #.  #.  #.  #.  #.  #.   #.   #.   #.   #.   #.  #.  #.  #.  #.  #.  #.  #.  #.  #.  #.  #.   #.   #.   #.   #.   #.  #.  #.  #.  #.  #.  #.  #.  #.  #.  #.  #.   #.   #.   #.   #.   #.  #.  #.  #.  #.  #.  #.  #.  #.  #.  #.  #.   #.   #.   #.   #.   #.  #.  #O@F|``s9cf6>';$(QJ$x|X,`X,,X#` @`` Ĉ ?O@F|``s9cf6>';$(QJ$x|X,`X,,X#` @`` Ĉ ?O@F|``s9cf6>';$(QJ$x|X,`X,,X#` @`` Ĉ ?O@F|``s9cf6>';$(QJ$x|X,`X,,X#` @`` Ĉ ?O@F|``s9cf6>';$(QJ$x|X,`X,,X#` @`` Ĉ ?O@F|``s9cf6>';$(QJ$x|X,`X,,X#` @`` Ĉ ?d=+6đ8d:? Y>BYp&D1@FеPR@ &J$$R[vID'4z%gIz@`en>`3~O2y̜d'8Lx^ 3d7i Cʷ¤@PgĒU`<# Xdp)3_Z  pl8i!b11bǤ䜓@`IƖN.@E?78 C, '3yל`ZO߻b ,._;,-p R`"/@'P2 . f(-u͠+  , i@Y)|,2 !&Y~.KdY,t A$MU)$BxAuG=B5V`#AMk~^2܂ZM_(ӐsITR̚W*„ސ u(4e0]D$D2E4p%QpwRp iMI|Rr@hc4&§wtejAY&a  `X ,<#0F"@\*@!Kh)'^ _w 5g+@o@BD*D>`E3M|& ( (O dPy QA^>@4o@0(PȒ~ ,@-(r@ a "Kh4 `RP!1k!ֵ:@$(pU|>BoR_+T$s$+w1հ>4;kKP [t>. n?k֖=°8[XMijEOq[,ֺ ]JJLz uzDT?\M*%uaM[pjTw$$-gWf'Ք@_C8A/]`Ul[㥠[D(Ț }\St ?S,[~ξJtRO*@WΌN0Ҿ?~NJ c1cf6>O2y̜d'8N2``!PBt4w'nѨ@9K2He, | E]*Q=$W `eož"j'Fl~g?mXs KM7B!*hsVB=&bWH) B7Hpr"8|x ,p H@5_v5&@8nƉ uDB4Yd@BhAnXdge$$$J'$䜒C'% o=)՝,"Oܮ`Μ`2J ,H5-yIpA_+M|ĤsZcR _An6𓔙$UʉAw PA$aгgST:cV8M#e#k={&Ht<[CZp kFmǷ9)zvHB,Bs ,`=06k `JPMnO9 2 !&Y~.KdY,2#BL,hF#_ U)f[ke]x"Cker3ŀ40 J !e.1B}K:00%t@t s [[ HBW1I*KG0U1+{TI@`b ߟDT,^mȒA|]>E!' O9Or?xXd.oPH@H,$2UP2HR?!-7.DxFN9/DLʰ˒>$I]` ,?@,Iv:(-e_46iz,~p !IYP*\˱ud*9Ÿ@>Hu>.&$ht0`,,YxG`0D" BAQ@H%1$@ҬJal+P4S J( AyWEDi2"K)FbJVLJR)S<8/H9AO][5N6 ۿnW" g'Yμc1'D\ b+[E R0<:tG(k]{(=4DTJ ?=l 2 ~L B? I_@@4JIP_9պ)@ʹ5D(G'Co13ts! /r`?4 iN |V`[`uO[58'kJkT՘M`J ֔֨5#u%%֔޸78@eF' Hk 6p(Qyu`0Bm@}CհxG/`\5ڠE G |. |kdRjG[rP :/m8^&PdaBH_ZiRB*yяj9s ` ac1'd'&L k3 + ] Ph "b^Rׄ1yu3W&@"F+̂Bz *dVDt!,KdY,J؜ RCDX @ PP&]~4r1*;H%BhiLHB\@p (h*o)o (`Np}1Ȳ/44h[M&80Jw BhU_qD9R}z KWc B@X x1e % JR@t abŗGxF#@ @$|#~`LRŋ/y Ѽ!D. (/xL  dfOGc@ :q(h#(  O@F|``s9cf6>';$(QJ$x|X,`X,,X#` @`` Ĉ ? O@F|``s9cf6>';$(QJ$x|X,`X,,X#` @`` Ĉ ? O@F|``s9cf6>';$(QJ$x|X,`X,,X#` @`` Ĉ ? O@F|``s9cf6>';$(QJ$x|X,`X,,X#` @`` Ĉ ?O@F|``s9cf6>';$(QJ$x|X,`X,,X#` @`` Ĉ ?O@F|``s9cf6>';$(QJ$x|X,`X,,X#` @`` Ĉ ? x8x8 b8/58QP@`8ffw.  #.  #.  #.  #.  #.  #.  #.  #.  #.  #.  #.  #.  #.  #.  #.  #.  #.  #.  #.  #.  #.  #.  #.  #.  #.   #.   #.   #.   #.   #.  #.  #.  #.  #.  #.  #.  #.  #.  #.  #.  #.   #.   #.   #.   #.   #.  #.  #.  #.  #.  #.  #.  #.  #.  #.  #.  #.   #.   #.   #.   #.   #.  #.  #.  #.  #.  #.  #.  #.  #@ce+@!x&Ο`d@$=le%MUAM0.ȈIpɅ%e @tooB- QĉWୄ3ýGS D&D j 'p ІP\` - h1``lx`4 anС( S٠ Ї*@Th( ѧx@L|{4 Gs4=)Q2@mP`&%HX @ IP!Ԁ%Ē(P8j @>EBPx =UH9 I.Bƨi WA Uf]1&,@ h(툀hA!8as$ 8] -K $hOOp9QT,HH%@HPo.  #.  #.   #.   #.   #.   #.   #.  #.  #O@F|``s9cf6>';$(QJ$x|X,`X,,X#` @`` Ĉ ?O@F|``s9cf6>';$(QJ$x|X,`X,,X#` @`` Ĉ ?O@F|``s9cf6>';$(QJ$x|X,`X,,X#` @`` Ĉ ?O@F|``s9cf6>';$(QJ$x|X,`X,,X#` @`` Ĉ ?O@F|``s9cf6>';$(QJ$x|X,`X,,X#` @`` Ĉ ?O@F|``s9cf6>';$(QJ$x|X,`X,,X#` @`` Ĉ ? &&2?@ `vV{1 Ab7A$‚==OH0IדE==](MQ`($6UW@bB ap?ԁ9! Q+XqX,E%$@ψ!@gNp|ԝ g!=OcCKzc`0܁9+I[whE] |@Pdˆ@.' R⑀0jSXB`BH @%08R{N(c@JE;jXT_B hɕPi3`"Enr2߳"Op\a!@3*gJ0p`as1'd'rNIP F!tu@n;a Gь& {A;!k4𥃠qq 1;*1@@S ut] P?6Xj{i=` H'eH`;+~L֓QF" gx!I ` z}q\eXx.rȡD]U_z5g]辑KPJ\*3 ~t q!ZǀwɂAuIBA.(b8;!CjZP> J%,'J?K(ڙ 0D B) H{(t5yR 6t,KdY,J(0 j@ aQ?< ٌ9=h~rQ_a|@ld `nSPM;B T@_!:e<K{k=8sk\P ,X[Ld,pܔ|j.7!FGC@ȆY"*Xwxב.'Rf"@ [Z1`mTۭePPʹ8SUUGudY¥c}ֵkW28ư Iaw)x_*N6mkK2Ҝ\:rڥw.(L']8c[cJg4E(,\CfqBSL+@AHβA+2lzV@'>At8rl?MbjYA=^$z9b_}@|Q$ @* Gv8Ȑ6Ð  ID*:(ӈ6A0 vxP 1M#(G+}Z?𹳙f I͜z37b)QƳWe̳=L7 m]Hv٦`\ł ̗ޓH) Ĉ<1VIF84 =>fsrBLz2bc@K;$,,]XQ@_`s03d̞d'8N2qs N1  !yK82I,2ryit>_I ",J"ЉCs4ݧH$>LP-/W?_Ȟ$J z'a 1 0g11' z5#= ]>FV5#l:zOsu>ybA>h3m[,Ē!>iuM@^&G]pTbnpLl})2U`[H}CoTп1EJ LX#L{( ~(.Ku=H@H%R oa>s)q ( q1,a'19'$䘒01ڿh( |.\pd[eԄH LGDE4rc1Faf#"FAَ}$H*8GfH;B8Ґ tXbn,t>LH|Adpp-ea͟ ѵ;kP;Se)8c0 ĖC4M]gZ;h Q88vyҔEnAE4) ͎"jb-銱X: [jiNZV5sSZK(Vl3^ TP-"]!@)j`pۊe2q@B(X]J(g|$"h  QJN"</Hb!,L/"ֺzk#MA˜c]]0tC,].K%dY*#@f)% )Vyo̧4|T7UۈFVN_Ȉ_d P`B Z^`iB' 8M|4sP0rBj@< ChQ1@ 44h[造H,a#DFhGb<"JSiRFﯥn1&P (0E Y!o~{D)~ѤDbD4dqg@h+hӼ{aGi;!qDp)*CHJ Qq&G,tB-QI'*~ /RzK+[iʽf:SKW\r>oDP׭HU1,@ $>޾CI N?M0; 4=@UH E$j 3fW͏@ 'THHG9*Z+wGp" h%Łз_8]>hkk0 8%ٷg%`(YA*Pr7:ŋ/0F"@@q0BlE&W1t"˻|NpEV$_9X-' s2V*3 I8?+F1<VF 9y 'g-7C2$D`@܄cz_#r I Ѵ 0H4KFJAY(P<ՕV`Mf-C#wEH}+~3$sj G_NiIDg}x'aAi@! X>QlI1A) =.I#1=J$z|5$.!@6ܨTC#%LP2O*6|Ak^¸+kn$n)$|a ,K8s3Pq4cN4~[@/tY,K%D "hke< plMn*ЪRaFih8,A=7Gͮ_iF'u4:fQ@)a1b_Ϗ0$+ C:#j 4F~~!H Xtx P"I)%M QlQ3 ?SXZPuf/עBPxQ`B.#Z_vJdn^%X*ÞAOX1}A_R#b05 } !Ht"/T 4vLi`v(\3 FCUL({JQ)\@)t+ܝw`, abŗGxF#@ @3 B&lDÊ+fS'3\-gePlŽ@W z C$Q>}S(WDuB W$H}\|`F a0#_e06nyAF@D/O-_7[3Jv(OzgԎV1@ A)mtGES2y% UAM2L0!P SRޟP弟Ob]VH{-Yj)Ж$]+;Fhr}03XSb|0j.F(X+f\c3f& b8>Gzd{f t.H``͜ 4>&P f g Ad%9Gł:?4ouǃ"0e$SV0U0dPa10c01l}O2y̜d'8N2`x 5a]6jWVG 0#]i\h46@h^u3_Jϲ!:> 0;GSa>0.- ZE .[Q/9 G3z011T|O=@$(PL@a؍?`(pI  A N'E$F|I _ذR(F  j$cD?D541PP_W%5w0{@x !fz_h R1ve0:읅$HF% `&HA4cIj٪dqkU5cA PȊRlk|Gۀ(*kQm 9=J݀ X!t(Sӈ!^` 8A n}l0Iaii/gxPT`(Uay* ow~`abŗG` D"@T#&!&4" Zv0RDA!!A+'@(իB҄O:E1|0fZ/Ni<-x}l(,1HQSo0';$(QJ$x|X,`X,,X#` @`` Ĉ ? O@F|``s9cf6>';$(QJ$x|X,`X,,X#` @`` Ĉ ? O@F|``s9cf6>';$(QJ$x|X,`X,,X#` @`` Ĉ ? O@F|``s9cf6>';$(QJ$x|X,`X,,X#` @`` Ĉ ?O@F|``s9cf6>';$(QJ$x|X,`X,,X#` @`` Ĉ ?O@F|``s9cf6>';$(QJ$x|X,`X,,X#` @`` Ĉ ? nn X0+QP@ffwSFEd 2 DDHW´VR*EH"@ Ì `1cll}`L{w gx3@gn,O @( ABa0H$ $8j@d@2 ehpǹ@xq,@hCF5>>:tӧN+,``, Ŗ_1j @ A(J$SFEd 2 DDHW´VR*EH"@ Ì `1cll}`L{w gx3@gn,O @( ABa0H$ $8j@d@2 ehpǹ@xq,@hCF5>>:tӧN+,``, Ŗ_1j @ A(J$SFEd 2 DDHW´VR*EH"@ Ì `1cll}`L{w gx3@gn,O @( ABa0H$ $8j@d@2 ehpǹ@xq,@hCF5>>:tӧN+,``, Ŗ_1j @ A(J$SFEd 2 DDHW´VR*EH"@ Ì `1cll}`L{w gx3@gn,O @( ABa0H$ $8j@d@2 ehpǹ@xq,@hCF5>>:tӧN+,``, Ŗ_1j @ A(J$SFEd 2 DDHW´VR*EH"@ Ì `1cll}`L{w gx3@gn,O @( ABa0H$ $8j@d@2 ehpǹ@xq,@hCF5>>:tӧN+,``, Ŗ_1j @ A(J$SFEd 2 DDHW´VR*EH"@ Ì `1cll}`L{w gx3@gn,O @( ABa0H$ $8j@d@2 ehpǹ@xq,@hCF5>>:tӧN+,``, Ŗ_1j @ A(J$SFEd 2 DDHW´VR*EH"@ Ì `1cll}`L{w gx3@gn,O @( ABa0H$ $8j@d@2 ehpǹ@xq,@hCF5>>:tӧN+,``, Ŗ_1j @ A(J$SFEd 2 DDHW´VR*EH"@ Ì `1cll}`L{w gx3@gn,O @( ABa0H$ $8j@d@2 ehpǹ@xq,@hCF5>>:tӧN+,``, Ŗ_1j @ A(J$SFEd 2 DDHW´VR*EH"@ Ì `1cll}`L{w gx3@gn,O @( ABa0H$ $8j@d@2 ehpǹ@xq,@hCF5>>:tӧN+,``, Ŗ_1j @ A(J$ SFEd 2 DDHW´VR*EH"@ Ì `1cll}`L{w gx3@gn,O @( ABa0H$ $8j@d@2 ehpǹ@xq,@hCF5>>:tӧN+,``, Ŗ_1j @ A(J$ SFEd 2 DDHW´VR*EH"@ Ì `1cll}`L{w gx3@gn,O @( ABa0H$ $8j@d@2 ehpǹ@xq,@hCF5>>:tӧN+,``, Ŗ_1j @ A(J$ SFEd 2 DDHW´VR*EH"@ Ì `1cll}`L{w gx3@gn,O @( ABa0H$ $8j@d@2 ehpǹ@xq,@hCF5>>:tӧN+,``, Ŗ_1j @ A(J$ SFEd 2 DDHW´VR*EH"@ Ì `1cll}`L{w gx3@gn,O @( ABa0H$ $8j@d@2 ehpǹ@xq,@hCF5>>:tӧN+,``, Ŗ_1j @ A(J$ SFEd 2 DDHW´VR*EH"@ Ì `1cll}`L{w gx3@gn,O @( ABa0H$ $8j@d@2 ehpǹ@xq,@hCF5>>:tӧN+,``, Ŗ_1j @ A(J$SFEd 2 DDHW´VR*EH"@ Ì `1cll}`L{w gx3@gn,O @( ABa0H$ $8j@d@2 ehpǹ@xq,@hCF5>>:tӧN+,``, Ŗ_1j @ A(J$SFEd 2 DDHW´VR*EH"@ Ì `1cll}`L{w gx3@gn,O @( ABa0H$ $8j@d@2 ehpǹ@xq,@hCF5>>:tӧN+,``, Ŗ_1j @ A(J$  000>0b a$01a$̂0QP@ g0ffw`MTD2@DD"""G¾VR*EHВ%J( @ A(J%-a"I$R d !//y¼B>D @P(( сC|i " ߰moFc۾ky$Ⴤ*p>`kB* 'm]spd( ݈@ o@q&GFheX@ ~4( 5@*&5>L&p^؀(b ' 8} sP yOhD"#_ Z+EH"TR)T t#)S#q.d]}BZp4 $ @?_nşTApI/X|`<`gGxc0B@+P@4j*bZ#l``E@íI wBȠ1 ^12hRQ)/ضŦ-1e$H$H֣0/ho>8RW$pT#1A\+ a#&9VOd n`% S;1O6b-RR.Lj9^r)P=}`?+U\o3 D~/.8$pm(T_X0HtD,ȿ*+qPee_!BDUH[!LQB\ucҀ5qAA"]5 qd\\)CVENI"` )0L& A 8eY@DFOy0q/  5.M`8@vEx@OF*HT@,tkFOnQ@@d.@)GB)W/T'!C0X=R$~g$cQBuA I"fSc]BrV Ie!p)J(XJ(6?4 K;-{ӝvplrQ#CAH bR_miR*kI4(!HR}kBD(?GLER5/NiSRAFCF5>:tӧN:tI^PɡQ4h 5D*8pM؏ $bSC Ĥ$0m 08-l -;˘/J)@h3-N\I9'$$HB @o$K),zaBj!8`Õj ! _3n]T^.|C(c0.<0:"!L"|ԭc8V36,ApP~$4tk_ ⚹Ɣ "j ҈sİ{%@|Vv?V^aVW?5GEÈ$ 2sZ'i@{{sFSYQte @_2t0ZMg7Z &pb(% q'wg/!2ωOasY"0~Q%q }ش)Bܰdjͩ] V,m!CHtԭ͟u#6r,ns,*㌇ip(@H B!>VR*EH"TUCb8P~E 2-4PH9t8/M!y7@1jxU#`_$@  awhAFAlZelZ%f4BBMKo7sFhd` R) ?983spXQcY#K. n81/2,0,dd _gC9H It VfbXF)XH7_x$1ؽcoDF:=%ed`ѣMoώ:tӧN742@6Tݚ`jLB1`KB F  (M?{/5)C rߒYb2[c@XA"`,ol[#2܂>{.Qp`0{؉-u(&xVBԮ`( tZʂ 8uN`ih -D r+CI rbR~Ah,"9furb*M%8 F~1E V%?(y>2a;o=D|Wp㣫( =OijPD$#Z+Eh"TR*EHP&Ѐ "\dP&!^\9&X|Y1/"<QJ( C_ )~\c $_"ȿA ^ ă*gPeb^diO3"^.…O2MNnJ0'H$I`G'"Whu+ߡ4zK^a5?su C0fVi<2@ sNBA<@ o!EB-mlZb^DI$Y[=D?ک}RU^9s;-w}^X$ՏDQ Q#MQCiGkT AA<@\չTv2\"W/9y˯p 'PtjƯ[J|c>RcAܝtшDB#k [Ur (1vS,Q:fCc@@p,(f-P)LC҄+x[ ־Z!Zd$*X)&=4p cLɢmrD=:bRzIF8ƍx!>:e{a t25Cj WǩPCSG̠5 )a0H$ A hH"t\P r@!*E ׹amRI} ݳ#0` @0 \wJ= wUWyBHeOj5@ !NX1*:D?#($X8x@u,'ADe pǂ.Z\Eĺ~0 ok`i,`G \(ɨ( C 4E`CU!+!] pm#3d3 3|Nx\zP) ` IT Z"z зKW#82!H :LcHZ_[d:b%?.!,,X[N:tӦ! BJ :A-‚,@(4iEg[-6}ܺaSag)W.9mIn<*NZA26?/q2[63^&,zO䜓bJ$HB; H*}vkW 4-LULPQr^p6AR 2zUڕWѱ|1M5`*uH`a }hTL)`$Apf] 7 ?3PP05(0]V ڍBBL[[;ؑ| Z.RA%}/G@+ZI$ԨC9=2X5S6@ 0z}y36b89Mc ? >D2#~HAu3r\`cC>NĕܰL`PĤ`NgV_JAAf+@G`ò c @HDDhTR*EH"@03N%V_ ,2x0OPim5\w/2 .ȿ\?Y`WJ{l `N{B<\1@Tr}]<L“I!*!/|V]8w̷R_=p*ԤY!PEPT*+bضŦ-1e$H$H:l=z Y@P >*Q(PI8Q!E HjQ<` 81Bt"ڐ-zWy9y^rB+cܬCXE-6 xf &Z}.i?zwی#NN>Ub@ k 'H}-2i蔳M;:{)luށwLJq&]~~0PC;-ƍij =ݎZ#FGx2b)4JiMW &ɐ_6 4ӧN:tx6"*hH@44h6=O## dZJPc bdR Z n( L. f3pIWɋ9'$䜒D(P( RR~ zc)%I t[-ElF\K Q3Z3 ngCp 8<.^Ȏ#S TIvɵhȠ*D7p"$$~7#WHDs_Yջ-R0[i -jmЮH50Z0'ЛB`hV\al^ZATUSSsXڂkX-S6@N)ikPymf !v`VZ( 3h1!@` p ֳTo,pF$H +1^5!P_r9MťI\ A-6+,bP,Js@-&YE dD"#Z+EH"TR*EHP( @"9!chi61[PDßg!LaMISi k]?p+(TQt70Ox bc  !%i$s/r_SvYŸ+ L[:Bp b,HP)ƨBp 2B5cg];h̨hCYgJ\1ޮ*zGpd&='4ź J%%[bŦ,$Im?,.$GC5 r0Pȣ!Cď"MJlA~gz|ZE 9& 02~[8aڇ6i^r󗜺(AE^E˾s9aW @BY]mDG)k찎n&=8.2XM;tC4[Aia;d&r>=Xn(S/åku3X%e_ dJf/3$4 AEDX׍@,F'8U<j2j^Xžg K@ (O A H$ H5!eB"ΊPQo QY n, *R@j9twBK(@ƅnDOnF6F,d՞ !Gb TDh/ދͰ94 !X$n@eLFv:{=K16"Ơ؇q+C8{F$;$?}.3TJ5]SfCSjh[3zzS H X! zpu E5L=c@*t)ݭ]s_ LC!ύ|$@d_*q`M6eN㧑%  4ӧN:tx'J ¢h bkA'.  geX` bnӘ `4Fn"D^{Nc&@.Nqs" t&@@ТxB7rn-aN`Id G~R) u,Zݍ|X=v0\].+k~||tӧN:tRd, *P( QK -c"l</Phze2Ff=NrCtZg-:Phg lAȽ1fgOf|GSVQŇ^R0oEbOZ+rNI1%r$PBPc I|o RX0Wh0 %ڷ@%WO@q%(wm(ɗ*?g+Mw] 18 jg4h2O20!  -\[#~z+>mWX ^~" h ?)&Q}S0u#:J4a O |Ә- C[ۅιDW?[(qfaep%М JN[`%(͐k J SkFGKĹ8(;ݙ(o RCgq7"k0G䁑?nYqj/.`FilX)LL06{j*N=V?EAf @z`Aah |8`D|1`VUӄP&R"}&XB@H$DhTR*EH"@F! ɘR#9Y!!O!>D7WT -E 0bYDt9YʽBO!%MB@"VR*EH"R_ADDQ (AA {qҭ@S^<,5JKml[b $HI$^*2`! @kf@ P&e+.D\$- 0 F.. C|`((Ӣ_:*ՀРPPE/x& A H$ C D$:b@A@E ( i?n C@ >@X }1?{8hBo s30@ K04 I4CF5>>>:tӧN7!4΃< &*$ u!$~rNI1$$HB^,-݆,_382@| I5 \Zm@o\ __|? /@DD"""G¾ @:\u msjj BQ(pH)-=fD>Ĝ[4!vLȐt !J{3SA4 |__?|/ P PPE/x?#~O/; A!"D;cQ!$o$rfYLۃdFܚZLl< !t]O]>t.E ѣMoϏĀ2:@d=!H0d#F@#pC,@9ՀkaLxj|@oсJsC#I,P_g(-C #` 00 N 2̛QP@`ffw,  ,  ,  ,  ,  ,  ,  ,  ,  ,   ,   ,   ,   ,   ,  ,  ,  ,  ,  ,  ,  ,  ,  ,  ,  ,   ,   ,   ,   ,   ,  ,  ,  ,  ,  ,  ,  ,  ,  ,  ,  ,   ,   ,   ,   ,   ,  ,  ,  ,  ,  ,  ,  ,  ,  ,  ,  ,   ,   ,   ,   ,   ,  ,  ,  ,  ,  ,  ,  ,  ,  ,  ,  ,   ,   ,   ,   ,   ,  ,  ,  ,  ,  ,  ,  ,  ,  ,  ,  ,   ,   ,   ,   ,   ,  ,  @ 3̛QP@`ffw,  ,  ,  ,  ,  ,  ,  ,  ,  ,   ,   ,   ,   ,   ,  ,  ,  ,  ,  ,  ,  ,  ,  ,  ,  ,   ,   ,   ,   ,   ,  ,  ,  ,  ,  ,  ,  ,  ,  ,  ,  ,   ,   ,   ,   ,   ,  ,  ,  ,  ,  ,  ,  ,  ,  ,  ,  ,   ,   ,   ,   ,   ,  ,  ,  ,  ,  ,  ,  ,  ,  ,  ,  ,   ,   ,   ,   ,   ,  ,  ,  ,  ,  ,  ,  ,  ,  ,  ,  ,   ,   ,   ,   ,   ,  ,  P 4QP@ffw,  ,  ,  ,  ,  ,  ,  ,  ,  ,   ,   ,   ,   ,   ,  ,  PFreeRDP-1.0.2/server/X11/server.crt000066400000000000000000000020051207112532300166310ustar00rootroot00000000000000-----BEGIN CERTIFICATE----- MIICyzCCAbOgAwIBAgIJANbqtAWwlQZuMA0GCSqGSIb3DQEBBQUAMBIxEDAOBgNV BAMTB0ZyZWVSRFAwHhcNMDkxMDI5MDA0MTQ5WhcNMDkxMTI4MDA0MTQ5WjASMRAw DgYDVQQDEwdGcmVlUkRQMIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEA q7mxFgRbS2FYJZX7BzpNd4T/n4nEVDBY6YaObLjGpaB1TptzXTcmfDrDslTGwcEY hTFAC4ZvY6yOURExqbph4LSgvkoa6J722RjVPfshGa4mlh2SXvTiaV26VPPxddGb o6fbs2u029lbtBlpIVbhx5RN9vstNkll26oSZ6wfEdBNHQJLd2SU4ItWHj8zjz1f eGxjgChHihUlwcBYKDJsKFkzHZmLrMgB37KsGlXi/WV+eEsjgvz4yP7I3TL8+GsN MjV8fRGVEKTbKSmgunO67d5u+IaqUQb0Ad1ha1jzDQ+a6hdymrulJSIhoOVfKkwi ptTe43FgwxVRIygJP9HjHQIDAQABoyQwIjATBgNVHSUEDDAKBggrBgEFBQcDATAL BgNVHQ8EBAMCBDAwDQYJKoZIhvcNAQEFBQADggEBAIOdEDhOX2kbl02znltd9hCr nV4kRPKm979RKwBNkrEuwYSlcsjAHg5MZ5itH3wFOUo2s5pjt7/vMOAg+6rOBbIa nqr22/gKBtOmuaJLG1yjxDC2vfez7f3B26pKgxa/krM8oxiFdT9n8QbdxdkN7/D9 3RLU/aCfgrMzXxRus7eq3kR00jnSs6ggnAfE1E9gric3vFgr1wCzdcriRXmXDfUb hRq+4VG+ZWk16TwCofV5GVU39XWCv5HNO2swAdjkNXgI5e3tQbV3wWLZLqqYzBco iWulAXtoCGmE81+u1Ms7hLLzpXitLZSGPu1r+sDdkKPLCmOvkAaljDQ4nBz7fIA= -----END CERTIFICATE----- FreeRDP-1.0.2/server/X11/server.key000066400000000000000000000032131207112532300166330ustar00rootroot00000000000000-----BEGIN RSA PRIVATE KEY----- MIIEogIBAAKCAQEAq7mxFgRbS2FYJZX7BzpNd4T/n4nEVDBY6YaObLjGpaB1Tptz XTcmfDrDslTGwcEYhTFAC4ZvY6yOURExqbph4LSgvkoa6J722RjVPfshGa4mlh2S XvTiaV26VPPxddGbo6fbs2u029lbtBlpIVbhx5RN9vstNkll26oSZ6wfEdBNHQJL d2SU4ItWHj8zjz1feGxjgChHihUlwcBYKDJsKFkzHZmLrMgB37KsGlXi/WV+eEsj gvz4yP7I3TL8+GsNMjV8fRGVEKTbKSmgunO67d5u+IaqUQb0Ad1ha1jzDQ+a6hdy mrulJSIhoOVfKkwiptTe43FgwxVRIygJP9HjHQIDAQABAoIBAAVv5K54xtc1JtBR 1lfdPbSqDlnjx8aOnVIPg5TnqMp3sR8jBt0NsPc/+RA9ZOmfjoIxFAEJaZ9zSDJC 5BqmnxC5R1mfCQkSd2haQ+4pdFvWyrv4Bblh8YU6hXrJGn0LfO0KlIcywtAvKpsi LtTyZkWmaW2HeF/+pO32jYygw38R1wd8Tl6GwjOXwTF6lFACJXOT4YAzcfp3FKSB AiKBIGuMzozoSND7KPFNRrhGhNumJpdS5A8Fb8D2c/ZMv6Cq5IbwOgTfKun+Bz+s mFbnzeb1uWRqQbsVXOBBW/zHfuG3SU5qeZsaAyuu4DTy+LE1oAHF9uhBSHuT5C6i vCJ8A8ECgYEA1iaOmiEJYBrs25iAc4SjCKqhY0mwR3wtu3I06vmgUoML5fhPMv36 SvYQIqDyNw3p7TE6mZtw9+G+kK3PqhuJhogwSwg0a6o51RdKnhXH3/68oNWtKCLC 1AmR8q/Gd3FwAR3b49CuOIZ9uOiJrc/ejzKdFEJTDR1/TX1frWfZznECgYEAzUiz XxFf7YrGel7JgmfRD2eZRYngOoteFlg5Tee42UjeAY2Pt2aiDLk+2TqQEdI9+Xg7 LcFdBqcSNd8bh33xSzgNthIkX+lTDzx0SmKGfyxfFBJcY8nzsLvvnNt3YeuMeaJQ CPszwoZ0jcD46jTCjbrKhaLyEWmUkDp1O71NTW0CgYAXKF49Xpsz8FVyvcAOPeaf dkwzf3F3mX8ciRId4taqdY9g1AREgGCDoK5IAF2RBIkqZCtxFvUVaS0BWjpdq9Ko YKvQQVfh2KueVoF0LOjLWTGutsydzXyCD3Lf6pAstHCnPkJcFWHxrOGFkGfrCtKH a7K+0RlIDsuIZqllCBjukQKBgA31+MTpYJW+D1t5IMkumEgs6n6RLt+sZLyuSU9k B+03CGogn3qAj1rAKmcJlYywuKhDpfqpoNL3/8QMJUokpYlRCZWtTC39pzltCheY 9b6mXNz3lrLupBUL4vLO9iKBq28GO90wgEelbz3ItuTuq6CJ6IYIG+BVRtY8M4bZ i+1NAoGANXZjYnJYDnh8Je9SDxDSc5byzK7ddkQoId64RCIfNHqNKH63P81vjgnH YBIPtagY75ZVVNxujCF7m8Rety+d8tEFwfQKDin2EVI7PD2rOJra385/izp7HuBR vqxvLzG9Xv3cNOU2l7PttVw4Pa2i5E37atKi3V3Zp2kMW+KaKPQ= -----END RSA PRIVATE KEY----- FreeRDP-1.0.2/server/X11/xf_encode.c000066400000000000000000000075651207112532300167270ustar00rootroot00000000000000/** * FreeRDP: A Remote Desktop Protocol Client * X11 RemoteFX Encoder * * Copyright 2011 Marc-Andre Moreau * * 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. */ #include #include #include "xf_encode.h" XImage* xf_snapshot(xfPeerContext* xfp, int x, int y, int width, int height) { XImage* image; xfInfo* xfi = xfp->info; if (xfi->use_xshm) { pthread_mutex_lock(&(xfp->mutex)); XCopyArea(xfi->display, xfi->root_window, xfi->fb_pixmap, xfi->xdamage_gc, x, y, width, height, x, y); XSync(xfi->display, False); image = xfi->fb_image; pthread_mutex_unlock(&(xfp->mutex)); } else { pthread_mutex_lock(&(xfp->mutex)); image = XGetImage(xfi->display, xfi->root_window, x, y, width, height, AllPlanes, ZPixmap); pthread_mutex_unlock(&(xfp->mutex)); } return image; } void xf_xdamage_subtract_region(xfPeerContext* xfp, int x, int y, int width, int height) { XRectangle region; xfInfo* xfi = xfp->info; region.x = x; region.y = y; region.width = width; region.height = height; #ifdef WITH_XFIXES pthread_mutex_lock(&(xfp->mutex)); XFixesSetRegion(xfi->display, xfi->xdamage_region, ®ion, 1); XDamageSubtract(xfi->display, xfi->xdamage, xfi->xdamage_region, None); pthread_mutex_unlock(&(xfp->mutex)); #endif } void* xf_frame_rate_thread(void* param) { xfInfo* xfi; xfEvent* event; xfPeerContext* xfp; freerdp_peer* client; uint32 wait_interval; client = (freerdp_peer*) param; xfp = (xfPeerContext*) client->context; xfi = xfp->info; wait_interval = 1000000 / xfp->fps; while (1) { event = xf_event_new(XF_EVENT_TYPE_FRAME_TICK); xf_event_push(xfp->event_queue, (xfEvent*) event); freerdp_usleep(wait_interval); } } void* xf_monitor_updates(void* param) { int fds; xfInfo* xfi; XEvent xevent; fd_set rfds_set; int select_status; int pending_events; xfPeerContext* xfp; freerdp_peer* client; uint32 wait_interval; struct timeval timeout; int x, y, width, height; XDamageNotifyEvent* notify; xfEventRegion* event_region; client = (freerdp_peer*) param; xfp = (xfPeerContext*) client->context; xfi = xfp->info; fds = xfi->xfds; wait_interval = (1000000 / 2500); memset(&timeout, 0, sizeof(struct timeval)); pthread_create(&(xfp->frame_rate_thread), 0, xf_frame_rate_thread, (void*) client); pthread_detach(pthread_self()); while (1) { FD_ZERO(&rfds_set); FD_SET(fds, &rfds_set); timeout.tv_sec = 0; timeout.tv_usec = wait_interval; select_status = select(fds + 1, &rfds_set, NULL, NULL, &timeout); if (select_status == -1) { printf("select failed\n"); } else if (select_status == 0) { //printf("select timeout\n"); } pthread_mutex_lock(&(xfp->mutex)); pending_events = XPending(xfi->display); pthread_mutex_unlock(&(xfp->mutex)); if (pending_events > 0) { pthread_mutex_lock(&(xfp->mutex)); memset(&xevent, 0, sizeof(xevent)); XNextEvent(xfi->display, &xevent); pthread_mutex_unlock(&(xfp->mutex)); if (xevent.type == xfi->xdamage_notify_event) { notify = (XDamageNotifyEvent*) &xevent; x = notify->area.x; y = notify->area.y; width = notify->area.width; height = notify->area.height; xf_xdamage_subtract_region(xfp, x, y, width, height); event_region = xf_event_region_new(x, y, width, height); xf_event_push(xfp->event_queue, (xfEvent*) event_region); } } } return NULL; } FreeRDP-1.0.2/server/X11/xf_encode.h000066400000000000000000000020321207112532300167140ustar00rootroot00000000000000/** * FreeRDP: A Remote Desktop Protocol Client * X11 RemoteFX Encoder * * Copyright 2011 Marc-Andre Moreau * * 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. */ #ifndef __XF_ENCODE_H #define __XF_ENCODE_H #include #include "xfreerdp.h" #include "xf_peer.h" XImage* xf_snapshot(xfPeerContext* xfp, int x, int y, int width, int height); void xf_xdamage_subtract_region(xfPeerContext* xfp, int x, int y, int width, int height); void* xf_monitor_updates(void* param); #endif /* __XF_ENCODE_H */ FreeRDP-1.0.2/server/X11/xf_event.c000066400000000000000000000101051207112532300165730ustar00rootroot00000000000000/** * FreeRDP: A Remote Desktop Protocol Client * X11 Server Event Handling * * Copyright 2011 Marc-Andre Moreau * * 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. */ #include #include #include #include #include #include #include #include "xf_event.h" int xf_is_event_set(xfEventQueue* event_queue) { fd_set rfds; int num_set; struct timeval time; FD_ZERO(&rfds); FD_SET(event_queue->pipe_fd[0], &rfds); memset(&time, 0, sizeof(time)); num_set = select(event_queue->pipe_fd[0] + 1, &rfds, 0, 0, &time); return (num_set == 1); } void xf_signal_event(xfEventQueue* event_queue) { int length; length = write(event_queue->pipe_fd[1], "sig", 4); if (length != 4) printf("xf_signal_event: error\n"); } void xf_set_event(xfEventQueue* event_queue) { int length; length = write(event_queue->pipe_fd[1], "sig", 4); if (length != 4) printf("xf_set_event: error\n"); } void xf_clear_event(xfEventQueue* event_queue) { int length; while (xf_is_event_set(event_queue)) { length = read(event_queue->pipe_fd[0], &length, 4); if (length != 4) printf("xf_clear_event: error\n"); } } void xf_event_push(xfEventQueue* event_queue, xfEvent* event) { pthread_mutex_lock(&(event_queue->mutex)); if (event_queue->count >= event_queue->size) { event_queue->size *= 2; event_queue->events = (xfEvent**) xrealloc((void*) event_queue->events, sizeof(xfEvent*) * event_queue->size); } event_queue->events[(event_queue->count)++] = event; pthread_mutex_unlock(&(event_queue->mutex)); xf_set_event(event_queue); } xfEvent* xf_event_peek(xfEventQueue* event_queue) { xfEvent* event; pthread_mutex_lock(&(event_queue->mutex)); if (event_queue->count < 1) event = NULL; else event = event_queue->events[0]; pthread_mutex_unlock(&(event_queue->mutex)); return event; } xfEvent* xf_event_pop(xfEventQueue* event_queue) { xfEvent* event; pthread_mutex_lock(&(event_queue->mutex)); if (event_queue->count < 1) return NULL; event = event_queue->events[0]; (event_queue->count)--; memmove(&event_queue->events[0], &event_queue->events[1], event_queue->count * sizeof(void*)); pthread_mutex_unlock(&(event_queue->mutex)); return event; } xfEventRegion* xf_event_region_new(int x, int y, int width, int height) { xfEventRegion* event_region = xnew(xfEventRegion); if (event_region != NULL) { event_region->x = x; event_region->y = y; event_region->width = width; event_region->height = height; } return event_region; } void xf_event_region_free(xfEventRegion* event_region) { xfree(event_region); } xfEvent* xf_event_new(int type) { xfEvent* event = xnew(xfEvent); event->type = type; return event; } void xf_event_free(xfEvent* event) { xfree(event); } xfEventQueue* xf_event_queue_new() { xfEventQueue* event_queue = xnew(xfEventQueue); if (event_queue != NULL) { event_queue->pipe_fd[0] = -1; event_queue->pipe_fd[1] = -1; event_queue->size = 16; event_queue->count = 0; event_queue->events = (xfEvent**) xzalloc(sizeof(xfEvent*) * event_queue->size); if (pipe(event_queue->pipe_fd) < 0) printf("xf_event_queue_new: pipe failed\n"); pthread_mutex_init(&(event_queue->mutex), NULL); } return event_queue; } void xf_event_queue_free(xfEventQueue* event_queue) { if (event_queue->pipe_fd[0] != -1) { close(event_queue->pipe_fd[0]); event_queue->pipe_fd[0] = -1; } if (event_queue->pipe_fd[1] != -1) { close(event_queue->pipe_fd[1]); event_queue->pipe_fd[1] = -1; } pthread_mutex_destroy(&(event_queue->mutex)); } FreeRDP-1.0.2/server/X11/xf_event.h000066400000000000000000000032731207112532300166100ustar00rootroot00000000000000/** * FreeRDP: A Remote Desktop Protocol Client * X11 Server Event Handling * * Copyright 2011 Marc-Andre Moreau * * 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. */ #ifndef __XF_EVENT_H #define __XF_EVENT_H typedef struct xf_event xfEvent; typedef struct xf_event_queue xfEventQueue; typedef struct xf_event_region xfEventRegion; #include #include "xfreerdp.h" #include "xf_peer.h" enum xf_event_type { XF_EVENT_TYPE_REGION, XF_EVENT_TYPE_FRAME_TICK }; struct xf_event { int type; }; struct xf_event_queue { int size; int count; int pipe_fd[2]; xfEvent** events; pthread_mutex_t mutex; }; struct xf_event_region { int type; int x; int y; int width; int height; }; void xf_event_push(xfEventQueue* event_queue, xfEvent* event); xfEvent* xf_event_peek(xfEventQueue* event_queue); xfEvent* xf_event_pop(xfEventQueue* event_queue); xfEventRegion* xf_event_region_new(int x, int y, int width, int height); void xf_event_region_free(xfEventRegion* event_region); xfEvent* xf_event_new(int type); void xf_event_free(xfEvent* event); xfEventQueue* xf_event_queue_new(); void xf_event_queue_free(xfEventQueue* event_queue); #endif /* __XF_EVENT_H */ FreeRDP-1.0.2/server/X11/xf_input.c000066400000000000000000000063631207112532300166240ustar00rootroot00000000000000/** * FreeRDP: A Remote Desktop Protocol Client * X11 Server Input * * Copyright 2011 Marc-Andre Moreau * * 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. */ #include #include #include "xf_input.h" void xf_input_synchronize_event(rdpInput* input, uint32 flags) { printf("Client sent a synchronize event (flags:0x%X)\n", flags); } void xf_input_keyboard_event(rdpInput* input, uint16 flags, uint16 code) { unsigned int keycode; boolean extended = false; xfPeerContext* xfp = (xfPeerContext*) input->context; xfInfo* xfi = xfp->info; if (flags & KBD_FLAGS_EXTENDED) extended = true; keycode = freerdp_kbd_get_keycode_by_scancode(code, extended); if (keycode != 0) { #ifdef WITH_XTEST pthread_mutex_lock(&(xfp->mutex)); if (flags & KBD_FLAGS_DOWN) XTestFakeKeyEvent(xfi->display, keycode, True, 0); else if (flags & KBD_FLAGS_RELEASE) XTestFakeKeyEvent(xfi->display, keycode, False, 0); pthread_mutex_unlock(&(xfp->mutex)); #endif } } void xf_input_unicode_keyboard_event(rdpInput* input, uint16 flags, uint16 code) { printf("Client sent a unicode keyboard event (flags:0x%X code:0x%X)\n", flags, code); } void xf_input_mouse_event(rdpInput* input, uint16 flags, uint16 x, uint16 y) { int button = 0; boolean down = false; xfPeerContext* xfp = (xfPeerContext*) input->context; xfInfo* xfi = xfp->info; pthread_mutex_lock(&(xfp->mutex)); #ifdef WITH_XTEST if (flags & PTR_FLAGS_WHEEL) { boolean negative = false; if (flags & PTR_FLAGS_WHEEL_NEGATIVE) negative = true; button = (negative) ? 5 : 4; XTestFakeButtonEvent(xfi->display, button, True, 0); XTestFakeButtonEvent(xfi->display, button, False, 0); } else { if (flags & PTR_FLAGS_MOVE) XTestFakeMotionEvent(xfi->display, 0, x, y, 0); if (flags & PTR_FLAGS_BUTTON1) button = 1; else if (flags & PTR_FLAGS_BUTTON2) button = 3; else if (flags & PTR_FLAGS_BUTTON3) button = 2; if (flags & PTR_FLAGS_DOWN) down = true; if (button != 0) XTestFakeButtonEvent(xfi->display, button, down, 0); } #endif pthread_mutex_unlock(&(xfp->mutex)); } void xf_input_extended_mouse_event(rdpInput* input, uint16 flags, uint16 x, uint16 y) { xfPeerContext* xfp = (xfPeerContext*) input->context; xfInfo* xfi = xfp->info; pthread_mutex_lock(&(xfp->mutex)); #ifdef WITH_XTEST XTestFakeMotionEvent(xfi->display, 0, x, y, CurrentTime); #endif pthread_mutex_unlock(&(xfp->mutex)); } void xf_input_register_callbacks(rdpInput* input) { input->SynchronizeEvent = xf_input_synchronize_event; input->KeyboardEvent = xf_input_keyboard_event; input->UnicodeKeyboardEvent = xf_input_unicode_keyboard_event; input->MouseEvent = xf_input_mouse_event; input->ExtendedMouseEvent = xf_input_extended_mouse_event; } FreeRDP-1.0.2/server/X11/xf_input.h000066400000000000000000000023431207112532300166230ustar00rootroot00000000000000/** * FreeRDP: A Remote Desktop Protocol Client * X11 Server Input * * Copyright 2011 Marc-Andre Moreau * * 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. */ #ifndef __XF_INPUT_H #define __XF_INPUT_H #include #include "xfreerdp.h" void xf_input_synchronize_event(rdpInput* input, uint32 flags); void xf_input_keyboard_event(rdpInput* input, uint16 flags, uint16 code); void xf_input_unicode_keyboard_event(rdpInput* input, uint16 flags, uint16 code); void xf_input_mouse_event(rdpInput* input, uint16 flags, uint16 x, uint16 y); void xf_input_extended_mouse_event(rdpInput* input, uint16 flags, uint16 x, uint16 y); void xf_input_register_callbacks(rdpInput* input); #endif /* __XF_INPUT_H */ FreeRDP-1.0.2/server/X11/xf_peer.c000066400000000000000000000363741207112532300164250ustar00rootroot00000000000000/** * FreeRDP: A Remote Desktop Protocol Client * X11 Peer * * Copyright 2011 Marc-Andre Moreau * * 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. */ #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include extern char* xf_pcap_file; extern boolean xf_pcap_dump_realtime; #include "xf_event.h" #include "xf_input.h" #include "xf_encode.h" #include "xf_peer.h" #ifdef WITH_XDAMAGE void xf_xdamage_init(xfInfo* xfi) { Bool pixmaps; int damage_event; int damage_error; int major, minor; XGCValues values; if (XShmQueryExtension(xfi->display) != False) { XShmQueryVersion(xfi->display, &major, &minor, &pixmaps); if (pixmaps != True) { printf("XShmQueryVersion failed\n"); return; } } else { printf("XShmQueryExtension failed\n"); return; } if (XDamageQueryExtension(xfi->display, &damage_event, &damage_error) == 0) { printf("XDamageQueryExtension failed\n"); return; } XDamageQueryVersion(xfi->display, &major, &minor); if (XDamageQueryVersion(xfi->display, &major, &minor) == 0) { printf("XDamageQueryVersion failed\n"); return; } else if (major < 1) { printf("XDamageQueryVersion failed: major:%d minor:%d\n", major, minor); return; } xfi->xdamage_notify_event = damage_event + XDamageNotify; xfi->xdamage = XDamageCreate(xfi->display, xfi->root_window, XDamageReportDeltaRectangles); if (xfi->xdamage == None) { printf("XDamageCreate failed\n"); return; } #ifdef WITH_XFIXES xfi->xdamage_region = XFixesCreateRegion(xfi->display, NULL, 0); if (xfi->xdamage_region == None) { printf("XFixesCreateRegion failed\n"); XDamageDestroy(xfi->display, xfi->xdamage); xfi->xdamage = None; return; } #endif values.subwindow_mode = IncludeInferiors; xfi->xdamage_gc = XCreateGC(xfi->display, xfi->root_window, GCSubwindowMode, &values); XSetFunction(xfi->display, xfi->xdamage_gc, GXcopy); } #endif void xf_xshm_init(xfInfo* xfi) { xfi->fb_shm_info.shmid = -1; xfi->fb_shm_info.shmaddr = (char*) -1; xfi->fb_image = XShmCreateImage(xfi->display, xfi->visual, xfi->depth, ZPixmap, NULL, &(xfi->fb_shm_info), xfi->width, xfi->height); if (xfi->fb_image == NULL) { printf("XShmCreateImage failed\n"); return; } xfi->fb_shm_info.shmid = shmget(IPC_PRIVATE, xfi->fb_image->bytes_per_line * xfi->fb_image->height, IPC_CREAT | 0600); if (xfi->fb_shm_info.shmid == -1) { printf("shmget failed\n"); return; } xfi->fb_shm_info.readOnly = False; xfi->fb_shm_info.shmaddr = shmat(xfi->fb_shm_info.shmid, 0, 0); xfi->fb_image->data = xfi->fb_shm_info.shmaddr; if (xfi->fb_shm_info.shmaddr == ((char*) -1)) { printf("shmat failed\n"); return; } XShmAttach(xfi->display, &(xfi->fb_shm_info)); XSync(xfi->display, False); shmctl(xfi->fb_shm_info.shmid, IPC_RMID, 0); xfi->fb_pixmap = XShmCreatePixmap(xfi->display, xfi->root_window, xfi->fb_image->data, &(xfi->fb_shm_info), xfi->fb_image->width, xfi->fb_image->height, xfi->fb_image->depth); } xfInfo* xf_info_init() { int i; xfInfo* xfi; int pf_count; int vi_count; XVisualInfo* vi; XVisualInfo* vis; XVisualInfo template; XPixmapFormatValues* pf; XPixmapFormatValues* pfs; xfi = xnew(xfInfo); //xfi->use_xshm = true; xfi->display = XOpenDisplay(NULL); XInitThreads(); if (xfi->display == NULL) { printf("failed to open display: %s\n", XDisplayName(NULL)); exit(1); } xfi->xfds = ConnectionNumber(xfi->display); xfi->number = DefaultScreen(xfi->display); xfi->screen = ScreenOfDisplay(xfi->display, xfi->number); xfi->depth = DefaultDepthOfScreen(xfi->screen); xfi->width = WidthOfScreen(xfi->screen); xfi->height = HeightOfScreen(xfi->screen); xfi->root_window = DefaultRootWindow(xfi->display); pfs = XListPixmapFormats(xfi->display, &pf_count); if (pfs == NULL) { printf("XListPixmapFormats failed\n"); exit(1); } for (i = 0; i < pf_count; i++) { pf = pfs + i; if (pf->depth == xfi->depth) { xfi->bpp = pf->bits_per_pixel; xfi->scanline_pad = pf->scanline_pad; break; } } XFree(pfs); memset(&template, 0, sizeof(template)); template.class = TrueColor; template.screen = xfi->number; vis = XGetVisualInfo(xfi->display, VisualClassMask | VisualScreenMask, &template, &vi_count); if (vis == NULL) { printf("XGetVisualInfo failed\n"); exit(1); } for (i = 0; i < vi_count; i++) { vi = vis + i; if (vi->depth == xfi->depth) { xfi->visual = vi->visual; break; } } XFree(vis); xfi->clrconv = freerdp_clrconv_new(CLRCONV_ALPHA | CLRCONV_INVERT); XSelectInput(xfi->display, xfi->root_window, SubstructureNotifyMask); #ifdef WITH_XDAMAGE xf_xdamage_init(xfi); #endif xf_xshm_init(xfi); xfi->bytesPerPixel = 4; freerdp_kbd_init(xfi->display, 0); return xfi; } void xf_peer_context_new(freerdp_peer* client, xfPeerContext* context) { context->info = xf_info_init(); context->rfx_context = rfx_context_new(); context->rfx_context->mode = RLGR3; context->rfx_context->width = context->info->width; context->rfx_context->height = context->info->height; rfx_context_set_pixel_format(context->rfx_context, RFX_PIXEL_FORMAT_BGRA); context->s = stream_new(65536); } void xf_peer_context_free(freerdp_peer* client, xfPeerContext* context) { if (context) { stream_free(context->s); rfx_context_free(context->rfx_context); xfree(context); } } void xf_peer_init(freerdp_peer* client) { xfInfo* xfi; xfPeerContext* xfp; client->context_size = sizeof(xfPeerContext); client->ContextNew = (psPeerContextNew) xf_peer_context_new; client->ContextFree = (psPeerContextFree) xf_peer_context_free; freerdp_peer_context_new(client); xfp = (xfPeerContext*) client->context; xfp->fps = 24; xfp->thread = 0; xfp->activations = 0; xfp->event_queue = xf_event_queue_new(); xfi = xfp->info; xfp->hdc = gdi_CreateDC(xfi->clrconv, xfi->bpp); pthread_mutex_init(&(xfp->mutex), NULL); } STREAM* xf_peer_stream_init(xfPeerContext* context) { stream_clear(context->s); stream_set_pos(context->s, 0); return context->s; } void xf_peer_live_rfx(freerdp_peer* client) { xfPeerContext* xfp = (xfPeerContext*) client->context; if (xfp->activations == 1) pthread_create(&(xfp->thread), 0, xf_monitor_updates, (void*) client); } static boolean xf_peer_sleep_tsdiff(uint32 *old_sec, uint32 *old_usec, uint32 new_sec, uint32 new_usec) { sint32 sec, usec; if (*old_sec == 0 && *old_usec == 0) { *old_sec = new_sec; *old_usec = new_usec; return true; } sec = new_sec - *old_sec; usec = new_usec - *old_usec; if (sec < 0 || (sec == 0 && usec < 0)) { printf("Invalid time stamp detected.\n"); return false; } *old_sec = new_sec; *old_usec = new_usec; while (usec < 0) { usec += 1000000; sec--; } if (sec > 0) freerdp_sleep(sec); if (usec > 0) freerdp_usleep(usec); return true; } void xf_peer_dump_rfx(freerdp_peer* client) { STREAM* s; uint32 prev_seconds; uint32 prev_useconds; rdpUpdate* update; rdpPcap* pcap_rfx; pcap_record record; s = stream_new(512); update = client->update; client->update->pcap_rfx = pcap_open(xf_pcap_file, false); pcap_rfx = client->update->pcap_rfx; if (pcap_rfx == NULL) return; prev_seconds = prev_useconds = 0; while (pcap_has_next_record(pcap_rfx)) { pcap_get_next_record_header(pcap_rfx, &record); s->data = xrealloc(s->data, record.length); record.data = s->data; s->size = record.length; pcap_get_next_record_content(pcap_rfx, &record); s->p = s->data + s->size; if (xf_pcap_dump_realtime && xf_peer_sleep_tsdiff(&prev_seconds, &prev_useconds, record.header.ts_sec, record.header.ts_usec) == false) break; update->SurfaceCommand(update->context, s); } } void xf_peer_rfx_update(freerdp_peer* client, int x, int y, int width, int height) { STREAM* s; uint8* data; xfInfo* xfi; RFX_RECT rect; XImage* image; rdpUpdate* update; xfPeerContext* xfp; SURFACE_BITS_COMMAND* cmd; update = client->update; xfp = (xfPeerContext*) client->context; cmd = &update->surface_bits_command; xfi = xfp->info; if (width * height <= 0) return; s = xf_peer_stream_init(xfp); if (xfi->use_xshm) { width = x + width; height = y + height; x = 0; y = 0; rect.x = x; rect.y = y; rect.width = width; rect.height = height; image = xf_snapshot(xfp, x, y, width, height); data = (uint8*) image->data; data = &data[(y * image->bytes_per_line) + (x * image->bits_per_pixel)]; rfx_compose_message(xfp->rfx_context, s, &rect, 1, data, width, height, image->bytes_per_line); cmd->destLeft = x; cmd->destTop = y; cmd->destRight = x + width; cmd->destBottom = y + height; } else { rect.x = 0; rect.y = 0; rect.width = width; rect.height = height; image = xf_snapshot(xfp, x, y, width, height); rfx_compose_message(xfp->rfx_context, s, &rect, 1, (uint8*) image->data, width, height, width * xfi->bytesPerPixel); cmd->destLeft = x; cmd->destTop = y; cmd->destRight = x + width; cmd->destBottom = y + height; XDestroyImage(image); } cmd->bpp = 32; cmd->codecID = client->settings->rfx_codec_id; cmd->width = width; cmd->height = height; cmd->bitmapDataLength = stream_get_length(s); cmd->bitmapData = stream_get_head(s); update->SurfaceBits(update->context, cmd); } boolean xf_peer_get_fds(freerdp_peer* client, void** rfds, int* rcount) { xfPeerContext* xfp = (xfPeerContext*) client->context; if (xfp->event_queue->pipe_fd[0] == -1) return true; rfds[*rcount] = (void *)(long) xfp->event_queue->pipe_fd[0]; (*rcount)++; return true; } boolean xf_peer_check_fds(freerdp_peer* client) { xfInfo* xfi; xfEvent* event; xfPeerContext* xfp; HGDI_RGN invalid_region; xfp = (xfPeerContext*) client->context; xfi = xfp->info; if (xfp->activated == false) return true; event = xf_event_peek(xfp->event_queue); if (event != NULL) { if (event->type == XF_EVENT_TYPE_REGION) { xfEventRegion* region = (xfEventRegion*) xf_event_pop(xfp->event_queue); gdi_InvalidateRegion(xfp->hdc, region->x, region->y, region->width, region->height); xf_event_region_free(region); } else if (event->type == XF_EVENT_TYPE_FRAME_TICK) { event = xf_event_pop(xfp->event_queue); invalid_region = xfp->hdc->hwnd->invalid; if (invalid_region->null == false) { xf_peer_rfx_update(client, invalid_region->x, invalid_region->y, invalid_region->w, invalid_region->h); } invalid_region->null = 1; xfp->hdc->hwnd->ninvalid = 0; xf_event_free(event); } } return true; } boolean xf_peer_capabilities(freerdp_peer* client) { return true; } boolean xf_peer_post_connect(freerdp_peer* client) { xfInfo* xfi; xfPeerContext* xfp; xfp = (xfPeerContext*) client->context; xfi = (xfInfo*) xfp->info; /** * This callback is called when the entire connection sequence is done, i.e. we've received the * Font List PDU from the client and sent out the Font Map PDU. * The server may start sending graphics output and receiving keyboard/mouse input after this * callback returns. */ printf("Client %s is activated", client->hostname); if (client->settings->autologon) { printf(" and wants to login automatically as %s\\%s", client->settings->domain ? client->settings->domain : "", client->settings->username); /* A real server may perform OS login here if NLA is not executed previously. */ } printf("\n"); printf("Client requested desktop: %dx%dx%d\n", client->settings->width, client->settings->height, client->settings->color_depth); /* A real server should tag the peer as activated here and start sending updates in mainloop. */ client->settings->width = xfi->width; client->settings->height = xfi->height; client->update->DesktopResize(client->update->context); xfp->activated = false; /* Return false here would stop the execution of the peer mainloop. */ return true; } boolean xf_peer_activate(freerdp_peer* client) { xfPeerContext* xfp = (xfPeerContext*) client->context; rfx_context_reset(xfp->rfx_context); xfp->activated = true; if (xf_pcap_file != NULL) { client->update->dump_rfx = true; xf_peer_dump_rfx(client); } else { xf_peer_live_rfx(client); xfp->activations++; } return true; } void* xf_peer_main_loop(void* arg) { int i; int fds; int max_fds; int rcount; void* rfds[32]; fd_set rfds_set; rdpSettings* settings; char* server_file_path; freerdp_peer* client = (freerdp_peer*) arg; memset(rfds, 0, sizeof(rfds)); printf("We've got a client %s\n", client->hostname); xf_peer_init(client); settings = client->settings; /* Initialize the real server settings here */ if (settings->development_mode) { server_file_path = freerdp_construct_path(settings->development_path, "server/X11"); } else { server_file_path = freerdp_construct_path(settings->config_path, "server"); if (!freerdp_check_file_exists(server_file_path)) freerdp_mkdir(server_file_path); } settings->cert_file = freerdp_construct_path(server_file_path, "server.crt"); settings->privatekey_file = freerdp_construct_path(server_file_path, "server.key"); settings->nla_security = false; settings->rfx_codec = true; client->Capabilities = xf_peer_capabilities; client->PostConnect = xf_peer_post_connect; client->Activate = xf_peer_activate; xf_input_register_callbacks(client->input); client->Initialize(client); while (1) { rcount = 0; if (client->GetFileDescriptor(client, rfds, &rcount) != true) { printf("Failed to get FreeRDP file descriptor\n"); break; } if (xf_peer_get_fds(client, rfds, &rcount) != true) { printf("Failed to get xfreerdp file descriptor\n"); break; } max_fds = 0; FD_ZERO(&rfds_set); for (i = 0; i < rcount; i++) { fds = (int)(long)(rfds[i]); if (fds > max_fds) max_fds = fds; FD_SET(fds, &rfds_set); } if (max_fds == 0) break; if (select(max_fds + 1, &rfds_set, NULL, NULL, NULL) == -1) { /* these are not really errors */ if (!((errno == EAGAIN) || (errno == EWOULDBLOCK) || (errno == EINPROGRESS) || (errno == EINTR))) /* signal occurred */ { printf("select failed\n"); break; } } if (client->CheckFileDescriptor(client) != true) { printf("Failed to check freerdp file descriptor\n"); break; } if ((xf_peer_check_fds(client)) != true) { printf("Failed to check xfreerdp file descriptor\n"); break; } } printf("Client %s disconnected.\n", client->hostname); client->Disconnect(client); freerdp_peer_context_free(client); freerdp_peer_free(client); return NULL; } void xf_peer_accepted(freerdp_listener* instance, freerdp_peer* client) { pthread_t th; pthread_create(&th, 0, xf_peer_main_loop, client); pthread_detach(th); } FreeRDP-1.0.2/server/X11/xf_peer.h000066400000000000000000000025531207112532300164220ustar00rootroot00000000000000/** * FreeRDP: A Remote Desktop Protocol Client * X11 Peer * * Copyright 2011 Marc-Andre Moreau * * 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. */ #ifndef __XF_PEER_H #define __XF_PEER_H #include #include #include #include #include #include #include typedef struct xf_peer_context xfPeerContext; #include "xfreerdp.h" struct xf_peer_context { rdpContext _p; int fps; STREAM* s; HGDI_DC hdc; xfInfo* info; int activations; pthread_t thread; boolean activated; pthread_mutex_t mutex; RFX_CONTEXT* rfx_context; xfEventQueue* event_queue; pthread_t frame_rate_thread; }; void xf_peer_accepted(freerdp_listener* instance, freerdp_peer* client); #endif /* __XF_PEER_H */ FreeRDP-1.0.2/server/X11/xfreerdp.c000066400000000000000000000051711207112532300166030ustar00rootroot00000000000000/** * FreeRDP: A Remote Desktop Protocol Client * FreeRDP X11 Server * * Copyright 2011 Marc-Andre Moreau * * 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. */ #include #include #include #include #include #include #include #include #include #include "xf_peer.h" #include "xfreerdp.h" char* xf_pcap_file = NULL; boolean xf_pcap_dump_realtime = true; void xf_server_main_loop(freerdp_listener* instance) { int i; int fds; int max_fds; int rcount; void* rfds[32]; fd_set rfds_set; memset(rfds, 0, sizeof(rfds)); while (1) { rcount = 0; if (instance->GetFileDescriptor(instance, rfds, &rcount) != true) { printf("Failed to get FreeRDP file descriptor\n"); break; } max_fds = 0; FD_ZERO(&rfds_set); for (i = 0; i < rcount; i++) { fds = (int)(long)(rfds[i]); if (fds > max_fds) max_fds = fds; FD_SET(fds, &rfds_set); } if (max_fds == 0) break; if (select(max_fds + 1, &rfds_set, NULL, NULL, NULL) == -1) { /* these are not really errors */ if (!((errno == EAGAIN) || (errno == EWOULDBLOCK) || (errno == EINPROGRESS) || (errno == EINTR))) /* signal occurred */ { printf("select failed\n"); break; } } if (instance->CheckFileDescriptor(instance) != true) { printf("Failed to check FreeRDP file descriptor\n"); break; } } instance->Close(instance); } int main(int argc, char* argv[]) { freerdp_listener* instance; /* ignore SIGPIPE, otherwise an SSL_write failure could crash the server */ signal(SIGPIPE, SIG_IGN); instance = freerdp_listener_new(); instance->PeerAccepted = xf_peer_accepted; if (argc > 1) xf_pcap_file = argv[1]; if (argc > 2 && !strcmp(argv[2], "--fast")) xf_pcap_dump_realtime = false; /* Open the server socket and start listening. */ if (instance->Open(instance, NULL, 3389)) { /* Entering the server main loop. In a real server the listener can be run in its own thread. */ xf_server_main_loop(instance); } freerdp_listener_free(instance); return 0; } FreeRDP-1.0.2/server/X11/xfreerdp.h000066400000000000000000000030171207112532300166050ustar00rootroot00000000000000/** * FreeRDP: A Remote Desktop Protocol Client * FreeRDP X11 Server * * Copyright 2011 Marc-Andre Moreau * * 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. */ #ifndef __XFREERDP_H #define __XFREERDP_H #include #ifdef WITH_XSHM #include #endif #ifdef WITH_XFIXES #include #endif #ifdef WITH_XTEST #include #endif #ifdef WITH_XDAMAGE #include #endif typedef struct xf_info xfInfo; #include "xf_event.h" struct xf_info { int bpp; int xfds; int depth; int width; int height; int number; XImage* image; Screen* screen; Visual* visual; Display* display; int scanline_pad; int bytesPerPixel; HCLRCONV clrconv; boolean use_xshm; XImage* fb_image; Pixmap fb_pixmap; Window root_window; XShmSegmentInfo fb_shm_info; #ifdef WITH_XDAMAGE GC xdamage_gc; Damage xdamage; int xdamage_notify_event; XserverRegion xdamage_region; #endif }; #endif /* __XFREERDP_H */ FreeRDP-1.0.2/server/test/000077500000000000000000000000001207112532300152225ustar00rootroot00000000000000FreeRDP-1.0.2/server/test/CMakeLists.txt000066400000000000000000000020451207112532300177630ustar00rootroot00000000000000# FreeRDP: A Remote Desktop Protocol Client # FreeRDP Test Server cmake build script # # Copyright 2011 O.S. Systems Software Ltda. # Copyright 2011 Otavio Salvador # Copyright 2011 Marc-Andre Moreau # # 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. add_executable(tfreerdp-server tfreerdp.c) target_link_libraries(tfreerdp-server freerdp-core) target_link_libraries(tfreerdp-server freerdp-utils) target_link_libraries(tfreerdp-server freerdp-codec) target_link_libraries(tfreerdp-server freerdp-channels) FreeRDP-1.0.2/server/test/rfx_test.pcap000066400000000000000000036272041207112532300177430ustar00rootroot00000000000000ò''  ʬ @((  GQP@,ffw,  ''@  ̛QP@`ffw,  ,  ,  ,  ,  ,  ,  ,  ,  ,   ,   ,   ,   ,   ,  ,  ,  ,  ,  ,  ,  ,  ,  ,  ,  ,   ,   ,   ,   ,   ,  ,  ,  ,  ,  ,  ,  ,  ,  ,  ,  ,   ,   ,   ,   ,   ,  ,  ,  ,  ,  ,  ,  ,  ,  ,  ,  ,   ,   ,   ,   ,   ,  ,  ,  ,  ,  ,  ,  ,  ,  ,  ,  ,   ,   ,   ,   ,   ,  ,  ,  ,  ,  ,  ,  ,  ,  ,  ,  ,   ,   ,   ,   ,   ,  ,  `  ̛QP@`ffw,  ,  ,  ,  ,  ,  ,  ,  ,  ,   ,   ,   ,   ,   ,  ,  ,  ,  ,  ,  ,  ,  ,  ,  ,  ,   ,   ,   ,   ,   ,  ,  ,  ,  ,  ,  ,  ,  ,  ,  ,  ,   ,   ,   ,   ,   ,  ,  ,  ,  ,  ,  ,  ,  ,  ,  ,  ,   ,   ,   ,   ,   ,  ,  ,  ,  ,  ,  ,  ,  ,  ,  ,  ,   ,   ,   ,   ,   ,  ,  ,  ,  ,  ,  ,  ,  ,  ,  ,  ,   ,   ,   ,   ,   ,  ,  p QP@ffw,  ,  ,  ,  ,  ,  ,  ,  ,  ,   ,   ,   ,   ,   ,  ,  pp  ̛QP@`ffw,  ,  ,  ,  ,  ,  ,  ,  ,  ,   ,   ,   ,   ,   ,  ,  ,  ,  ,  ,  ,  ,  ,  ,  ,  ,   ,   ,   ,   ,   ,  ,  ,  ,  ,  ,  ,  ,  ,  ,  ,  ,   ,   ,   ,   ,   ,  ,  ,  ,  ,  ,  ,  ,  ,  ,  ,  ,   ,   ,   ,   ,   ,  ,  ,  ,  ,  ,  ,  ,  ,  ,  ,  ,   ,   ,   ,   ,   ,  ,  ,  ,  ,  ,  ,  ,  ,  ,  ,  ,   ,   ,   ,   ,   ,  ,  I  ̛QP@`ffw,  ,  ,  ,  ,  ,  ,  ,  ,  ,   ,   ,   ,   ,   ,  ,  ,  ,  ,  ,  ,  ,  ,  ,  ,  ,   ,   ,   ,   ,   ,  ,  ,  ,  ,  ,  ,  ,  ,  ,  ,  ,   ,   ,   ,   ,   ,  ,  ,  ,  ,  ,  ,  ,  ,  ,  ,  ,   ,   ,   ,   ,   ,  ,  ,  ,  ,  ,  ,  ,  ,  ,  ,  ,   ,   ,   ,   ,   ,  ,  ,  ,  ,  ,  ,  ,  ,  ,  ,  ,   ,   ,   ,   ,   ,  ,  I QP@ffw,  ,  ,  ,  ,  ,  ,  ,  ,  ,   ,   ,   ,   ,   ,  ,  II >> ( QP@`ffw.  #.  #.  #.  #.  #.  #.  #.  #.  #.  #.  #.  #.  #.  #.  #.  #.  #.  #.  #.  #.  #.  #.  #.  #.  #.   #.   #.   #.   #.   #.  #.  #.  #.  #.  #.  #.  #.  #.  #.  #.  #.   #.   #.   #.   #.   #.  #.  #.  #.  #.  #.  #.  #.  #.  #.  #.  #.   #.   #.   #.   #.   #.  #.  #.  #.  #.  #.  #.  #.  #.  #.  #.  #.   #.   #.   #.   #.   #.  #.  #O@F|``s9cf6>';$(QJ$x|X,`X,,X#` @`` Ĉ ?O@F|``s9cf6>';$(QJ$x|X,`X,,X#` @`` Ĉ ?O@F|``s9cf6>';$(QJ$x|X,`X,,X#` @`` Ĉ ?O@F|``s9cf6>';$(QJ$x|X,`X,,X#` @`` Ĉ ?O@F|``s9cf6>';$(QJ$x|X,`X,,X#` @`` Ĉ ?O@F|``s9cf6>';$(QJ$x|X,`X,,X#` @`` Ĉ ?O@F|``s9cf6>';$(QJ$x|X,`X,,X#` @`` Ĉ ?O@F|``s9cf6>';$(QJ$x|X,`X,,X#` @`` Ĉ ?O@F|``s9cf6>';$(QJ$x|X,`X,,X#` @`` Ĉ ? O@F|``s9cf6>';$(QJ$x|X,`X,,X#` @`` Ĉ ? O@F|``s9cf6>';$(QJ$x|X,`X,,X#` @`` Ĉ ? O@F|``s9cf6>';$(QJ$x|X,`X,,X#` @`` Ĉ ? O@F|``s9cf6>';$(QJ$x|X,`X,,X#` @`` Ĉ ? O@F|``s9cf6>';$(QJ$x|X,`X,,X#` @`` Ĉ ?O@F|``s9cf6>';$(QJ$x|X,`X,,X#` @`` Ĉ ?O@F|``s9cf6>';$(QJ$x|X,`X,,X#` @`` Ĉ ?P4x8x8 b8 58QP@`8ffw.  #.  #.  #.  #.  #.  #.  #.  #.  #.  #.  #.  #.  #.  #.  #.  #.  #.  #.  #.  #.  #.  #.  #.  #.  #.   #.   #.   #.   #.   #.  #.  #.  #.  #.  #.  #.  #.  #.  #.  #.  #.   #.   #.   #.   #.   #.  #.  #.  #.  #.  #.  #.  #.  #.  #.  #.  #.   #.   #.   #.   #.   #.  #.  #.  #.  #.  #.  #.  #.  #@ce+@!x&Ο`d@$=le%MUAM0.ȈIpɅ%e @tooB- QĉWୄ3ýGS D&D j 'p ІP\` - h1``lx`4 anС( S٠ Ї*@Th( ѧx@L|{4 Gs4=)Q2@mP`&%HX @ IP!Ԁ%Ē(P8j @>EBPx =UH9 I.Bƨi WA Uf]1&,@ h(툀hA!8as$ 8] -K $hOOp9QT,HH%@HPo.  #.  #.   #.   #.   #.   #.   #.  #.  #O@F|``s9cf6>';$(QJ$x|X,`X,,X#` @`` Ĉ ?O@F|``s9cf6>';$(QJ$x|X,`X,,X#` @`` Ĉ ?O@F|``s9cf6>';$(QJ$x|X,`X,,X#` @`` Ĉ ?O@F|``s9cf6>';$(QJ$x|X,`X,,X#` @`` Ĉ ?O@F|``s9cf6>';$(QJ$x|X,`X,,X#` @`` Ĉ ?O@F|``s9cf6>';$(QJ$x|X,`X,,X#` @`` Ĉ ? &&2?@ `vV{1 Ab7A$‚==OH0IדE==](MQ`($6UW@bB ap?ԁ9! Q+XqX,E%$@ψ!@gNp|ԝ g!=OcCKzc`0܁9+I[whE] |@Pdˆ@.' R⑀0jSXB`BH @%08R{N(c@JE;jXT_B hɕPi3`"Enr2߳"Op\a!@3*gJ0p`as1'd'rNIP F!tu@n;a Gь& {A;!k4𥃠qq 1;*1@@S ut] P?6Xj{i=` H'eH`;+~L֓QF" gx!I ` z}q\eXx.rȡD]U_z5g]辑KPJ\*3 ~t q!ZǀwɂAuIBA.(b8;!CjZP> J%,'J?K(ڙ 0D B) H{(t5yR 6t,KdY,J(0 j@ aQ?< ٌ9=h~rQ_a|@ld `nSPM;B T@_!:e<K{k=8sk\P ,X[Ld,pܔ|j.7!FGC@ȆY"*Xwxב.'Rf"@ [Z1`mTۭePPʹ8SUUGudY¥c}ֵkW28ư Iaw)x_*N6mkK2Ҝ\:rڥw.(L']8c[cJg4E(,\CfqBSL+@AHβA+2lzV@'>At8rl?MbjYA=^$z9b_}@|Q$ @* Gv8Ȑ6Ð  ID*:(ӈ6A0 vxP 1M#(G+}Z?𹳙f I͜z37b)QƳWe̳=L7 m]Hv٦`\ł ̗ޓH) Ĉ<1VIF84 =>fsrBLz2bc@K;$,,]XQ@_`s03d̞d'8N2qs N1  !yK82I,2ryit>_I ",J"ЉCs4ݧH$>LP-/W?_Ȟ$J z'a 1 0g11' z5#= ]>FV5#l:zOsu>ybA>h3m[,Ē!>iuM@^&G]pTbnpLl})2U`[H}CoTп1EJ LX#L{( ~(.Ku=H@H%R oa>s)q ( q1,a'19'$䘒01ڿh( |.\pd[eԄH LGDE4rc1Faf#"FAَ}$H*8GfH;B8Ґ tXbn,t>LH|Adpp-ea͟ ѵ;kP;Se)8c0 ĖC4M]gZ;h Q88vyҔEnAE4) ͎"jb-銱X: [jiNZV5sSZK(Vl3^ TP-"]!@)j`pۊe2q@B(X]J(g|$"h  QJN"</Hb!,L/"ֺzk#MA˜c]]0tC,].K%dY*#@f)% )Vyo̧4|T7UۈFVN_Ȉ_d P`B Z^`iB' 8M|4sP0rBj@< ChQ1@ 44h[造H,a#DFhGb<"JSiRFﯥn1&P (0E Y!o~{D)~ѤDbD4dqg@h+hӼ{aGi;!qDp)*CHJ Qq&G,tB-QI'*~ /RzK+[iʽf:SKW\r>oDP׭HU1,@ $>޾CI N?M0; 4=@UH E$j 3fW͏@ 'THHG9*Z+wGp" h%Łз_8]>hkk0 8%ٷg%`(YA*Pr7:ŋ/0F"@@q0BlE&W1t"˻|NpEV$_9X-' s2V*3 I8?+F1<VF 9y 'g-7C2$D`@܄cz_#r I Ѵ 0H4KFJAY(P<ՕV`Mf-C#wEH}+~3$sj G_NiIDg}x'aAi@! X>QlI1A) =.I#1=J$z|5$.!@6ܨTC#%LP2O*6|Ak^¸+kn$n)$|a ,K8s3Pq4cN4~[@/tY,K%D "hke< plMn*ЪRaFih8,A=7Gͮ_iF'u4:fQ@)a1b_Ϗ0$+ C:#j 4F~~!H Xtx P"I)%M QlQ3 ?SXZPuf/עBPxQ`B.#Z_vJdn^%X*ÞAOX1}A_R#b05 } !Ht"/T 4vLi`v(\3 FCUL({JQ)\@)t+ܝw`, abŗGxF#@ @3 B&lDÊ+fS'3\-gePlŽ@W z C$Q>}S(WDuB W$H}\|`F a0#_e06nyAF@D/O-_7[3Jv(OzgԎV1@ A)mtGES2y% UAM2L0!P SRޟP弟Ob]VH{-Yj)Ж$]+;Fhr}03XSb|0j.F(X+f\c3f& b8>Gzd{f t.H``͜ 4>&P f g Ad%9Gł:?4ouǃ"0e$SV0U0dPa10c01l}O2y̜d'8N2`x 5a]6jWVG 0#]i\h46@h^u3_Jϲ!:> 0;GSa>0.- ZE .[Q/9 G3z011T|O=@$(PL@a؍?`(pI  A N'E$F|I _ذR(F  j$cD?D541PP_W%5w0{@x !fz_h R1ve0:읅$HF% `&HA4cIj٪dqkU5cA PȊRlk|Gۀ(*kQm 9=J݀ X!t(Sӈ!^` 8A n}l0Iaii/gxPT`(Uay* ow~`abŗG` D"@T#&!&4" Zv0RDA!!A+'@(իB҄O:E1|0fZ/Ni<-x}l(,1HQSo0';$(QJ$x|X,`X,,X#` @`` Ĉ ? O@F|``s9cf6>';$(QJ$x|X,`X,,X#` @`` Ĉ ? O@F|``s9cf6>';$(QJ$x|X,`X,,X#` @`` Ĉ ? O@F|``s9cf6>';$(QJ$x|X,`X,,X#` @`` Ĉ ?O@F|``s9cf6>';$(QJ$x|X,`X,,X#` @`` Ĉ ?O@F|``s9cf6>';$(QJ$x|X,`X,,X#` @`` Ĉ ?`[nn X +QP@ffwSFEd 2 DDHW´VR*EH"@ Ì `1cll}`L{w gx3@gn,O @( ABa0H$ $8j@d@2 ehpǹ@xq,@hCF5>>:tӧN+,``, Ŗ_1j @ A(J$SFEd 2 DDHW´VR*EH"@ Ì `1cll}`L{w gx3@gn,O @( ABa0H$ $8j@d@2 ehpǹ@xq,@hCF5>>:tӧN+,``, Ŗ_1j @ A(J$SFEd 2 DDHW´VR*EH"@ Ì `1cll}`L{w gx3@gn,O @( ABa0H$ $8j@d@2 ehpǹ@xq,@hCF5>>:tӧN+,``, Ŗ_1j @ A(J$SFEd 2 DDHW´VR*EH"@ Ì `1cll}`L{w gx3@gn,O @( ABa0H$ $8j@d@2 ehpǹ@xq,@hCF5>>:tӧN+,``, Ŗ_1j @ A(J$SFEd 2 DDHW´VR*EH"@ Ì `1cll}`L{w gx3@gn,O @( ABa0H$ $8j@d@2 ehpǹ@xq,@hCF5>>:tӧN+,``, Ŗ_1j @ A(J$SFEd 2 DDHW´VR*EH"@ Ì `1cll}`L{w gx3@gn,O @( ABa0H$ $8j@d@2 ehpǹ@xq,@hCF5>>:tӧN+,``, Ŗ_1j @ A(J$SFEd 2 DDHW´VR*EH"@ Ì `1cll}`L{w gx3@gn,O @( ABa0H$ $8j@d@2 ehpǹ@xq,@hCF5>>:tӧN+,``, Ŗ_1j @ A(J$SFEd 2 DDHW´VR*EH"@ Ì `1cll}`L{w gx3@gn,O @( ABa0H$ $8j@d@2 ehpǹ@xq,@hCF5>>:tӧN+,``, Ŗ_1j @ A(J$SFEd 2 DDHW´VR*EH"@ Ì `1cll}`L{w gx3@gn,O @( ABa0H$ $8j@d@2 ehpǹ@xq,@hCF5>>:tӧN+,``, Ŗ_1j @ A(J$ SFEd 2 DDHW´VR*EH"@ Ì `1cll}`L{w gx3@gn,O @( ABa0H$ $8j@d@2 ehpǹ@xq,@hCF5>>:tӧN+,``, Ŗ_1j @ A(J$ SFEd 2 DDHW´VR*EH"@ Ì `1cll}`L{w gx3@gn,O @( ABa0H$ $8j@d@2 ehpǹ@xq,@hCF5>>:tӧN+,``, Ŗ_1j @ A(J$ SFEd 2 DDHW´VR*EH"@ Ì `1cll}`L{w gx3@gn,O @( ABa0H$ $8j@d@2 ehpǹ@xq,@hCF5>>:tӧN+,``, Ŗ_1j @ A(J$ SFEd 2 DDHW´VR*EH"@ Ì `1cll}`L{w gx3@gn,O @( ABa0H$ $8j@d@2 ehpǹ@xq,@hCF5>>:tӧN+,``, Ŗ_1j @ A(J$ SFEd 2 DDHW´VR*EH"@ Ì `1cll}`L{w gx3@gn,O @( ABa0H$ $8j@d@2 ehpǹ@xq,@hCF5>>:tӧN+,``, Ŗ_1j @ A(J$SFEd 2 DDHW´VR*EH"@ Ì `1cll}`L{w gx3@gn,O @( ABa0H$ $8j@d@2 ehpǹ@xq,@hCF5>>:tӧN+,``, Ŗ_1j @ A(J$SFEd 2 DDHW´VR*EH"@ Ì `1cll}`L{w gx3@gn,O @( ABa0H$ $8j@d@2 ehpǹ@xq,@hCF5>>:tӧN+,``, Ŗ_1j @ A(J$`[pp>>>Bb $( $QP@ffwʳMzIcn>E#wg` OZC@ dThlc Li>0uo9 ď<͕ ؁S@ ֖Ϧ/`Cr)һ O;t3Y8Pғ_(0)M1b8qDW}+#ʋp@@p;Q+bҠK#RxaQX$J,B1?eF `c7B&`eyىXB$! Z+EH"TR*E*#!Cn,СcD=P, W!C)D+B@.(8d^-k2@ W.Y76]C1 fzؾvGdYD2(Qqg9N 80LL]A=(GLm)jE\r6iQ>J$@ o݈:3\1e@Q_E-mLZbH"I$B`#bBC?WM;VKl{p0"6Itoz7_dNkM-gR.y˯p )D_V3GVvE' \jDHM)?eywY'$'=G(2 P`%>kk* 3{P05O" .C%m=?c34Y\^TYi/QQ$xpbh E'* "Q^R~1`j-R(YN#%ÇP!c`B_0L$ A D`Ti$b\(<BAYCəVbat\UD`F/|dF _AddL'pj5 %`I`b+1><2q`ES@MvO#AHpg2IUG w$#ݺGӚ >g~yrVI 8B!p" @qN~_##ayAڋtA ne DHy&M*)ZGX0cJc v( ֢Jo~;G(,HX I9@4 1ȡo !PQz9~{l^Ѹ ,v}:DPJ#XP^<dP`P*0iž)Ÿ abƚߟ:tӧN7 J( Vc%E!(*<.ui Y(+k0_=D}0Ɖ 7i,dafJ})-?"'e9^Ex*NZ̖'='rNI1%r$PBPG%L  z_G&B /ȵN*F_t *|!裄KHP?ptXQ롔23a]?^DRm@J~14 yTdːJ*_]{,ApʫH!=!!^!) ~gH]!G! ۛ$M-W;*'bku圧ךO hhV1FAyl`fnިDuLeY]fZ5O?1gBl41- +h (?`]GS_eY} uNŒ3C}[L,)5h nd؇8: mh@P5Y0Da3*do-^[@9KUCBrѠD@g'20I H$""G´VR*EH"TJHAABQW."8Ǒ|$ 6}5^KpNP ǐs L*|5 '$nKE7;A8Nؑ0ihij"`T )@T ^9REW{SҸN]P tKI֧5DG -mlZb^DI$ qx>v7X ȽաAaC N1SN";f/͚ ,ExU;PPȬAjo%f,h 3Hr󗜼*4Y9-n\RA%F|vSX>&GXkiNl9900\J42F 6 ""˸HrcrdRO#Yԗӈ]5nPlwP&+AW ɕ*PkE>YHqj@ML ,"p*1fJ kPyRgĖv kBuɠB0Pȏf`B"MusAJ@< gf/Lf|֕cD)D )SlB!bS6a#bwq],S#xQlGER?ĢP{*+='$䜓bJ$HB1 R OJ?cjF.mJH->'rއT8 TU{/j;P n|>TU%sUNѝ5G]e? ʂb|\>~/__x~ @d !Dt:< i =g5 V?G#'``}& 䁀 LT /#=%?~\`|ot r@G@?]ms q6D .Evw .E4huH<0â4hJC`O nBw7hn  "757@P=>ZA@jߴ~p  06 6( ʬ @((  6(wQP@\ffw\_  ¯,G6΅7t2j % (hR')#/@t $`n\`lMć(&& EC!'`tCJ~I 56_2jK@zF$;Я$DC q) E"^"F5Q i90D =xC5((!`$kE Vf@u Q+LZw` < O@QS %pIQlYETH"PJWzt}y?>b?Xt$$=K"Y;D% 'F0ҀcCB !AC) "L H * _HIh}$I x ?@t5h6`>4LɎ7Ppuzsue)nM )'w$D( <1# ; h{'k w?2L$I%QXB ebGQUqF"Pffff<" pQ5ǀRbt<sXf'}`Iz'^|A%X+@BeTPrft;G7@k@1' 8ـ|IaCm*g(Dș5 L  b12)0p S¸ъJjS6[CS1}<@Zw(iXy}U ԍ+Lb 7 @\ ai (-$׀R7&o`Ҭ(<5Lwe)iB}0 "*S@h RJFҡāJ=CCA#GJGO'\GGG1`DiO€!D記,G,XB %g `3'A)lUE/uxHL>o0^0 /aȀ(P,BIB1b %s ߲`$į )Ȁ28X#Q鰉?$U T`1FUТj݂((PV}5.ob;WeArFB?+e@ DHd!`*+(#p_<\ @ ?$l%Z7Hȇ@\o EI>h{EAZ @!R,Y4)Mv@[!wD!)/BpjFDrԯ;.kƊV:EpJ Ozd8&-]H: lpn ( }2BTKi< ^+S^@ #8Ą P),Ę3 & k~B`I)1c 3Ɍf]."$GP*)+!Cpd 8[xACB:B_,AgU!p!!`(߯ՌC?㼁.@@BEHCS(n ) Vg& A^L-h. $ & Y߰Dg|+.Q}>U\H~!' Ȣ65HCD? :p:|YfAPY5| X4r~ב)Ǐ  MlPA@ 0 0 06 6(6(wQP@\ffw\_  ¯,G6΅7t2j % (hR')#/@t $`n\`lMć(&& EC!'`tCJ~I 56_2jK@zF$;Я$DC q) E"^"F5Q i90D =xC5((!`$kE Vf@u Q+LZw` < O@QS %pIQlYETH"PJWzt}y?>b?Xt$$=K"Y;D% 'F0ҀcCB !AC) "L H * _HIh}$I x ?@t5h6`>4LɎ7Ppuzsue)nM )'w$D( <1# ; h{'k w?2L$I%QXB ebGQUqF"Pffff<" pQ5ǀRbt<sXf'}`Iz'^|A%X+@BeTPrft;G7@k@1' 8ـ|IaCm*g(Dș5 L  b12)0p S¸ъJjS6[CS1}<@Zw(iXy}U ԍ+Lb 7 @\ ai (-$׀R7&o`Ҭ(<5Lwe)iB}0 "*S@h RJFҡāJ=CCA#GJGO'\GGG1`DiO€!D記,G,XB %g `3'A)lUE/uxHL>o0^0 /aȀ(P,BIB1b %s ߲`$į )Ȁ28X#Q鰉?$U T`1FUТj݂((PV}5.ob;WeArFB?+e@ DHd!`*+(#p_<\ @ ?$l%Z7Hȇ@\o EI>h{EAZ @!R,Y4)Mv@[!wD!)/BpjFDrԯ;.kƊV:EpJ Ozd8&-]H: lpn ( }2BTKi< ^+S^@ #8Ą P),Ę3 & k~B`I)1c 3Ɍf]."$GP*)+!Cpd 8[xACB:B_,AgU!p!!`(߯ՌC?㼁.@@BEHCS(n ) Vg& A^L-h. $ & Y߰Dg|+.Q}>U\H~!' Ȣ65HCD? :p:|YfAPY5| X4r~ב)Ǐ  MlPA@p vIQP@`.ffw: өl}yc|g < 0(!_dWg Xl=XmS#Za0F!bzCܴ:"VR _#Rn ݤ fRBk$(Q B ?Hf@CE6Kf i8~AB( = LJ8%U;8hTPAlFcȀr]YBDT ,,#Pl+ tޑ&Y&,0IH !~c*& P Z_ "8 N ED{ PPB1$w-/vrC0P11N"(\؅)T jxIa$YP6y"1  k~ ðߡ_JmyNz7)-24G$(MȵCUAG~PH5@Fe0 a ڈf fH(KxƢhW@s6Qa?魹+λZ~aKrƋPE%bOiB2ʅLPԼFvJ>#]o*bEТKW%]:(QhAxPj$RP2 R+E)z,FX # ߎ~%@ X `'1k/  E78u(l`acJBj9!p`96H2+F|3DAB_zL?zvX[pya 8@Mu@)h^,;b8a@qa@t!€wct~X+^נ hc^i(:d#&Z C0z@P,|=U,9I 4#@J`cl@GF( J$<#O-LΒBʄd".NJd@sy0s'|"!/ev]131`L bo fhŤ@i%CR &: @Dt z 4|z,-BZ(?# nQFh4:Hh~`6}Y~_$jl/T!D\@Z(QMfQEyLL%F'?BBJh^ PTzxLj|.tpTSFVD D Ỵ0YWa3zP f&6hjj̠ ZP@ 8h\%"|L @BTI=T3RO.w !!B`OߴwN #șR L"0&J̈́WIR`pGk/?(}XXk L[=\TE\,!aq`IG b`f*8N`' ,D4d4ēADK"brR BA`K`!8 !P )CUHQ  PL\d, @DE% k "  PaB(*1J𜾖Jo "`N h  @(@bB&Pq*W   @$  #?g%`!,D+$&P@Q_0P" d hz $#P(F",1IUO a@hJ$A0(RBcd@! <0b!JZ aP"H)(ZRQ@,@, J( a "`@{&" S@A@P%Ce^G*,Wp PA @@$W `T",o%@PDJJIE~ͦ@H  % PDpP1(F*"0Hq`m #H/ #\QA$:@ F""WA @$  <0XY @А E b"P)! @( NV`0 O @ʍ 1(!L@;8p wd. <A PTĥ?%%1м3 K´w$xI2}"E)K!koFw@<PctUb1Nj0-@6Y2r`QkւH(x 3(` $H_`¤ Z}ߣ02$GV4r?^NrDh+4*n?F  ?zO( Qsކԏ%RtXP aB n M&7ɣ%ZQ A| "$Wi_Jbq"4c\0-JF@a" 5[ramy7cG2apӜWF8F@0QљNZh ,o B>L>%B'gx`d4RrT_e's@q2 - gS0E`c *U -?L 2Qrc,5 $?.\ %@|L =bbM!GG!z;u/B+AD )=k"+5efI <ÑJa5ZT I axWy7XǙ`ygLl8 8,b>f/Ӭ @P r9pCIVê >P]ԃ 8@D4D( &@i R %ZW\#9" V?CÑ@z2Ҥyg&l;Xik(z(%qu0dҵ -mq(f Lx&"EL0Jwo5$JB< CCa*%Cx>!`$T6qޠHp+C$X jXb1 t!x`EP P @NXτq&K >\w@hBmkx@d4DC! F,ᑨ@uGq"HŜ.I9'9Vs)X)KV{ YԬB-VJR^Z)b$`ykF#Qs'f*8iTQY+31/@ B$ (t-2,&r)T=~d s(B5u "XF@@ &,h-9n ;N/FC0! n|I6Pmb X~䓻׬<06,P]Z4yFĖQ>/1z&(?7qkj!A\! u>,x} ]?@ p怠>B#8g?Nn;5PF*j24 E!F  S砒(dI-HpZf Oˑ@R %"I|@Wzvv'aYEA%9)Cj@u:[@Pό%^ rcXLHWa"DJ# s 1 # Za0\2yGмLҤa(94$_~D!`@AA1 (ml0NG.V"r 9|@    J٠8E w`sir%(bO  h-t!@PТPAIB_D^~9{5&H_), l(P(@EJ_(x^?@)ЀL/" S:Ӻ ЙVz?P <<@|^B.B">DB _">D9P9@F2w)E`<S,:xLSry  RDD61Ο/dd| p'P(Q He*TWy?lL  `@fAHPpa@JA$ @M#@r&#H 8 a \0pP!EP~XMP  R   DP)(&P6j  0%94RNWU8P< # ł"$,S? P & t#" @b A$)YW;M$H @$0A` H@B $Bee "HA 0p㘂W섀AhB`xYAa`@@K ? ~ ZlC@dKNSLIA #{Vkr#<$ E DRR &HSHGJ .CT @C5+&g@ dNt7>Dax`(Z#X0K rr9=jCpEj)qw6`hAAY~ ,~>?%#&F Ye_B0"ojok5܅XJ,.KGG k@XtUqUh"uu6e t}[Ox N!h3? *~kAv  0 7#AbLdj Z.P F*P$N,"IY*rU&||\`GQh$ [?E+cJޗZ` AHDbBKbu"l 2 !r D(? "p@AC+ @pA oS4౺Kr%$ȈMpe5CD2 LN.b̥xWI,u;E;+3 cl7.P?G9XXpV$`@C1|$Ha"ce@ D.82vy0h@&"B8)22$!_>< \0) I ({̡tBJ))E 3K f䟈V?< >U%4R D0UG#U idO_ r$iX8ƦJ1!_VOɄBՙP镢$?DK`g* ,LPR1@ ΰ$WA!6L]/5Y"w'hq Y42&f>WFxyc3X `bd@`. X➱I2AV!R*s"?T C4B>jBR * r̈B(9. GQs0 ?qHF6)iS4 REM @D:C"ZGBqjn}N׵  Yh÷wr#quRm-+Li(N.z`ޮǞqU" .c\  j EP} <, ȆGP " DO$\ՊF9xJ_<m &Yvƣ ]GBm'ߵH@$: gZ"&P.A0 JN䡤Uy<@AA G&@)L`( M#A!^@*ocxgsvB01P @[ceۇK8 ·+@SU+.?L`dPh$$(STGtҨ;%gՂӑbQ#hܘ4܇$ HqTԐcW0R-H)_0!>1.R8=#2p`(C.8P(BB0 wP;\oJ!EbQ` =;`P |I&XJ*c jw+v _bSkH\;e0fUHF ptmElgHJ$RͧIMʌ AH?BzSڊ`EJ?ҢE<0'{MқsWh^p4R¤k2;L]VdxuTDh & :h\LN' Ax4V]oΪ)>֡uJP $d,$< @ʩ| $BUT! ifZ  5 %U(cE4Dˎlb}u\|f DPU//G*  @!_V2VJDVD$KL4().P"10!U ȇI+."6+o !AhGXt* ^y1{bb! P [o/yi* )їe#.#UE,CQFA2 AcTzQĀJݽ-L#AUuyF, "ȵibhE,b&*$ϠQ4Dr1%#A6*@!.٪z;&IkI{BWd Q`1'?HSWSeJL]cVnFY~g4i pq@$| W_#ِY / 9ZD N )cBB}J5ÀTx00HeBDXJ3A]L"3sv TDATIJ`T<N A \)Uy-R B> QTyy`Lj iFh/Y׵5ب/*,+j?}!YvrZಀ8^ K?6@@bhp(/@ rA +_J%N"f X=*k/d$*'D% eg8yA!M8 >"Lc- 5&^C6v?)5f~Qr\FOIJR? f`Qfhqv 4]NH#m R(jJtK10Oqp' @:C:@ BɡZKC+_2 DF ft..mA#I{נEt) PI@;%@cTE!Ē0"IS2S%Iʲ'pP*&UU[T}ꭁKxkY)/K V@0 COW_,d@P,Z=p%BA.n7i0aM6&R߰ e H D] 2)`r"QԆAUЄƂEhf+2XmFJ qG" ڗB'# ¿`(ϊhAG9!fZSOlT`x 1x7/A(l}>Sj<"J(u4yrjhw 8 0@4Ax&TM(1bD$PI?*(Y0@? 2;I{C!_ H~5 p KC 2lĿ;FO\!*pۼ!a!a@ +tfG0XҸQ b `(|piQ\$reA}LO7A yiz+}GxV.Dv!N> TY||"U Rm *3D%BF>%|7 Cjt4SX !]`&B[(mƠJ 4QK*0X&9k@8K`A T!ջ/ GU!.,T}oM j@FM&C-{BYH)4-'Ł"4R2jARCል$*E4@Go@"mD#?& kaڂq 34Hˬ1!ZWP_@u0HEG^~/? >\ܿ@  'ET!@})( .@ktEO /U\B]-[_q.w@,*(ȆBBD ,BPƄ@;J" (rj%8z)ZHzDEH$Da!*,Xb P'P 6L>D8*5 EIA =&";8ݒQ=ܴ yy F8$)@(*&jVr_U8L#-xTZAJ5b( 5BۄDڎ\rrWVi2)z0m9 J·"`}/+8[rF|v2E|yr#@) [ Qk} { ARwfAS䚇1@lo0I.Q4#0~k@{ 'Hx{C8G'"?@O )%4l \] j1ÜFU+dIycq7 4F<ypiӀ K6{}lIw@rހjo@6q_?@>|^zjjF`!M }R1$\Y膱Q'@ AYi0CnAȲ?pM,_!%'L(/48esIQPe0.[ 8dCdCqun.D^G^>Q""""^4:@sX-3Ӥ0\GHj@AkNO(LB|/ QY -!DMqKB^i%`0XGi{(ɂq*@ C%D (4"0F)QHDL%8JA1(NE( `4{'"@$@" pT IVE D@ `ʂ 8=JWI0Ծ_IAvkyDVtp9,*QANR6ck?*]k BU5/ J (@1u7"Se1(2 ?T4T %IEqa5B5@WI`hBpziU>N((Zmi ($h<>4&$@M Eq䋔@n% @wxdrAnw"L}C[.?T@d?;y&J "{Glɍ1 tqU&h  AzBlI`҈C-%Hj`0L(D8L.""L0DHwHbK )UL!HRJA0~<@bW3 CV$QibTd r] 3HtK5 Fm=?r׵" A}k?}AP1$@PF@ .N?< ȿ =2Na7x5%8 d%`m՗-!p=H @ ^+u6WMWQBt|"tT@w 5'yep0p i>4PÙ% h&%A@DthA,A`2 b. BAJ*ʆP!@aR=% B4jjC @9+a XEa?`UѭM/ۀI:M`\6SW4MUҡj} ȽXw-@l X@bHۣLF`D!#4NViOF_*= 6`y 崑ğ(vB@(4aEკƸC 4=|x}o06bbE|G@ONa\ bTw09TGC&r5y!?W)G1~yx8A tÿ_!# ݺ #'HEgukwӊ%21ːte;_~!jA <8<`$@TT*i(Ѧ$*98SE+<}z Jj2t U">|XrC:1C.!1O( \ A* 1Oy2Qa@~li/ XTr9ZKb,/^ )kK#AZ;H)/F?,_ᄏ& kbDN‰ * 4  pG5TYpX:A8B9C(08lGh(tPiQGXU%3CiLjz|TI4`R9 xNh%v' A%n''mNM""K͢FŘTNTp_̶3#@fzHT "(mfL-9[*@EnS J79I'gyA8q $=JG`5 Py W^]C0""6lo1 <ޟ)!T!S|?[[?!YW)2V4#2fj`y!W( ^y7XƟ҄\Bsz<4$\hhBiF(?~,aٌk7a2$NnnV/*n{. קn(1ӏN h;UҤ7>a/]P" t 9 *Puʯb4"~DBG+@r頊J(X0ȸAZԤ * d@GK8f9!2iC J=J,.ѠP ps?PX( Ě-Jvm J _iQF&Tk UB8A55a)FkB [BXB!WPⲁF5_i_KU@)V/t T@tR`}X \ iA"{8G_V*Ydup:$F8T~NH e2t9N%@XCk ?Pu/3 PQH@G(bHTTt&!M@km^?^Z! N2@#NPG՚ٞ<' C CƄkhr? ds*QA1ńxk+9 $^ Pb @ER =2BU(%B?U  f@'0P0-k/ #n>!!J S< 7=(_a׀EY dbtrFZV*tPf ; *rRJ zaԪ`[8<\'@!&QG}@*u"AR_/ф+>Ki>0*M2 ?`A*PhG1A >a@(w_,#B?p?:-*!4?BU'` p  np@10㳊# +#3(B!:I? - gn0]AL5q%.LA?t, G1h+s:+`,3IjnZT T8ŕj}2)yA,%p nt c8(D3>RPDR+Ȁ!wm:oB?JTBxU$ -U H('HX/06F(@lwJ/SMP;F4%W!+_"K5HB|n0Bd4@-%ŝ@V/#C 3|.1NjY O?/Pſ1@Bda8 ( a캃eJZ #,dj0!gB9@Jb,7 @|0@44Q@0:@:&*1D 0Ui@!AkQ Ah6HGҪ׀ף69ePO0O!!-,WHՙ %)@FҋOWl|C!@,u4qC @#=R+T2/ d hψDY52Y(n "b@(0Dxz 7SE`B@}D/Hh `r*V Wؿh AZJh@+T2&h8NY F?ɴ) ]* { |?@}M=  #7gfbF^W`O*Ur1xZ o(_ʔxٛD0(N?xn@dxJA(G N~( 2PtrJiJw+8C;M5/ ^\D Zhy6*z#E R+R8>/TF`!u>I٨ @R- iShz 'LG $0!=5HY P]UE G=QL4*|Q}?&P$7@ d+6vh~ ҡV\X%hRGz|gaRGf #Pax5P->S^~ ,%,I00"'B,M%AoRR L#2C%JP:Av(` vB ꥽[,},$K$0 P$I I# @db#@@0`@8yFʅ*#%@ 0!p PPh Sp;f095xн,g1'*i?` y ~&ǜ074iMH]FQ,+kKɆUAu ԼV/Ӹr < r cYwBa !Hު%P`:WHEt\D04zd%ਥGITtdQ)j%/f X$pL?ː?y>y(h^.^  B1 hM2#a&$M( fG <+|x>Pj?tuPJȃ nviKQu4PWgŪ#G e em1## "!d(J(\(U( /|$*P+ .+@`@Xbn "y`AԃqI %(r 6' eɢS1@A_%HILydKcxL%p(0g$Ix)"lT\w@xzIs e8 #Ǒ(NE@K $ p 2{ ~\ªLLA"ixM|`w5&2B|bl ԫliWN>?[&cf'i;~PT菩R{@՛GĹe1]޲q./!DS@K]V9p:YQAAěG.y4(@(dʲ#%gJ%#(II:`}CƁfX2d#'#72!3DhK8~t9Yzf'-/1$\cUGP?d;D*Ni3frc< AZBG vbc\t貰gAqp9z3 D Uzv*Z*0LH6U5-+_GG `9L1P m `=tAjLR0kZ0!ThVBY<` 90#T{#dEuUzȀhr@-:X8Iqˀ^ cE G;L{(RE09,Kdٟz`¶P"i%D "+&QzC Ϗ(Fh!_m }TIɶA?$!jB&Xsa;BaA$5 {p4rR%'Tp6re{ ?GP$P6,1"HycL!AptrH˄Q P@aWd]D@#,N! `z#M3 !%"`UiBhT"z=;P_r/s8}V(.q r- *2A $44$D#1"_Xn_[hS^<A +"UQA@ HAZ AI]Vkx_0;y_E xRGΏȡSMX4S'HxZcё4e=Ze'`2@L5?#W \Jh0.ֿS0]Jp%݂Vf &E)"ŎTb| :!"RAF]lSUFS}90$ψBbmg)Py` $Ht&!E@؂f攣V{cu4^rY8g3d:jzD!Rk@Y7"H5BI*P&Lģ@/;,E-52ME0$8$0t˖4Sʀ12IPIڹOYlHY01*]gP! Teoǣ@Ffp9$a1k/SB9)6/%A.B\|p2)RQBPz)]b-wHJ]> snI!2?5P0ትhGtV\TZ1ʔBG] qسCI!a# A(sQlrTQ N ⌭pRt Q|=g#QP1z L ԯ (Ag(BA$ECQFXHԁf QuZOViVN$XFhе$TJyC($h d)J Q(` Iya y|*'Q@$Hՠb2NO"G+ǦD$8D(|A 2}Bgr@HpPR%g0 *.*K8 VC΢'IL-B ?)JC_T$G`,EusވRArb+Abٜ#@ґ !1о:j*E,qA8@Q+"iO;ÈS (ϘqO)ka_C]QvME8Dij4WWԇ,&,)^85#*Q. 14?HE1H,DxD$"p pT( . P$u8z?ʬt Y+0-GW##(گ##4"$@R+Jj@/_h,ʿSZm#q!KE$k]KL%JaNފHF׾B#j'cH*K<" )Cg ~H& Ps ,">CLm!"I м\Eix @p`0-(/AyA QEC rÃK``a(@ `'TtG*%B|t63C! 8$,Šϥ΁&C9?Qy.=.3y (|z/Gp}@-E`BQv]QDZXI:'֑~/ʑye'Oుazō]EBON a)<\!@$X. \/?!#x^,B AiXx|d~P?(7c(\|zPoFy@  #@T8/5#"4P"(@(@! D!B F !@8n^@,J:C3ׇDQC*hS? @M(Pz!Z(O^@Y4 ^,)Ԍ^\@vF7 =L@/6dQ?gB"\A  "-PJ0GԎÇ`CA/ zi 'VP5(r,@(L XdsQ@c3`wDY aA~+p@@#E` @ "5I@*QB sFV@ Hvl N,晬F-W # 4 ddd1#Nj-&`5G'M!i*  %4'PB#)D!_爇& @ ah _0p?4 A0aK'!((AoHs搘Q%w6 K#L?\a=N94uJ@ )3APLU|$ .6(?ade 2* Fbt8@<@P5B(\U/3(})?ojTt=׌I]E\\DSA{,D[(B@T!Kf0&1?s vN jH"'etÓQxVиG@BYg53 9 Y#& 14UZ< ՠ@ hI - IB> ]y,L~0T:6m CJ0$xJ]@Xպ+g`a<n*IYBH (qܑA0 q/z5+Ɣve2`ʗ`gEA9EZҋ$5CN-@ BV4 M7(%_QE W$ P=  @2?aHgL@# "L~G(W4HNə~*#$+<V?M@@`4\B-,d/(i$iZ X@Bt``  $ D^I@< RN $tx`%@ Ҁ4n5@/VQHY]@| Ӂ*0NH DEFȀ }!b(iÕTf/hd Ac(-I`x!I Qn>!!D0D8 H¤/ ,xMP$.-X-(RtE@RdK1 :a&!* %,gDuN~r 9UɕծE_ܧ`AJʑH\9W~`W_W(]`Q^潏 |1g>Ph>" *,(Ddɓ&ij t/$DCxΎ{tl{8@\B8R>oeriD:F`<"LͰqQ-qH?i, 3a؆cEH !H)ȴ(H (Hadc8d T"1貊 T"1X1踆*Q #@"Dddd0 %!!""Ai^t@?\.(?HhDP5:1޽(u$R`Ϭ'DJ)}a,$zr:if&*+0B1tkeXB#?F@(FTJ)@EAja'#GYL?!UT6= 4<d@Dbwa s&?@?5|P`D`" Rw$r ! Zn!h h^$t%B] A^ KC"A[J3:٠Ba{ `S%h1Ά{E9Р#: gBиЩAjt  8>hh$Xdx!Zh|<<]>.JiC`LDM^&^)oen uj| oX~N( !&184b,;W#=0c{8^M )f0^ bq&~(m"Ɉirb+ 12QJTBPA* B QRHm 0%(i)쀇ݏUGڱGfsS>P[/W+W-#ZCA:9@fBET>HQ# '2mpPJ")i@7!aCGo󞧳@т]i d\V@ R]0; Zh8&H$80Z ' Q6hUYДf2" ̐P,+@`B0d"Hi UJT @Pd Ex:GyA,`K ^sii-]Sba wu'!Px82'! p,GBwIJ)Q [ɑ@P4ӆD DqwpӢvSEw{Ԍ>"y!-79u9prr" ', =@+䣳$A"ʢ 8s \bƏb`q&N3ɈxAP @b!\3J Ck@P) Q/XU`R_46EVf 2F0D8yp @&B2PtP)ChI9$BVTF34px4@T"y!jppQ  `1$kh5 dj(ŀ/TQ sH@BÜ&hs 5 sh<S44S8f(U3h>ī~2r ZPA!H 0)@ZHyV `B$NB"jR#v (!0@h(D? APP '9Hx!xEV,5F0.!@F8!Pp*` [nCD$ ()ӯ"D Wc-*(b FBA'ZYiSpATpt JD(*!PqB$z.DOD{"dmE&#N]?\)2@Ր|(ϒ'(b(,CQgL_2?HD ʠ8&\C 4jf $AĜހj>%J@6s* z92 $= X)K0XF G% qB%W))פ!(qHVJBY4)sd@E@$6)k@kiD|`7FHH t4AZzGH8@h%A  ] 2.0P!fBH)aBPY <4hk)O}XP8ro` A/QEb$GJΔ$K(HpIEt17EI($`؁ɓ/亊K`@(_h>~.J8%0LңBEwaSWB H_<'E{#,pTˈ@KUHi@vS*wfۊ#;` ^耢V)"p4b҃ˁUUY !ƀ @@Ph(&q=" l!Dq)&׿hno((! V$m ``hh&aNo)(gK̄K`(88)A:?JߣgKmW8e7LttŔ]PNeVkGq40 Bϖ&%bz^Y`U1'AE $\ko:(ք MI B{aDk++-TEe1=A 1 $賈i0*!\$`@D@K~Y"!c#PJ*u&w)B:wa(<ĺ(("[ᒐ_Ĕ)" 0-A EDPX*.#ʠ수`4(>5@Y#D⇞8etyHPp$a&R@<)_hZ H ;C xwHeH>h+: :\\ bЂ5NÆ-#/ ]d)jBlI|aGЂ>DT@,ϐT[?ang{b#ةA+ ? MED%NO`RM_,Ru30+wbCqL>+"tK74HU* D`FRPz#"yn3_q)U zJr`/0_J`+3X$?T &" Q:3/d@խ  `$@slGT BR$$ pjF (Zo$hzՠ_q Z " UGj4w$3|ܸU~=MSUtlXY Rlh'ȕ9Tv5gs%owNdbKh /*8=$OPGH0o`?|NRn~e* +k ]9fu%ҪYsH kNS'[1^s+Ve0UG X@0(:zDN@`<j5B. q~9Y: Pr@ќb ? nF91 M~""M@1 y,!APF/5 j}>}J# @-EcCڐ3t5{9p`PHh3@@p@$|vF|P x!L q $ kB$PA 4n _>C]A 6GZ%^AXaad 8hy*V( PM&J? .(=A@! o\=րS`{!urgpP+PIhPӅR-786$d? m`#&J g%ʕ\%|hAt x/ɐ_ $@$ p2ʁ  0B^>}` @DO x,4A/EЀ 08!-18hhC((!K  x`x ʧ83)@ @~H4h Ѐ  Ph(V`@4((@D"rR~}@@T )R`@$    @@ p pʑ _TAP, @cv`A|AN8•zK*KLg.{*VhT\H8A."<'$N%Sp@! KnCU X QA$ygZc@`Ba"-$*(@I0,h)KCY $28_op,}𚻪r0 cJCo maC(ҏ]lh<NhA= =9P `i|ifP@ME9"/3,($Z trꃔH<)XVdAfAwkɹ XqӇ~7 \I÷=C PO˓m f{5ZqІ'?w"C͙g'uDP]6VD }ʖ'EA )`2N4 MJa/L H` aWG  b??<2P8/GAY,8Q*KB2$}c4(E -Uȳdk9ꣃM̀<#(Q|rk,Y i/ :P ^ؓxvz( X<8ڋ7P!mNjnFp/PJn>n;a! fJ&Nd u@E,2h$@<} h41 ٣ /&a6#iM3QX*Gz0t EIRd@FNĊ$g32$ ̇P% V@ J%SN\M Dا*1+s Z+Hd$$IiU&5/v^4Wqje8M4l<Ksr@-K #Y?O~K4+P?hH X ̌Ļ(e6`4Z5AHJ?p PA^#`  jEN@G# be lXf02Y0C}b0B5F?,_ Aʀ$0(XaznDXF@b7#QU'`bMaG.xM'4 ][f4Ca8eJXV"s P"2ެԠxE3d(TajAZFN_)aIG(". >aCm)VX@;ZQjLSKOlUfڿH%Qg91기bTHT*2PF'0 v@,Y-@4Y2 ( 0=~@ͦ-@ @B?~T#I+!JPVN`1DM񭊲 z0P8IY @ӂiuJ[OA`dVBxy)"&ʊA%%c+XBF^O\+a4JQ"&&&RV)1@P}o VRβt@"'Ϧ,dmXhU).4v6ܸ |` C8+ZNnLM(DgM`Rش1V@t -JP`2xFh-آ)CB,y. BoȮ64R89S"I +1BPuSO L XAC 2K-)uw %/9Lf|̺jAIdTAu1 x`2`J  hc+(wLy8,bcJ-& \9*ܠS @ KIPG Aʬ`iDW"TaP h1h,Ql8zAYT5OQ {C:-R-GK4" i5JԬfGp %BB0 $z"ބt8 /qIKHh &$A%(hJ4@zND}VL4X 4k@xJɎ@I*5A:@b &P`yl)8q\L !:Plr_V!G~A[UbRH@cLR( (A  BrQ(BX$BHzic }Mq@9v~Qr!W)s<)@}I)u A #C?pF46{"*N0`s`Y9"Z sFt*LP1QS?xfℨ鑁iJ]QJS!Cy_ hʒ6xΚِVN](*ր+,nfT25 N̕*mc ݒ .@a1 i'^ %!B)X,.=0'x&68 }55oDJ2\ SU SZ !`yZMo$KQ|(刁kpdHP= QFź[R#I1(3>YU.E(ԦX!'\JP )GfBővqGQx&l)PQ4ڔufG>z9}tUi"epa5o!^8J/Zl3EEIȵzE |D9&B.`]hw@~$>,Zk^KP!FX9ʀՎDQn}$l *+KV46@5H7@4E4@/@R z]h -hOx  EU ,I X+HQт>Bp)#Hr-=0!g&# y]xb$ W$ #"tB(%ԪJ: WEPUH*J-QKJBHH)D5Dq2*&P@`?:E? fX$@ ̍ P\*hĉ .zC!`U*/T!J@?P]O+Ny2i' ?-$#O+I la@AH9@J 3rzF(P9d=Β 0*5=":]!u #>l/ wbTzH@XQa N"TLI@3D0RXbuo(U!`l*^"@` Y|Wh[XW{ ,p`p<?t01O!Zp0t%AÃM (d0ʆb(ب1G0GQV$pD$< H Az!HA=H@m@DkњЀA:!M*&*&<4b %Hi!0()OEAޅt)-P$,?]V9@ ɬ"%Y+1`TYA jVc ý ~ Q WD!H݊0JX)F G_ZF\ l ?,h0<"e]EF,l$xc< &e0pGWz89 393JOl t r w!rgK&{OW@?@?A=ByrLXNš ؀@A jUG<0e .r ((0/y?ǒ4dA ($(@"8OA@rx7Ar t$耦)v( CxMF O) 4[0@"!T,0:@GH i$%p   TfgbYo4t#q,@[3 h0(W((p @60p$琹qs !4_@0.#P) jKB aAe=$P0,ŵ"D0Ʌ(0M) Z :ȡ`,Ga醡! p$6krD@]. a?#C4$F ]e0"t`,_?8ħNN"  Q,M@_qzG-)ąT2O#%X!ن(\ey87 ^PJWM1ඎ$ t %T QT%@Р6 (  .m+HT:? &:+?W?1( 'Mp;\Zaw =nQGQͳZd(XAr0>meOpA;U8~k  )BrxGK6~lxHJ(E11@tEDIpZ9T!%I_!%P ȘQڣԡ 2 #5Wf1eD xS0`@6w_`ҕ@xV(^mHH0EM-ApuX=#SLX~сZ( /6TĴ^/u H$ Et'-,K0Mf(L%Yƕp6@8Adx/DP ڐ\B#M`sp ,_tBIm BӨmodpoQYaQ/&hJx4 2LWlHa;7(2NiAxB0 1hxABPbѵxꌥ+@fUG 8pZ 1 I`0!! AU 4N.L瀔w^V[t@Y z$ dBMBEԲsw;'}{XrnmGEahG r} !" uQEǴ-&n4O*_b-UcH(דGsBS4f0#R,ՌIʈO)EZ=X2 HAH "A :Ta\zMP GEB;@h 4iWpeoz Q5tpBȏ ĄRд%Ҡ-kF%7`xJ (c UhEHD;s`S:̅2"ؼMGs<0( %ɿZfm5(H0NU[ p6qMꀹX=##dz* ` #1D!@3F@P'Ad^~/B  K ZQBEP A@Дz_d"9t1htBN(@@ۃ PUhrR/E -5ߨ R>A(H7lBW6H߁-C< O~2> JCW0x8ܵ^zC.s3XAfh0 ?I@F)`v(ZLS>@ "\_TO& ?xI*|*_* wdXE^f˱`MT}@D5bToCAК2V"Ǵ*JI@6=p BJ&0\"ha DD Ea:Xy@.\b4P hCtx`#xFb(S pSl $cPQ1XqDRo 'sJ` y<|`,X<')e"oGJ9Ƈ P>FM (@( g@PPr-G.W]@z EQ@&U+@m db!-4"+o#DI8 %ePf_!Bl0 QO?Z? :!r9gArdO@PHP H.+% )$"" LpNp&E!@b@ b(yoBO\Ipb5!A(!k!eT4N (m aj" tpΙچ4 7@(; !T >#C%G"p0+p݊jpb"Ms"T%J cW:8YDŔO V%`H $ **a&S]BYOy+OP[OG`*> A1OSjHX O 1'7BcbM!~t1PdT ` D+d!TB$6<#}lr^Db/`eJGBp7RzP%/ 4`0Fh"8?44y$ xa`>2Wr';~V W!\r +.5vJ$,Ǘ͘8U!p!еpѡܡH-V,1k %@/,  (4EbN`PxS'W+H$LFwmhB^D?H#0ra"9l["Q]6}NmEW FD!,9do!$h&CBX ~(<J8lQDŽ$xi ?@2GhGڡrBB^(0`݀K@%#Q*?>PP0>#H _ BPB?'JP?=A[e@@Ɍ1]jA]آ%XIÉ $1__ J 4{Çaa@F@rsYz/"𨭃͡j3S A[a7'&Q0K?(G˗/XL":KЈntGj'dF9JI<W:^tOR(@Y5ha GhC^h- @¢,6 Y  ХAhg8D1{VS_L`RIIC4&P&ȠQrP@Vo}Hbt1+!,g 4j#QYd1} p,; _`7РʇD (ԟH@P_K #)%! kzif~[ACQFX)QF+A4*]}Dvq Hq$Hao@`8Y5h >oFhu$0X=$UCR! tpUQ{(Py8@\ U?}i  ԛt(b1#/ ϪtȠ=Rj(v`@2 Y` uX@N<@2E14@x:2^ZЍ V#E+F" zqq% CF.F.&*gD0]bX?( (IL ,$a1Z8"чP1"ZAQ,ߔHao Y]#ʜ(, O%AzCtڅ Kȓpr"Qq8e B4(Z1hj%F`%i(Kk3Q?Վ! xDʝca(x)%uBe A੹l%9QD o!ܸ |b 2\|l7 @ A UH!JRa ȆɆ1!n4SnʐJAEZh?0ae 4w0 ',>fZ#-Q@  @io@!yu3E)_Gӱ@pʎgd?Cg o!۲ab!O䁀DB   Pa1P! dh/A 0<tBROH+GY(PU5@GF^nnn_B\ J8Q]Rb+#q BdQпN??@OM #!~Hdn /DtE  Aky X.JLR hPH2 8pTP$BCah.P裃1ZaG-I@kO{ f)@G0@%5|HJ@Y."#H0q(brȍ !! Ѩ$"Qac$i*!@3u$POףeRBTGk:=lc\!dAʗj5w@ b4D:)U 6*ҟJke,H^A Q*qԏkMdBfuaJ42\s>A~5&/˖'1zR %HhD~6x),=c!=-߷$i}Wr >BJdcQ@Dk"n!!}iBW@M E22)JP`eL@訡)5!_pݏA,]9%Dε9gX1&ʘ:fRB;,)  !R!I@PQTV  tVy1W u$myxm$4础Ej(S@F,j\Yh +C!XNȮVr%kN? o8:B2bﮥKMdJ1F+Rtus"0@@AEj PbBF*J#Ɖ/NZ~|9w( "%BPG (ZƀE. dRpA^@ y4P^R%<)JP`l&} $(+:A o$"հAH,q/0FTP< u4b e)(s5ĸGƙ#HNͧ<1{'̩zpoEWa P+ .',wV`Asi5P&d"\J˼|eE£&s?!&XcP3` ݩ)!'H!(j4V |lG) ;ĖJF/(M=[)F GLTb}icEcC0 "K RbP>V4yDN0SWFK%b1i0p9tv AB9@*Q?(U8r!x"F@AHݒ &XON4ij4@gF"(Vanj)0̸c@aJ+ ec  AN(3/2)`Uˮ_i,'ȭ*遛0\)`1Yr;)4z};C )!$!S]\s}) w}@H|sْ8YXB!_XCOv t0B4HЪv  `&>xw! |hfp\4bH$"R,++ŶxO^x[ɨ\hj~Pa†Q?#.C\-#?4Hb )?lם8I{aToHFNrZ >8jk r4}:~ue=&>dcfJ{@Jg1-@]M@Mjh .4)@M X5ZіR.B L.&!@Le9 E}/CpCcHAE OiqBQ2y*?HI8*%1,$H  JQZK1͏g X3Fl<\sF E BUN;FGX "@00i"60q(^,>H6ؓXЌWL:[3נT 0i!dI $4CI%RbBD4>yU:L $  @d٘ P` ʲ H-*BAHtIIREP @@ @C3R Aq@%TȀBl@#$ThQ0U(!` ~8 8hnAh4Ka@!soN $ʻL0,nD$hbRD8nK` Ɵ T„ r p8ZQyٙPn@$!KQQ΄P 3Ğ@UTcz"A4HjȲkx @UPˈMwJam.PvW99@d(%{+P@9 r'$(Ġ#DR)81 u) BTHPk&[3j@L mEQI*F0 _0DR*&i'@3g1p QTCD@nAT2&4ZB(B Ɇ@ȳMX"2 ) ,cb{sIVI Ae>|X T!tO@l$`ť PhT H`|/FȣNFOóvv;;;;;;;;;;vvS:uO ~=@A A PH" Wy"@$I0x#(%(}P0V ht['zwl(4@NECJ8w"f~4b(0 /?}f~C@tANY Pj0!@t&ܠ ?]=PPQ@$5:@%BUYs1( EPw]@ꀈ<P.I*T) Td(BN tδfħ'S"(q!d@0~@<!@0E ' )K'a0H$L ؀ '!b} >`x0Q1+Z?|+2MHJ wZT 5@u $G - h! e&%Eh8QJ8Xi AW^a.YCZ:-%R Jx9w!WTА0FU, jb3!@,?ؚülM:Fg)0A:_FPS oHR1Ixu|*HC$K#`%S S ‚0kӱ#LQB'NA,`bUq>Zu䀞#)!X4Aж(=J h (hw~%DJV0|$^}  @="0CH b % D3E Ғ3X9 ?.WBXO[JYb!_zu Yqr@A|Fa_TRBWW'nC60mQ>U\C>1G7hiTk+ "Z)ptS 08b paq zĮ橘Љ~@cgs':'e콗2\q&$k$ ""iNJdswM E}4GJH"V%מEF-YںFF Qs5K15 ,UXPdti f>o2He68Y.5Т f8&*ۍ@h44Qoj5FQ̀?@HX" 8-l$k&IN]$EE^\X8BW!EOGͯ Xc&0{П.IJFDZhl D6#Kgu*pg"hNmEum#@0$r WzUf렆VG` =@$٦tUU- AwCuJ(Hi!S- (Z*h)Q j RVI|4(%Jo2SNt%U@ (.]D`UO'E䜓bLI1%ϒbLILc Q|20`1:%!dQՉ1R%?n1+x<.IQ w:LƔUx׉E|)Jro, BJR,`!Al@Pp[ dbA iV(Ђs(BD'm' &Ij3`C@P !Be]?)Cŋ R @E&C Q LЖ^! `2 |jdjM&81ɀu#TWP P@$acjzɋU ,Dɍb@B1e:FTyť* i @D/I`Ig^VJ!H 7G  `ԅi ~:#Hĵ (& ?>JhC?-,^G?Ner?DDHOһEfVm[p9c@(PI#PBFG̒VE"|\xL -A-̀?mخͧo?yCy @bbG!)Ԁp.Ftֹ#?( d|+_dv.m2$)^ M )w+ s?ZSHANhih=]PG&E!74s/1"A<@M / LUP?Ŝo(Di^IN j2nlPFL4`EBAV*1PQ)Z.i$di .sD?.z@YV P FԕKbgiw :`TҖULΆA=\ F0 $!V$[?WW2;1ii">fX\!"'Jp;X2 b*20("%'͒ ]AP( J$h%v.-(@4@`T) !0@RAiQIE1ꠢU}8䘓"f\˙s.D̹"ǀpA!B J j$Nv(b PW!R*Paj(%5Aί/p8>+O@^` ĭO, ~BO!GzX< dXh^ b! `U͋99`~i!܆O3dZ2#̞ Qɂ!I chGBUv]dF1EQ:p9Nt& nZPKB\iB:P$(EtPfABdRipj5Qj4 |@DH(6Eİ$a֠/@Q-RĠ$ɈKR@xR !$cR1KMv (LgL) C;=3 up9P=P9f24T P< P Fn`PF(A~^7 P ijkCDQ:`G%1"[oۧOn=ZyV0P `!@B#Q)$T_Pq~7oRx@SwU-7i=b`~8 xINpH(}Z@_BX ea!Z‡5ea)ap4EpP P-ZOhK??$H+)PC YQhQC07NNGASp,\ $2Pd 288`0<&'c?` 0$7TL@Zv$ʢ364bX Dh~S,ިQA:Cj9K%(Iv ]> C - A'􁢭CZ G a 3P_{:׀{-7GSaC(ĖdqSnꇒQ >: Rf6 zp@8,t;=|>ᲃ&C H\S`a Ŋ@A4nZOl°&ɻz<2$V)C'ʏ@>.X9#0%"GK>֡7Q_Q[PDLBCEQT~MO" Q$ [" tA\,n2ZoY`C( PLQD P|*e0dFAq10`IB ZW1@N@TëG q<~ ;Ljp*OD  Dz$#aɹIPn4qJÒ6lF1DJ $<@!$W(CtQӦ}N;YNvv݇m;q / (~!L e!@Dٖ>RDO`1B0FI $IM}TS%&"uȇ o)_4Y Qh j?K"H*=9&0B0D2Mk^Y M>`App0B D Jip XATuF8)&u+;,VBbT*A /ɧ'u=#ǜD OڨQDŽ""|ET?'W |P($,WT41}9Gc6}'t^I9&$ė= PEs' J4AE EXdZpP-]5+A‚"zS_~tU_P_yWGf8[$?ېFNUVpؒ)'ψ@ G!PB*M= Xt"̨FIB"I/O/r: ,<#0F"@@HDKHpTXA!qu@a0 Cp= xL$@ 1x`} LϤ$+eZ:0̠V((cRR_xP)Ad e?D@2 F7&F"R H+T6)RT_l0[PNh . h!l RhKD>=;H6 4H @(MRk@5@5R!x^_YnSۧOn={t 3'8E`a$m;" x^N'" "Ax|fYl'Gwާz@@v,B1 ?y@j aA .8a(С3HaAEOj|pƦ/lbUzC#,6nJ h!&] k`&Q < I}d"͸J(A@ Vj p r!\%Ϡ U1c@LP#1M B@ F(sųZD91Hc6 "cQ *}A]`Gr.y<WԆu)邟G|!Hz"nlF7(@d/62b1pQAm@-PE+yK:`B_0L$ A@$ 0 TЦ qUUx44 yyb ~adByy0 `b\-=Z_0@ arQ?XJ7= pbp>dFhdJ@-{_D?4 1,hH/@`FA~4ѿ ͌Yl`Ў 0 (XGl4h}c`/y~B|.B/!`rC\m{=g ACRDG(Q]N p$(E'^=eΖ>XLC (d TA 1EPPJ  ,i9N@J5D[e bZdIUą - $jW@@ CHXգB4ϨlS\LpçOA4#jR',q +QwXLG^F 8GbJxa*Ta,C$CXAb!(ȎgȆ>]&0ġF(J4yh2q@@ A Q< 2h:A4_?\|HG7oT;x =tD AP#Bx#,*1?>D$\@?(Eʡjq~ii ;R5[E%ɓ^ht9p%v9j 0&$")l CM^K<ւf(K a#}`Q KG# &q?q MRU@)}feFU<㙃z=/N@H&2CXB LZn}0+d Nе-X`y'kn`i iNmو˘d5<(0X 0BnqPDMm<Ԁ:ҙwg-eA'h|53zY GYOf Z[h‰$D"/GP Ӂݭ%u×ŋ8 T_ΒE yv\} (A@൤7Q_&%aCD&,* ϔ{G / ق:It{ <1Ų?003U;䐏WȀ/1(ruT,0,HE@EBIDЪ!e;;F|ȥx-5$C}EābU@M`S/fAǩУ4PdR ٫*rd1R\xlaGU 7`2 * n9\ҽh('vC]8 C4|<(=5,,!я8ۃǫO:ҧ&:|nNdVUկuץD&ߋxCʕ hA4t0.ҫZ&3Z(dHVhvI J9 @0jPJZ0Pq. QAWG-ZPWֹ X C(GSJj,R":BqBjG(<:dT %%u#)CteKA]V-@MCw9($6h"(AVX>jҙ!/׻mg4`gJYa}kNgz^Dy8Vh K؄9y_kol$p_?q 2G$` @8F!'Np2<` S| _YZ, ONFt@I^m>@yKr5N!ˤHAtĜesI1X[~c \8C{H@JrfB%*Wo"is&@P i ]j EZR&vOCa)Ĭ^Q[J$+! BcJA T_l43O>8\\f/A%8 @>BrvxP q[0>b&P}?9,/]PLFs@[c֫F?|,a#m12q*H5 @@@gN:`>CO t0΀ v/7@] OZ +T0*VR?KL[ T> CXӘ/pz4q$4F$ Q_";H= [y$̎[}xͧ N=`3h ,x N W38ʜ d `D(H~ Ӱ ߰8Ѡ,5iYYL@R#ZEj@ ͭ0>B@zdS Q(? !*{ +\J@8g<$U*JjН 4 bCT @:l *0.5kG I)K IڔM|"|[fWZij]dd rk/` a(wb S( $__ v3 #;wlݳ}zxZtXh F5L%?'&ߏbf 1+ 4|$`Qq>Kʽ`@Dyw<@9TPVܶ@v@u DS[P  b0 4B%9 d }[[_0 8 <jAGAHև`3_`^]Ÿ0` A0)@(c33 +d!gqZ ު`˟/`~haG EG3#oݑ-Gp©FX*Q>:Nc` 7_ !E/@%)^9J,h~&Z9}T1ÑqTPȪl>"Ap`Th D%E)vV@7dH #DCpHz! C$Q@ QBB(Hj.wf>IMRYڨ@B A/EB"FF ABɈSVw/@@ LW|zm m6Ͷw;wlݳG`΀At.iwNr`"+JB7E 9$HS@_`9»cCp0|@(  )J1cAB)P]]*R-@?_WTAGQ"I䕝 (@=\| @P((8.tiIDyA09/zDt,BfATX. 2`T!K6cl6;;wd9eq% $8 Y@a ‰H Q#%Ʊ )#% &JN:tNmBk ^` FT/!Q"B/7@ RDRC(( 0  ̆DkJ~p܌@~G$ PPE*9\X(N;08N K ۂw B Rώ 19lZ2TAR K4pJ?ILZeH1|'(P )0EizX vV%PhM,d yydH6`bn\@\L@  Tg(Nƈh YYXQP@`=ffw@lY`cL !($v ѯ>ˀ,Wf Hx-PfIc`aɍ.*@ So+-Z@>QA B 0@SWhJ9hn]c0@:1re`Q%tyu-g r w*0,Ei4#I#3 +1%ϫۡ2m |q׈窸1]y\x>3@24`&dJ00AĒ*4m d '<X+ǔHr򢯎~麀sc o;*~rc,JOV@1%(zZd #9rFv}jmMlZb"Ûbl2ts `T _@B?7;, @[((%z;:>?)&^ٱ[HrݦޫsBw?cAsVl@ЉKqN~AP&H- K,Cy BD[*OP 4gӴMKjSaUV4XSd7 OA;38ydi Axڅ.4t 6\>hΧc#,s0٤fMg4JJ-@BIr`["N是|@ъ3cH'@4M%J@T+ME(Bh$UÀX= TA F5h:@(JCh 29C(-QB9 T3 +,bsE5"@Ev&J@u}+ZZ;j9VM8QA@`C8< ']Mw䓣g. `I4"Šӱ~A"tV#\#g:ޭoUHKkr@S3QD Zdba)_A"թ+_(l|>"R4<(+j@ |"L ̀5gx3SlF )$DHsX Ύ%b@ jF )dPzEBԤyL Qި@, <"@uŹ5 R'%L$(Aq(y&(Í JjOE 7$؛g`pƣ#S%KU,tkB)Bj R_,|TT;h23dLnnd$=\E g$Z RTHxODRRQ#F @Q- !5bBCni9"4B[SqaB(>YANЇ-jrG , R_DT%T_|;ڇa}mh0XdAl^D'V.*jm]k톘%"\ $Dj}mu4(s-W(!NI(@_ausF.D+4@"Pi A$Q!`R,8YhKzvRh|+iG:b1ZVIL 7- S!ŴtiI\N}$j)Q4 @P!!AH$SX@!UR:|HVbꤊJ`@C8}SOu]dxpsci* I0ʢ apHex JUSb> R4Vh"#@% PGhij6EI 6*d3D H09gձs 5G(bQӪm񣅑J(wʐa#* $:nx^n m @lH̞R1آMʻ9JʩNZ/p Ⱥ$F Z RaZG,!9U(Bp UH2U6b!E+2.wVHHK!Խ "`cOx #f@!I("\$\A ҴP>=P -P#|$C?"ڿr %CS:5{)"jaE'gA(JHTh=Ia \VN"SZ[/!P@(@ Ddn,7I$Y.i- +rdBe@O"R)ƾXǍhuS5əPt7y :3 vڗyCؐ|C]n"ʠ)(=@I(q ')`$J‹+$5 ' t`4 (Qԉ]'ħ]4V`9R"#*ZE2o |Al *y? yvF@(OC $ # ްy΀H 4Ėt=>$ýBlP44A=B A?,zm% 1!K~^?,۴Ʈ<g !Ä!K̅C+`J?@TPf8}i7OPS?(!8 )}# @ /\f ǺD$jw &m =0 d2 (z⅔ @"3F y:!2%)@(Q( " 0I  *\>L B-$)@":}GF t ";4P'#b@gqL,=kjy!6XAIcf8.0Bpf}n ` C퀈ǺAv4)g}j2[ѳ) 9K?V`s9aH8؞ ]gŚtWG CAHl,0(1薒(FR7M/+Z/=&%5lFZ5+$\vL@˭µXi_?#UAd@xxM?(Ap>`5@fr{SÂ˞$^Dp zxR||䌋OZ$($0X8 ;^OR Ƙ ET? M_JT !HQRNHhDZPVEN?Z{:GzqPH9,I&Dc 2@ ;Zz{R_b!XDH\_帏vu,o@d 6ހr31a!TOabC$#d送!>(xjz|0:"tX҃)*0 G"i`HGDIN cK`$x1|jb+e)Bp_B>EAAR4Tq(AZH"qJ 4@)g (} (Pk(?U ce P%hQrSAL. @0AI 8 ^Z!xncߟ  ;on 4'^<B@x,*0 s!PZwԕAY-lV@Q3=T4> O ˅aIY 0QC Cp YT pUipPkKlXWi۸p>Q"5\blŒyQ0B j^2HT,A`{7ZԠ|x/)] P/ YTyu-6a$C rD$= ` !(\πA{@*(C@+JH, X+J-h(z4P}A |9I!*$xЕ'E47aN9UA)`e{ɁÙB#w1, TCbrAOP}""4_0ut%,&c@s "8hCttX $z^!MH<@:Xč06R"N(GM$@QAOM:MBw<@mAd(rH|Y!@ z"tC)Cל!ey bbIU%*10 (\ T#?- 3PǗ  <@9^BO<EmD?p`Dsb ; !yZNL  *a eFzQb1@? PX&tfР2+ F 9==p7B vJcU Pm A0&Ry0?h2$ w ># ]:GiyB*~vqO!B? {͏x#( ج fU +aOth4-gIFL?.`G W 0U PBi@Q?K"cՐ'n"Ys<"sF+|\+Wwv2?j@+IyP$5g *@#;"2Ec€#K@Wc##^K}⠎~ J'Zx s@%@ z< (^6p zBH.(Pt P@s(dɤLCH΄-Z@Q`J|#BqHMB}9w(P]N^Ǣ( XC"F'Q!PAgy-UFٹB0 nJ#K)|LԘ,_@5RuƘ+1ql\JA6g=m؉T1",Hb@Bt~NPA/!"HLL@$D8D6A T@=@h +$5Hj+A -DǓGHjj5@Q'p9G\Hb A8hZ7B MW~$SQ}p@R)!mE߷+< ˀ"E#G1 tW9 0s#@%FaKH8 qDh-"ar$(nzHPZ`_K.FD H3rdBzrl@LVdwL<H&A &"aFdQrI>Uо~`գ e ZR0PLyƒ) 3@ zDO$B$I$៝A?E#@PJ6MO!ܚmJ .  KLc ~FG b\IJ Ze?K[j1x @ \*dcv`?@h€¨ᰆss0ŀ@Q iG~1Q(h) cqcGԎ$b!~(A5Lm8@i !)ñr  t?@./@t\`Jev/!sho ­B$%ЦP*ų_`,PVӾ[)aZH4X@Z `q 7HGxPm q_61l яhF(la}ckhl7K4>EW 5!x8z4mbxM 5E+! F'#Cj!!!!0PQ  (aa/7߄aKxSc)3a~SȌS̸@ b{X#}~O@i3z@V)FR֘i!tM=:Q G1tCH``4`%O:-v Hk3O*?$@B~H44 sP)D~C"P(c`ؠ2#,0F\%(fvx݉0km*"Q?ϓim0s>U:H/\LA 2 7~f7 8L@ߐ !<^B #t  +;XQy"NXZ(4Y;<P$p<ѪVj6!1oq@" 0Rb/ |b/6} O" % p 2ȏ}BSx*(0ZS9@`B-,+e\@;zp&nZЎB0# NXjAB¨-CCRzѭ ,y Y1R TD r hHP +6)O^IUy܍@(Q,ς(*00Z h4P7(8`$.&AHL Y3ЋGa~C J& m?)˄!T"1yk"k:q)#BҤ0`p+F`BX1=&!Hej  0xyL1E*IH&2I̒DTQ0?%QPJáb= EG]>> > N+P } {ާU" IQ5"+|P7X)k$h̅CAxXK„Pq'd<ՌR|{wSܨ4tpC:TT Dտ7ʺ WS\ 3p@hoтfT ;XzaDF;Vl`0e W Ѕƞ%IY^dYhSh4T"J*XU*B(.M$(hY HXM!#AFC(hƌ~p*n(Ez.Ұ0A׮A[" %<MHH~1}`h:z8 !z$LJWR@Mn G.zZ\J@ Z=PGZIK@ HA4ABbLF_o>MS% lrwUA%1B ?r~ 1Cp^Sɉ&z2H@Aϲ}o EwNp5+QQA#XIQ-/ Hvˆ@HAp&"yihLր%7ʀT?F 44Q[ LD5tBX`S-Ԫ(HBP5>H=+0 @UD?C q+PADFF>9b |(@xXTiT~ЌL:5/:dޱ rDFN0Ę04 FRO .rK"̑"Im߆ժcTbB*$JV~M uY 'VD*2T,&CXbN 26y\"Z (S2g YwU4x,(- CE"xnEE62gA&KJ228kPa&@VR`T ӇK(,UO ԋ:8>RVf S~4*/D 41(M2_MAL3?#G8c@-iJ+-_r8Cɴ % t &4ǖ!y wU\K|%$B/#ȡp($haQ!YKrrBQ U_4 @`E eg@ d %R0X4v$$CPN=xX yc)EGhPH$2TJ$I4@ )T9"r(q  :AH4@He8 PRR@3S) Q(#E! PG, ("C x; Pϑ,@@mBzpGw@ػqK7.1,1бh "9V@0)"/`@Oe  p~jQ2CGˆhq@5(TqZ/4 J0փl?FH!C 8v3*. Zuߤ6A~RzPE_*}$;1HB7:xlgƀ 6@ci(ųĉ \ &H&2^:^8rI )pUp?/\ 'Iih0󁯨wtjPCCQ2%!!?efbR`*Ԛ""j_bʄ2 ZaS?4+L 0 c#YJ 4&A6)vQ8g'eYvF|-H8CǺ~0@t9GEJDiǠ&78F}Ҡ G `Bl#BހQGi#D#Nq J#bgjqJP 6^CB* mX;2@5@d4b$Sހӿ̉ o`Q:aQq A91$[3["َH ŤQV?0`I h8 J%~Y(&$&7}hCZUP*?h7‘ƺ! Cx$#t"y.AEX:&n$8V1#5`F⹡@m9A7+@A) ̀<id">69S`&2օƦt&PE,B)(RB^4P^TUnO5ͱ"cɳ&ҐAS:J:FnNP† Xd@ (OIY WP_QMAjTBv UJU#=p98=ގ‰ `n!hܛB] _`;cgPWQG$0@@@E*ǔe)"4RyybŋThti@]%)d#*@((80$PH )IU]\A$*Nky,@=d"N W_?S X :D HO[Ǜ>0 qp\hLbCŃhI2*y ܰ,A`$ #@Ag] *<I-x0DrK!<""+.@p!;NdT @h,JΩKyYS@8V2R?P8IPCV5fPCU]Q[|+?lN?iȧ4'8` S?݄`cvNLQ 0q EgNF\JJ G0v#IE;QLJ( pWq; #| hxBTFD 5aO˜;(bPDBMb %r* ir_s: aK.VN")Pj14B$*HQЛPJU@6J"A l[()@(*::P$@_WBQ/vłn]h;G GFV P&x̙\1?)i  HI1GQ!]JPZ@5/ABl ^OBL/!.s^p,Fj=! {9(@!"ňJ)BnRR`2KCYVP{Eh#-cڢX(9b0>-A ?N!`o~ v偯R1QBKAV%WbTR1bxQ' X#!{,DDT1#šL @]EVo!U7&\~%&r6< )1v JC JZ#w䬠 !ι!+a/y^svohB5ED]9~%Q*2̕Qk30U/P$ V b_}VR`D? W%:,aETrZ" S Ta VJ 1E$BE"  1c@0DQQ(Q&AgY@ehb JgӘBOJ0R֤BQaD (1$a84V  :$H1"A`z,GP(}BxnIb7ؕ *X1S-8Ua7 sr+QJئLh냸ҁ6"5 pE֔$ Z(Êr-C=JDcD-!]0!ij^,+s]AcjGBD&ƏP/E}** b$dr9? ~c U V#%⨧ (q#G HYL-yz_OY,#:b{MP傺ȌF@| 0KH vFԆ0#uPRVhduGQ )UC]C{4BA"ʌ4(bX>L)"]9I‡*v<HeATbTx $QJ1Ϝ+˦F+X⥋^|ʀQ|pv=*eXqk ¢^0I/ԬH8 @"4q@щ'FJo|2"JJdJ[oKH^ыnW( "."iE;_($]-RrP@eT5 24C#P Mg@]HdW ԖS\U,y+h-d~0 @5U[PA h #CQ4H@DOi`B娇{$D$-*< .Vؘ|J ?m]f>:Eo/uD+u%po1zR(qt^C,`1 SHp&~l SJ*12hIr_N?CmQ@(­#eUۺ0̞S`9נ TWV4s]8LۣKpNXXw1$ s_lq(ӮɈ#N`gN+r88‚I4ߜJq!WDR;ƔaH@W|a[TbGOš`o(,Bkp,3zeaQl H~cx$3 oUɤa ~I9g*Q w}a8`}'^*Hf@ }>P< a6"&D5. Y ňAՊ!8IUAX4="bS~Y~; FD($U#̆(AJb UJ(pM`UH'EKPAzXc ,[?s 9 STj)"b֍\0iRтC 9H,e(@2 zLퟞpL`TlE=i6*%a0d aX00*˃Cf dO#%Xpc 6M**V}_MiirAQQu01(`sCqD$r0 !Z-AL`hh@F2+R8zxu_^$C|?$ 5I2˔K#!iK2g$ CQp&B @\PTWb'ʈ (- $Gz! =` 2pc?L[z ȑ~ 0x##ɐ|x9p6@,WXt藈 To :=? H$= N PqL@K\VEh$1eF "5(A "8;HIa0(״X]vp"Az=@he/d_Cl\R8e -paO(CR ̘ s'px : W$|?S/a  ^Â)!@+0h0ʰSkEBjB? }~y|*! V" E" EBkBEr(gN!SSyKG4Fn%8d_Pj ̈ yPEr4K3hKwMI?Ѹ5'p7 [9sP]9˷ |Ȱ`W[>Q@B*@+>c ju,6x `,@2k$iOHz )U )6G0õ'Vm#|? 7/-ST.Ly! &Y!f>!,9ڕ?Šƛ(ߍ0TH5A4ap G1,w_8yh'nE,`TuIQ|0d0|Pgǀ' 1R)E HH UP &> " yNF `!$RHE*|n!!!!!Ogm!Z \UA & Gʨ$ht"J+9m>X k 1[LSO@( +P"u&$FJ[`@YL,m#  Y`1r9YpwLZ>sAk3C,2`$i  @ t)H5">VN^BDAAA1 z AH P tqf/G:tT=/~n A]rY VI !Ei D.˿B ߏ5@$S7av@I1.z9/T\p, r'qsT))MDq j"~H0{$629wf$l @+`3 ,|XK,!G1G`1siCCP.TChCJ} 45uqꖐ3Y-$ X a+y AHd $|zzgaJ Fʪ]BA'd< Hjd9A fHB"` A ɥw(@XSǢϒ+FD Dt]H$B>X( 'XO@ PD@> =C1,>g ^\ @4F%<ҘԬDFbB餰P"0P!pShJr!RƸu]X0! q @ťN?hqR? ,bK<$P `X@aL` "HZh~ŵ8x8aL | D8 \ F/  "D3Fxe$UꨔhNd (: 9it(@v@*GQR_AIeN,ד J"fx$:!R@g K|0CAA_ P` FupBWA R U0H|GHQ% +'Sۄ=G&@?6K;o&ri@ص1_xQ@\Ɵ(7SX#0l} B 0!H,8ARޟBdHYpZa‚(\ػ0 @w(?$ /f6Ux @' C< D8B\5 W,x( z&'  R@0R SQLL3l2LOz CAĥ (dR?4s֡I] EhA„3"w;ŠdqR,b0WJZ(o =i#6exFXB k4 +'D1(n~'5D$X5pGtH& [ Fb@" 918B#P/?O!styW#xcP!gUf{-0ä"$G(DLDt.Z@¯_gȋQJ#HVy D&ށ8i2bάgM' 4zBz]M& $hpe~&GALiD)xR6@} 8 H1r \$IvQm;*zC 9 0TB( @$ dc FC!XEz^:ـNG-kgL23C*M 쎏o7Ԑ\h ׿ YVu!\@`X !O;dIAYCC@U'܋ (Ae4RB42*@1PP84!ļ.Q1Vz82$R  ~%TE! -U@HZFӗu3ZBA6XM,CKR/Bh4AM_0aZBz ƨά9(:MQLVs%hЖFX}芇 t!)dCMyt A *|X7cU?*VU@nV^j(h;taU?‡ٰ! F]0^V8 6!bݤE? )H<(NfH` plB=!"?"" ܀/ILh8v JH05 - ly(BĠ` e(@`*$W`)v mMZ% ŒGSG b@.OhMO f] -*썢 $jl sGh ނ\w=]@4@`|C/ G)AL? >_X3h4C: h %L0( Q713vupTUD3j؂!kb "ǐ(k7S *[XA'5K<289;3)Wα MF.<!KZ*ҳsX $V$*Q*ViD3(2CDrh $BKA5 }<_)^ b+CЁuU!ږFj yc1%n=$U%D;ZD4!4D(eOa@bFEȔ`l& mg^!TUE#3P-~сtAypAJUNuG\? * Z2Qw0S[BPq20l\cZ%b$(B AB%"le GP9 GZd/(J!Iq*KT!^yu9+O5SS.|*;_@шU R&TA 1Zc$!ǜb0 [$Q+W $A(9JB (.*!J8 1DL8,y 4 6Q!2ȎDK􍆔(BBgI q%(X"3M!#Q `Fp@l(4+ B@h`)ԃHE HxA tl%䌡ePDc)JЌ҈H4UAlv0TVrkG[!|I@Yܤ傴iQv=.#TaDDvjMjR1@K* d!J` X(VJo!60%QL*;3d\i'dNM-UBP&*# &TFP_CaC W CU"()?6=1=\ʱFQI2lӝ&Zcϋ;Pч$HsUT~4 !(Py +4Y-?BET, yiP骴FPa3Z%(B}꾑XaJڕkl2V It~^|9$Q!O`H>3@P"AG0(A*j٦ b6A#L5 AՀdT)GTG8j!&aF@2xX@ʤ :B JT)A`ht|T $b@"X,,$|8 **,%HB S( Sa>O _* h%l*??bO1$ : #/t 5_~B C`f/FH-D#2HEX}o?lS0? (jд$b [A# FT^D_@Q:5$CB©J8]𩀬M$MAE xQÒ2G>O< ,d4 $nV;bd4G8',GNJހ@Ë ^@Oo;179v#\)$$ mGa40WPp0Qwq_ Q.\y* %VX`l> \0`#ДN^i|r_,9V?'i@21eTicF#E(wQ Ezғs33 "!UuR#?@@`~@^#l CUAR *=$M(Aj/#Gt%90@D2(JT 8cTZ4 B=˦Ut;Y!x\QW.CVnTkSc Z N@f$؀ 8,H8TPtRcX(! ŐñRdαQ<)/.W)r $/U;B"nDU (2 ,G#%R!! @+:~@0N!G51pQŒ(A" U]c`1O98}@ `yHZ5JAn8 B(V#$2 !vQ @DXDdz@DJ{)S%c)@rp)<+ʵoג Tu tVL:WtT j-1x  "b;0R0Q b(`Ӕ"z  {CEXI),R?|ULBaBF+LxgG"P`8i-(K|ٔUH_o36(}6FX D> ":Rz 'jh@iHǤPR]OEt sy$6bXb *C&5 $2Ux&tQRRrnAhRY!$p\A%AtXqv`c-5(zd,:O J hH?@* &#Aĩ-4q:!c4bJCRrzWtHV!"ԩ!{*($fA̕.RV:@ %A@QJ! dX;01 S|Xpv/З[k/.c`8qINGS,dZ2^yDɧ^j9clr@( $BD`i+B% pr @t4 o4S%beykx_q e. CG\0 D@8Pm z $  p&/[)1(H @QX/GHKD: C.-TRD! &D2(9Qa4#$4R`lLBM]$"B/ׯh!ICR.lĵ8^Uz9pqɔM Q"2,ZHʢg-ZlF^ ::nNYWI7}o`X!iZtP8.t! EP<@٠DAC(T UIH?A-Zb4<ʡCa&)vH˽nPM=Cnl-r9v0><ApD@E 0$@DRVegh X CNXDxn)f#"R .\$*axD 89ژ o>*UhYv$ 3Ì`]U0$ GNi*,R⃐W)JXPV H} :ꪔקŦ!]&h!:bB#STo7‰ n bk˚HT$3D T pQbTe GHţDL`D "!DaűL Kh`) @M4IQR HE,$PzH $q@ R 2(fáT (FhN Zu箜!r/ 6z<]hzRs ,̆DFOX`lg`2o(HC QkXkH6PdT@LB^ LGU%3K+N ^lS0U0]h(=q6@h!PѤ,(QTB$Ic@E -(@46ȝ .@ @68">a! @tX"gԛH bEA*P2IEADL+83$i @s24P8!XFfu_O]zu:zJrjP4V<<ބt_.$OG 5WX*4\WTU`h1Zf”5jCٴ3CHRyj܇u P/iDf˭qͫz Pw1eM%R/%vKfUt"r|Q h&p!s@!@4C0F!LL١爃l̼hlB!# ☂ D|'A>@o  B!X/j@5%FJ"S;%"4gdb`z)A`{),xEg`MBдV.@BhUQ,Hi@4q#5en@B/  @A?>hx-D단ҏ'FUA!K0r$'RT#aWW؇d D!I@oHt̂G!pK8A-b"MDGzEʿ04Sz&(L=@JVq R%^bH'hSV h (T2$@6 !Dh\*Q %aR4R0B\@JfEV!"qhĂqNх ui/@EŊ$4ՏTh{ge,dH.Gx#1R)R,G5 Iy+E5s(kb9։stw=l%K5 ի[@G6l:(h qA@FJBzQ1"pHLrCFLD:r% aHkLe$W>`6SBxGxY_R\& `)`@'QKMcAZF[y&]ɻ7)i SBjV(v-+XK[ֶJՁȯ1( fA@Pjj : >R*쿢" R5Ȼ:8B|A+x:#gQ!_˶Q(]QU/ԋ$'ΓPpj%kݣn i%h ŢZ|8 z=F[ MEEg-B9GpX@QK|kXK?i-H*4 H( HE   JBj[@4,"EXȭfQ"B4Tu7!|Th"$ F'.:~ RvPl W?}U':.ԟG˯CgѸ2uxpiٰ)@Q- pb71P! ء=c0(wGpǟ ? !"#IX)Й-5vH6.Nxk Q6bRR1x1ꕉ~EuB@C C4 WAY{_$S4` (Ռ: Wzބ [BV)gdaZc2K[ ōAk5pejҥT$hF'ձc%ȹyd%P]*!ꔨ{DžQ-P0M2 I(3r(0Wp61-y9ʻ]pE/{> aD_f.=0i=7i˓k=')~&襡v]"HJ B^iR+B9DBH'(mQvdB(JiLst)s47`,yp%1EYQE=V#5.D`(ʢ\V^K AХX9DV=^A `B<hf;{FA7 d# !bfkX!bQӰY"A$(‚X!L4j*V4@P!HA$IPb $BAdiĊw.SCXhI %h!YQc0(Qd1嫑!nÆFƄƣ@i|j$*e$F$ QceMPO$V@h~($~;xavĐ/fBGQ"g3C؛& H<C8N 8 ,@ @8Ro` 8үcHWͤ<0sV|f(4.&0h@58`IA G!u0= E (2 Aai :PZ~]5߈5^`qgZT-p5Y1Rח-SFKN/}9 >)zr `=ӁM0fw t B&!@!P`o1mPaW bq* , %LD"%lK`,ߜ@" Z@ ( %J"UsUDPoV1*™SHQ_A&ϥHc f P~8dvs1_kOislAif `N J@T҅%銟 )2n&/HRz$Șcm"z44hbd .* b*K r!Sg $#$uKʲ\Ir K⑎5ƛ`F1'^q8,(D%A`iI ST Py -@RZ/W&3 RH%@LT!M:QZ:$&(bB A@5q$I7UͼDYckQK =7 "B<D$k+"+W5ﰿW#raC?S1,4(%rg BSB;lC@e^i>&yn`23@vA\Zgr QV7@@?Br-YJ 2 } (NU@ h]6]>@0H:-MFLe- GJ@^~F@A 8d$=&N-?JLD!D`/@hqvR@8?*`5}jcH($v 5SQ E*>H@vAbp'| aABpnA%B(-j (%!@YWB P@Pm*I@["Z`}L ''l@4P|EIvRPp#DIg95R4 0(.U==E8J?P~9 4Kǥ]3 a!$:śzJ_$nC ӰB rd=J`7  FADA`aF#BZ#,kt*Ki|@k.qFh% CZ$upi\m4 bAG}F$t @6L5|!-ڿ#5撃w^I}jR!.TWdrna8K)*6X/ ĢGDXTb#d@B NXS q"zBaQ8zɤ(@)Hyā2!036 d+A@]9!H":cV݃U]s4+ 1 ǐ-8Ât@Ll)o?!QNL]cW q0)q4yyr n4%N*俯o@Mm =4;ZlQK-k[Y fZGhqb0C@$ 2(ș> /t0 K 0`I*`gKiTE t0y8BE9*8CL4:IXH@Ҍ  " zH3Jh}ر8sTFJ_* m[YHAHAeAD!HN@Щ h̀ W:+F)H`;UG221@JR1JKkm7Pf|.t́5 |M Жztp9@h&4(F}F(V@SA4N.&4SRIƃ$GB tH!A%B4,JRmX@V,X*0:@4f T BBzQ -@d@UAdn"BR@ZD6LQ@DjD*DJ@X= O"CcI2`5P\AOAy35P &-(J:@ JC*`$xP'Z7?PA@͟S@PYAD(˽6@;D6(OA Hjȁ @$@LZ 9HH;XFg y!2 L FH0Kv0)/ .(15T5G X{0?60 A;,bA .G| j'@ &j ©:@ (6}OhH @ q *K]Hӽd2_H#XU$whۑr 6 W@qVtX0G$DEAJ;bZD(B JF0  Tp %k݄W I2FnQ\AG D4k=!d|CuC#Aq8AkI(;9$&Ld،Nu#Rb~HYW"+&@W3D$$A.4 V" l1 q;jq V&39#fF$+{T8Ŋ R1/)yÊBT"TR8; W=rZ2GXb(5kWaiDVF$*;ƊƊV.*p!GPp&>¡(@ҘHbG(.o4(0"}cF!Р;L|),H! NKxd CyS@\ǠJgP CA$.-t"߯$e6 be#a*2IZnKfTDqȦxjÆ^-Y.% )IhGD"X*8G bXE!*btwVMc̱|X.$av" ;Ic^[䱚2: U%d J$cAi,Y*UX#n?-ң8E(QM7:_ؚ*Ğc4\qt̕XZ8\#F 3(Ni-ax Q+FPEֆ1t4N/K &vc? 2Q\쉄2@T!djFH p yvA`"S+ȆR}JNzBH0@ h䂃A vfb4x~Fq 2z4U '0!ȡ.%ƒ+ABժ@\h# ,?{˓7%g)HKf#H1,#mׅ4FC!Y- f߆I&"eC1@@a 1ɐ!baC5X3h}xFd# scp\AR#@ zUO w]܄j?\4v'9A2&/ѢE& f9]r#ʻ m $rZ5"m (a(b dPx<#Y:y#IU*c ") Q4k hr44 QH,ye4\/ @LV`(,Q M!\BdJPPAխKr 8w@HRCHc% Ak1ubpa`Nc5Ueu;JgV&hΚBHt$B)PMqG*00QJ(H1(@iDAB)K򎘬V(2WKraZCiU4B+*Ie br%$l3 2D) .v] lU h e4k4Y@0,A厂_@HSJP5̾]ӤE`B "UJ1kM  jhREDXTQ1BcZ$PBϐk9czR4ϐSjYXH,I!2#S88DF K0%A+BFJ\y`$CbA &P@xT-/]BI%5 #4#TH,ADDTє.jo٢P&J`(qYp6L"t|}aPdt#J  ERU"uqRc;\Pŋ1-^tcJP*4Pfj F9բQC(ҖV0Frg^~GhTBH ;GWhE 1` ](I (] o}DۄĢ$Wz>RD7#X8"O9hf7܇7R$bQ _ (8`()xP F Py(!1@hZB+X  )]""Sv+A(^?׮"y\$yy $|#&""B1mtݖB ji.1kJ.H'Lϛ0D@8#lA UB)qT@x @!PРGnXd:1?(q]S8Caok Z+jc!b@rE@e&-R*M :H4&v0DH@7!\n tPjtE#XHŪ:ӻ;v|wrDtj|6烋5ԫreDNS@lL褪  E? PЫRh,1@M)2B@4Ji %&FQlv)Q M6x ֘o'<#ջ搢:\%+E6%-QD~g r;Tb9ʫaAqO#1*Un%;K"U& 2P4^nXɁQ`  E & i6E:+/,tt:: BE7/HxgpBsjyqYܘL;mVÔCL(@91G@?KVmntt  m 5S3SP`Kju Ÿ@ H J}h* GHC/.F 4{(,IHKɩa^C^֕ϖ+G+ B W_B 1F(ٝbyW D c=]M0a9"+N N,EFY9iHR?g 2| *ФUu#'`r`<D<@5BAp/@b\[ d7usxt-nPsh`6ߧ]>A􅨜 H" 2b""Ł2e$Ġm-UK)1DQR3a5-jDHWngZnj!V#p#D)C/:_VҦeǓq1* (B28C AdtH^UPeRq+LAtd) FS-XZ<9.4Z'0Mӫ 0 Ab(*S jƎ@EaU$@ ꔡRoS`t"PJ2@(: CSIHvE 1A,Kv5 -Av-U\ *hUuu< q%(AC(-CСar1BgC1A(>@ACEqӒa qrAJͧ]Z8Sġ(`:t  @ hĜLAp!uZ$_0HPpd(%/jR@sqS1$D+HvFh1MMV(@8\QnƊW9QG:?X0  @ D>3G308A䴯E|P((%AR朣x&7 9rqST%G]*K$;zQ$ nA"EQR, QP6@kAq'py"!ŽA! ]:&l,.@CJzT<&DJ(P@(t%!!p~% 4B~H5C(a@VS[ _ BAIUF |s`eNY(,AYܢ˜NTR? lC+1R  ,BΕb! ej[ZՂHB({MC^ hv.VeAT'ٓts]S3KDfjX  ( rׯ_UI"D կ ,xoP{lqMd7|i@rgI"܎~׫*wkB:1hXij3: ?<UTœ @J-(A LZ&U!m-5+hwZCB1f w|/H\b;H. )Pp qCI%#Jc!ZR%E*tB_8p(ICLda@6KR4bX2JB:P+MV:HVJ` $@BsHZ05W7R% GVxis8!,G$$]=.1"`>I  i,i,AXKF ԉI``j@h4AHYbaVaJ<̑F@$_4@qopq4+IΨN{qBĂ 05pM7LW3~FsF(HľqXQ#ԴC9%qꊬaňl!gJBVKT1F}LqР x>:!#_XZH!_5@#?7@̓ [lexޠ]@Bh(e-/U8ԌORI( (Z:"7UbAZ@ 5@i]q#+ !nk9NCoCU0A`DŽEs+&D*:Ox31tVWB (WHPXhQY+C.pHK#߀,15_k:,%~_ 2N% VqBlT[r jB\ ZT!POK-mAWxHe"!Py EdơG4 L\R@ ?6P<h/LFMT r $=]vmʿӂ`<6O,A$A X@b4B%|S3D; g86 E PIj J>#CWI+ 1S@.a(,?d>U~OѼk40 (07)XH!*^@z&L!K7(^PfꁠR[8T)cD+3,$Q)!ֿȐK*:EHA!C*Q* nsbLr*AT&_ 2@nNrbBK%0_̫zz",=-*sq3<2S™"ÁӨiWk2i >oPmG ;C ?{ P`PFל, 5.M\ȝI-؋E[ϊ 5Oa  ʣ,\PÄ(H]B  _$@FBvF,qmH ,w@N(B1PI]Pvv!} :A$D݁(@ J`q(- H X J@q*2JUS%LT xdg!B AA I!: !^H\9wP˒-?1H;GѣbG6"/y !u(x(\W K_pqBwgR@jewAƔ,N,%U;@fѐ(EE(a`F\ hfD(OC/a}~hy¥K*3:2bQ L8CՒKGi+ G B]/hg")N)!h+[HdAaV- LH AĖ |1B:_rU[p-(xdZ`d~Rd|AHJ,cO(4 _i<K2{|&!KG_BsЩRKP,Hur bLA pд0Y-$ =@=pPQ\jZX2? 9 1 R'O@QJx2%7[uJAftqDE5'PL%kU"{w N\(hgvXjhBe$4~<0!o rQ OQYn $zHpRd $yr)% B J:B>T399gPCVЂ-  K|K`Lh@P0VY9k# If@ @R+ r^HfW\),NPv+ "c F;F|tɜP. 53šasT$dE$bk`Cr!PA aJ|%KVzT9+#E+A]h6U)p8b;H;lHNB+Ph dbgeⴄ]|F!}81dA0> /B贚9ljPay@-ez$ IFZҢzd[ 3sT$ʷdU,QM]XJEV<OH,"L^i@5V$8<4TdR(( Mq^H(JDA(y 7hA@A UJ Pb  PH Ti(*2$[UV !_.+D/h+4Q5.w ='_Zr/<"#gF<\iUs1+HM9Acя==lñ(MVPgjV)p}bs|@>  (k[KGy'E&J)d`[I-PgEIxJd,JCG/kkߝME*3U5 }/ OP^V((6L4!@r:THaEPhm 4cBZEe0ĭ(=PCA@:_MA0h5ttւ+RQ+ڵTpGxT|N C DACAxP6~*ј"|XpEx8R'!c9Ad"wDڰooojʆI#h@a)zy" ("dG$y^#ULzjJ2oB 3#M 0ބQ. AA;JHf!zag*TM!grHHT>zN$B8A*荬 "!TPE%$4}(@#Nl +K}JDɹ]_ 09O °"`Dr V{":W†do )>zDO@v]= Z]i", UN)hqY"!/bbM1LQ܁-1 "2&R"05BA^(\R Bݿ{e7 v(fRd)>$ WzHM+fR"0,5)gEY`DIEOX㲌< 80R zN>q%q i,?G c_ e7e_Q\xU3D";׮P .t)!STsrD%Bc(aiAn$% rBP p"1aI:5/)XƣP,U]j,JnӤYQ}/R H9F<!,"\1 ҍkh 0*< khx`S1DM jП/< "!o Q3$ Ogg#H- G 8WL JJD&Է򎽂gJ 2RWQX``)G"b+m춈E &48@d`L:GQLmj[\~0YǑm@p)J"wئ̺ǐ1ȄbJ:yjgPPVգEwI-(J}4+ʝNLRHD%)E/s  *ϳj5*d] hDd1, %w".pW $Jj0 @i тF" ƯҚ)'dy Ў?LT!~:$hJB4bЎ@j*sadV0*DR刅Hb`t^}X'@gExwwt45w*@I52T0#.(Ѧ` GJ="r-.&EC~FjJ@ 1ZP9bRC#R0͋HWDӒbbƚ:4)V QQZ(]t)5i7!Tbxtlx T.jrPǓ[, (g&[$2PҌхDsdhhU?ɐ8*q>Fux]x% \##p.MMO Q*܇deA"Sn)\Y̼26%Ghf =\щCO+(#̐NÙQ)>iV(Un|A6RMbhn>[^*,!&bW4 1^8#za1B 3`pV-* `\s}B9dfL#1xZ ga !'(O"46"m|/@:JAA7Jd'b!^Z@0R$@Xg  -YY ~ZEiV<4 5 'UZH!Bi*y0kkCʇXe5wHȌf.,|+ơ+|-2P̋&%H"Kk2pfkp 17wZ @` ):D% XRDְ(JM)Lf38fxgN8+JD%(ybDc¶BҪjMP ),$e0S`%А&m-7$<{jz9-bY-YR0is7˘+ h50YZ?Y"T-~ _:_7#fb  IxG"K(' !`e(E'JFOv Nf}CE $PKQPjzщa $ $bD8qkG?(@@MYx&`c0 ߨ9wC'yIp֠+K L? F4 BY Y $_2H rp?‚zC@#8@@D @9N” '`c@P -XAd$vUAj~F$!nw.r, Hw:L#_Yf!;f!(h$$ QphPe)"4V !&}ɂJ.rZI0'j*JR m+G!֊ R(\>QLiE܀HI.  L 5bq Q*̌~))$S ~h= _&@(wdX0T1H R Y@cD@M'+J @]@TM:P`tPaH2DIeQNPЊWʱ^<Q`S[JWPX#j$-~ q&D(a$q li0 b #ǰ EkVP:zHaGP 1P{YlwhEW4 = AܐJ@CE_Lb q M4 r`MSJ7,@ C4P 44k GRX,1^  b H$% TŌݫ6~'嬒X U,'UJp> EB4#acc$Pm PA*ІMj!BH[\BZ#hz mD%CE rSs Hge0+H~b=_ޑkqY TU;<`_zD9$QAOJX"NPyAp*DG͈[F+`D/Mz1m}fAD p[KU _%1EKgKL$ytJbhZcO) ;HǠc~'.YI;B0ΎVp*+ZtɪqDEtѢ;@c @]HZ+,jPP7L("PhG&;$,tz` !Q:IvxIy@j09U R R h%A R Ph BFH6 3B4C֎,6 Qj(j3IumkF\O*Lb.B>*wuHYMJU?i )Ef$2L$j1 dcH\ $KxYi9 HɦfS ?ՠh)Ҕ;+  ӫSBDLQ>DO" \qH 7D Ăj]9wvBh}B`B.F>E FWț $)JdQ ?ԥ@<8T7WԿ'Z݉̚Jdk%2IjL"H۬ES@y:@`(yEJH_S0P*KP 8t" -+Y\AOAQY'GqZl6_[P,[,zm !Rf `@ r ʦy@,HXE"$ &ӁŔ$. ddY J$GƠ b=l |  ,kXFS0̌3cTjc;1W#F%hH"C.(q!00Ae40ILJ$XKJq#L):HOUβ- Pa&!z8jcHbHΘ Odsg㌔Tw&,(IOw`4KreH5 zi:JGF(2HV QZu? Bp@ʡ ]0A&~ )&;G/T1 :P(Lf{&L2s¥ҏ ,&uEtB|jѦHi1N5P1$5gh3##$}=@MR]x]V PCKxGP![nvh/,FD"]g{:!G 2PKby !CJ 41Y0!T *1`+*g$` ,<$D?wo<(Q@ G 0dm2i b0c uڠ'Ggh 3U F  @4ED1Xiԯ I,4Y͐E_44ZI?А*,1 R,XDҥnl<:lW <( !d$P'4Ag~eZ^ʣ[,i1$Ua%B5ADo:O< &xV.N9HA]N`l6 ~`jnx_ n=[S/hTR`&j))RP% X/~(q6_B@ hbzu*$ Hb ]XL"3@Abή*|fؓ@.Q;T@ϰ `!_`p64Q^tjd (LP0'l"SkG%{ U @?Y`H ( ,0  APe }~ d,J* q8k֊b&-24Ap`q)i@6qvJ2\SA BzYQ "B#ajCtajCtBԆ RD-Hm!!*@wA_B:_nL<-Ps,t~KVY:THQ@4@nj鳠~>? ʀ#4Bi> c]? vR?ҝH'tˤvC1Vs2c?G%e, r\ÀI,D@@aP`U hAZ3B2Jv 7#!_<0JYox`ࠠ ,dC/^"\^ ,!nC0(AƎ[g`$ %@hHOr19 AO~F@8`Ü,Q ^`Ţh )}8J $ QiQ#A_E~ Q$ P%GC %! _zH )j} 4\-7|j)_O31~]4 ?ӳE(4~NwMGlKcDY NaVuߧhHLEs`(Dt JQ/.4kӅ$A~c>_,$kP!Qr 1ZzF,oG`6w @ Hd H$^1 *=!D0E'HDrICw"n*c[qB?oV K/$P[JH/݌a=ʀ傅0`#s $EK  Be?VۀP,Pc0F~C0 R"(x#Cn"&b%$T %=?2$($[Pb I XhP>8+0=!!C J= }em+ +ϰwG"W@%RkeF˘΅ :bӄPSix)%GװE`p(q:C@rl?@/{pAB]($ٌ:.HP,3dxHه`Fi`%FqBI05p8r,HGDpZ3+#ѠS" jNG_L+O*1 7䣋-\("=`& ^ ]p0^% t!3v@e/ij!d@QSJ!Za0ڌA54`Mo 6F#I.K  L*.HJTONL ^6@r? FV4 P!QPGD}|.4_pz~B(BJ(E3|W'g2?0 G8_B쓜4B?|@:!' 3ViH e"Yv%DUHkvG^H+@( k_f"*A<P&,a!An &xjAk" Jgv$BC֩&ݣ֑2Ȳ 9<, 9oHQ/bhLFrrp{pW;F O@ 6MH98w ?' Wm!Bt0? dA*^\*q-Mq#7pP}!LUfbim?1%#T_i<R Ѱ4 P֐@ @dSk(,8%HȢ@zѡF.,$aK yB@PUt4RF#`jT2 +` #)P(& !^yP|Hx BRz&}ӧU$Hրh01M6Z/ZGꀖg6q48Bk?E}D5S @E)26B|1Zމ:~T)%JH=/A^:Uj԰OzY"?}p:{ "tr~3A #t1X"zQVCH<S<- YD0L~uXrui EbN/jHmOI0((`$ H PmA O[AX, i53/E@,FDY0O)ɍ K.Q!B !!JaS)߂b lAFԔ@ /f A0$K|fEbҟ, I {'A A rvF g@ HUǑMH т ˍw8`vE^FȐ1/i(:j 18`$LQՅPQ+(EbaN&S(GXE=ɍh\vEY s<|@}4XUyHGCnyT%q$w4I@A24QĦ6TZ t %ڀ- ;eurh=rP)ɠa I JJ!BAh"?͂t|BbYVhtR4Jd!X|- &Mm@ eQ !X-B<i*>A(?!K%O dԼZ@d:߇]sx@a ᱉E3 | c@soS$Ul1Wa(6a @dx)6*I<g!'Za4o VJW=Fk}Xl($ADJN#`ELaotJY7@1lHDp y3z e(k_'gʇaY&(\(+LkQ!Ƴ0J(BD 00Z!N TywLubW-\u\9[Me(Y1TF֦.V0LN9BykO(ATH#AjoN) v $ Od`_uFQJ:u qHOYyQi肝^]`S2TbGR@Tt޵8xC,D8JDF>HQ'?i0^8O.(!Bj0էrg)W#t9P30LY>HMQM=EO6z$4P%WY(i!1k.0h6Lr$Ve3W𡮰c.1jm$bɀl8p }!rgFQ`$agQeM5K}#« B е+ ŏ!Uu,LBN`в P"h"A !8n!JZ mv(䡑̹fF砶x7iHW$!F#lhLkH[Z%DBHBWGXV?e,Eb> b KNLEǕ,;I#Q@J++fs+ΌƦ@-ЎNV%%:$LㅊPv~j1T*bU\Tf))qKa=@ /o(p#( qcb@701]7)c\8@RB-<! _ P ¡yZ>|= xS3BPfi0h PH`Pb-` $FxHT`j42!xd^:/ *:@TTXt]Nq K*ȡ(Q$2,FPX@Ih @V L!E@;F P&@6< V<:x3-@P\"Aˀjɝ@"qd,S4B@kTmP->SEiʯk^R 5$"#kSdB4팸"CzAŪQ-x*%9P( lAH d] ܠE/7E ~.%; T!@rBd\iE)^B )A e0mV^NJiU? )~ `4HbA$c)H3kw P+S@u1w h$@ PDl7VxErBԏ/hnA@ { ߒ4}/ ]xOq!Di@8B %  D@1K($1^AJgg)ߠ [ A@[ `Ly/ #D xt+ӣ1&+Xb(;Av+E+U{0(pu`(`<+&Br fph$8:Fhr4p3@DЀPܦڎZAJ=Fhp#z ЧKl3?RK2(x&"& K9h6NMPhE $}P(JRIq*f:(PH1D{rP1J +S" PZ ^kNB E# TaƫB(e1LD?D1We|ZI@\ᒡꑟBܠ *ˌH`(C򊉂S@bÕh[(M, 5|u҂=1f_1wR+@/uh O9(,&z3;^"hY)QF#G|+!k p@DUe2c ANRQ MK Ii1Q I0&WJg"&գT  'V)*,!A=?4@-܈`_Ԫ!yȂufAoX$l-J,+c>w&zQK@(tCb!OIGQ( `2 sHSt' `sׄ`aG&Ң~GUӚl?Nk0MXjM24)G Heˬ wVdPNGш\.Yc\r:LF i,'~ j9ƳEe%li($ p( qj E'Ql2R\Ik{ejCJNjY$?P|w!? 4Ru6>C)GnFh"(L䑥DT0s8 }YFI)/.3S3b" X (1#E ,BA1p& =c;eN Ú8˖|Q|0p}/N1UtCw{ .B{&b56Q{0y 5 `A%5ΐ%)DHA#r2>۠ DkUA{-h.ցX{ׇ &r U D :BcA(fx.Ri+M]`ygXuI5-s?H9D"b%YȠ  K9@ji(AM%2,W#֜4Ult|#?E<9?E]>S@+By-l Bk_RD+zcB> r8}x3oIH]<=CKh pbX<%*BLt1KCCm>=HDo'~\M$ P ޮKwsڰSH+ &M(ZY tK^YvDхR) /"]( wC 6ؖ9۵;dʆvs3 2"!bDŽ2@SaBt J$IR:Dڱpe"£!!x)G4sf B+"Tgd2+H RM?Ő(B?`hp+" 8~1"g<ɠand3҅Thx8y1d>&~ba 0G̖ <(L#Bt[y0W[|^J̟ZC\Y#INO"PV^x&"!,$=i?3-s>CCqTxRI'qq**Q"hP`ŤsbH o^FaLS-~b d>Oz!X )$[T#%bzf2Y4& }̹4>&EKDOtCYCJ_(caL %9H жW9x ; 'lO'gǁQ(& kr}aI0j5eB Q &2С $E{PuU,`up[\RV!E!MdoZ"=2Q auJv´GE13ȣ [?̵Rz3ȤNizE=٭d*~NHKuWW Fb+4 I22BC: BS0:-OL9\!-4`bj)e#Kke]HIc$]|*+u,l7%J%1%pOSĬ%#ۼj[BzbZnJT0@  HrF! scȚbXJ\ yX}Vej8Yd*? ]esn.&wePTSp;}!n[pAkkQ&*_"A; ]B!,j3$DcI(RolS@4N1C.FIP {P z0 hSK3CE!Cơ?:?ai5<@ XnɊ !k4 *rFRJ @4Qū:¡RJ(꠲y%ED$dǘiJQΰ8i*2 IhPxQJ$ +J8(QGDFA 9T5 IQE'!Z)H,%;@P4;谦`kBr<)r%AQu1 ?la҂"!aIJGZt֓C^gf.`ٜ˝ VYx?-$%dT$?iDb8 =3 ȃ!à K% \0 tw11b!r|(:CRd'$C'} ɰQVNnY$pP2qȷ*$D]Io( E]`Swh_՘huaO:v`Är B} [ !!jY٧;Qᔚb3E-*_D܉AEPt@yE3 `$vJVeQH_U⶛?»R%]wh %/.,P1I[ %R%Q*r5ВZ瞿_>)u[DԱyvE"{0DG8#D!b?,fR ֙?\vsu͜v0ʏ$D "MY#P/-IE8VAS2v%*3)S!5.G1FZ)!Z{OFy' IQ0'f՚%@0B F+*a 25#(ZJ-J24H$͂)@ BiFqe&J{}0,tׅ0MhP  )hJycPojbUň Fm1l};%+K"ZfcA('hiEIf,"--a$!OQCBn'H[=u"ŲE)Yd{4Io@{o| 26 Z旄fS$Z ˢUM24ތW`.Kq)68i2 `, PB  A,h?usXnU8C$wCiƎPyIVӨR)|pG[敓FO{Lc#%Kq&%A:,DZ!"/c( nm SW|pzisjT*jQ7f)AcYA!踖U;Ul\>2JQ`AzZO(yp>>;1+'k7$Hs< -O\ :$㕮t{㌼QVIn L EJ5l( BD, XK1#TXBQBSUHQga,ո f|&8:ejԊ ÙJ8Q!@2@x[E"R@m$JBѥUgPKQ$`v*Χ#"TU0`AMj\9D!VsbxΊK, K֌ *0a EZtQ⃋p;ST J3ȏ!PX`%ҩ,` ?6?9,&X$B?c1h#bPG=O!iXE$ =ƿAJܞ8.S)(QԎ0x(d2#}<-jŪTMbp'c“! 0XԼ:P餠!ap c./&#'V/D ^mzb!\)e/oN)RC8tpȂ8S ɉ@o'(L`]oE`*Rc@HZ+p5J)bH$H %E]|d@ؘ%cz a օ"x)da^}Dw3ȋd!sN&n͙`m*殷2pW_DI8 Y6癈pxJ,M/3qKN'a~ǫ2!6 (`9# 6_!">r-‹Q Zڅ"35ɤX&1{g))̣"}6)o> =gP-g i#` xeI5 zG* )QqOKGC3eɗedڐC $$lj  5.:(-==)s`s棡 (|ײrp +rgQ;IR[ffF(f?j"yMryhּtM;.L{͑Hc =*Q$RP9|I, b\v+s6 =,;Fw{NCf.*#1m#s&ֹIM& ՚ 0) #CJɡ<J*R5:@b!6z `Y.,4l)D1E,җP. h U X5fP+E!JBU%D!f$D!8ATW!jC$ fp!F<^!UAf<b)*T/iQhc'B_FWE|%{KrzPd+^u֎H;Lֆ"EZF#aXf_]tLU1h! ^":N/WsrFLHbLVtP0:* tTCBQs2ϊBƏ_VJ$!UJT& +> ZdڒDϘp>ZR q 5!mLbʨ, ??cELbJ ,4&WB P:eL9Hf`a1'Tf ـ" q,R8ȕKԓ$ %Hg$ZLS6mR'2JN$b SuA#iPx3R!C!;XBAV= Vz ٠PCf`$Ha*5SG Kp (} e|>@q!r<8 8ONe!5t,FU$RS$MO+5EJ !Q$8$@B2HD ) H0{8[cCRHPe5c,y@B B:Mi 3ծұ/Ys xZp9qG2u5Yv-_`E/v%` @ RQDY8 7&ʻ Pj<J*IYzJT=* H*`:ƠzHya*`UEiuLAeq9' *dtxA# z9Xxe|[,^4\Ӣ+TG @2v!)0vu3F5[ 3 1"cWR)C%D1Q^"b,NDB(̀!$étjA CeΆdH3Ll 9##LEbrC)mp< TxEp%n 60*(%xnPF^e!N:HSSU"su2w 6~D{\JA .b/+#cCsA6c[ȅl M2o;) 4%iaCh"3%l;K hq`|b$88BuOlC xaèt=*! O*kC$!P &(!$ 1u' <[[V IsZIηAFs @zj $cFJ*]J Y6e.]^K <@0M~AJR+k ֑RDZaVB-Z;-zBNĚqi3Jx?($Bv^<#hRȑCVKA+` BKȖ "B/b4xvqhMUV )B]@*Lҁ ЉHB"4dEy v @%HH%]8=Axj RqU ^_G^@(o\#QHHbRZ^JEiłU0%B1q' AC DR0 HAY_"|#x$5u!f<fXlAgXb D~^򪸓(0¿N+tme›.o d J_I|<So`hQ\K|l0@QH !*WJ@ I@w`!puuu>N" H;`DLr2b P:xifaIaFqZH!IW E  Q䅖N>""Jd5@| :*/> [%g` h|e26H%H" ! |dB(`GB:_HSғAc,hiha[0Aޥ3 j{IKx@G "Xу` ؼd"Ù%/Fޘ+Pyv@ `)G(,ʄ҂Wu3y v?R>:4/:sM&E/G$@Q89*򤯊yA:BR)iPB<w>`A,J $0<&HB#A;@@2@@C/1Y'IS (y`%AFUIb`L.:|;8Hh)6i Q%UB窉R)8k.|t֛P`pbDluCk] ,Pq% !Nmѡytz @[-#Xhb~T 9T <Ձ'Ѣji0UB EҎ= Jz "`؂DށűD,[i@X!yŃ/.,(AC(jIAׇ`ԣBD,Hij&ZUU/XLO 9/p ɉaPkL!3R91 v;1\XE,\,X;Ò@pƊ' 9Ble5QA F1^>r!`Ụ FcI@BXkS!BE"QDr3Ɯ ӥ0YW !΢:3d9 2!%2+͇JU*@.DH!%2Ū#"|/@$  YW:vǙxQ$-8d඄Z[V KA5Bѐ4F0KSya1g%{yYO^xOf 9!vWIq'#ʂI .*,HP$B#AI{{aiamDC4կ_ 2Rx.$~8W! T]#Rg@I,!W bK@hFIE*d(AA2+7qdP3uĴ-qi N|&~:I"ZkH΀?u0PБr7 0Lt#@t`"#%!*$4zJ:j,Xuf)ñ !5f1j#IJ$h`Y$HuS R%@ɴ!Ԇ; `f/` 6 DUC02mL%X'i dT!bdL3ꎚGiADR*.MI T `ZؖIq@ {LHe[E "Jj(鎄e?Ɋopt 4ED`c@<إ@qiwʛq bHK0?T䦖LC`Ve:!H^^ u=1aI(QK2-w0wPH $‰`)R<W42@Du8YtGṑKE PpRŒ*sZCWF)}}&N`R? OUNOUv@H]$#-Rw mnw_L0rPn`quÜ?DF N$ C9(er;b4aݩˀ",H$C _b вF HB? H1Qe>1oOT/l  a0 Jp[\Z): l`+F<`)xJ<@2~`4ETbG`X]xwLВE?},KF3h,4 @ tJPЬJnQr[㒄 TW3"ɜz,Q-xZ aآBH-,h@H>ÔC{xcDW0 Xq$@Ďzr~A| B8Z60x0k`Od@G_΀0v r?ʑ!D#M1@ 8V?U>jG~bpPjDHX҂rt-N>@)=>WP%QE/FgFX 7XQdQG̜# ߋHTJ1 $# pHp·*aւi "DI*?7YYrX+@)D)I<ch#+06?,ӥ.C|DQ(3  U>׷+J)# ɼoW0|/KgN#|Qx)mEJ$nXcg&0 N5נ za5~5>5ßdkyPٲ$ Bp "= MV R5]AS܀e-QXi@MUҕJ(tZ`ii:EFӫNKԀXiKFbkTQ zpDd`@hO 7 >0 mPIa%H?T@zb`/05@, %_$|yBAgыG/81!srqRMPF=ӌa@hV"J-#|CH?+?@YAؠJґ _xᙃE6a-)!BD@e..,%@cާ MB(\ u\boE(x d9U bAƒ 2CJ!҈iD4-XWPIڳBE 2 gBvT>Q""]@B` paŐr!HJ#@[`cL~ADATB0$3![hԑH 1"u0`O=NA* t} J hS Ϩ 3 +xCNPe+E"T;MjT"ؠT|X *0BV(! h y+p= a RHe!:!AńVH +`DhPB*dҧ(MlZ%U䜒髤$cB2&HBH)$ L|U"Ml*lb`h(@Ő,JD)Ϗf,4TAjLHOjH)eň@CCBd (Cx&b`F~MP^AL#J@]%?J?BxI'ա $ -/&h+wLrDf o6eDJ&L? p07́3@ L)5 7ǂ;'a~NxD`!(.ғe骵Wo A@Rt߇`gPbd"4b) ,R ?V]U9 rF^F $@P [f&iVP8n͂(TIG"#B e)q& 8- A24[܀e,.++A51AM_[ۮu@#OlGa.R3M\ a0fV0&@Μ(A&5<sl&t@_)xI 9<,_>M.:: I@&4+C ,xi]4Н  hev!dx|8Qͅ`*02C( ::t>/Ҁ:!T Ȩ. Pi7 Qi0"tL4Q@$b(PQ44/ @ & 8cHAtІLO0O4 ε[`0/Z&R?h! qR$QLKY kPt}r VOc <O"ІXP(!S2Z8|#`HH`3Au5`U7:\""4d;HaX, E!J#|> Py@,r^0C4غPCp&~Pl)Y8zZZAU/ 4XB^ZGh*_(d+<`^$CyB!P& @lACAXnZ] *20Q$C )>E?R%7ҐF"UGJGZP ;/`ODo5&o˿bfDɄüw$_-11c@sЀh̟CC4Q4tDdqk0řH/-J&~dߴGgD?-$F"@15ZFz;J,(*ihkII $  h*hZ.iOP! $M^dd ZA rAJCDP:c? DD4Q$qeb=hf~ B\_5!* Nƕ QFVj#Lq.b*S,keBVjLĠ,~X%r1@J]cA' 5gV00ha X фAUP  @z@PT AUt@gn ė PKbH5Nh\P0/P 1eBmxxŌ!疞K1t**;Ÿf][? q S}w@4\^^^"0 ~G"XY YwM裓  yD%Bk/pl\yPf#$5k2@`N]Q":i)Tq.E~)h)P`2_ h I )ESSDt^BtZm gfFZb A~Ø|AEYP RJS$+ShH$FJ*D6D9X H2%J*T$t5HH",\ԠQGT-PK&s ,.@$"BfHFh %`?vCyCa `9H*i<_/t 쀲m4W~ 4H4i!Bۿ PSLzͽpsb@w K_2bT0֯e Yu@ PrЂ'=ATI `| 5 L%< 1$99$2%[ DLxJК0?"A9Dx@I'ࡀ'E DI K  $C =0_~q耞7 @-EVw` PPheh]oC BB#U4iQxM5mϋ^mH`=@=ba˕.} (QIV*uO%,Aw$𐡈 jA^ } \y^03D(P /+j4x,P\"P_}$AzE$Z@ ?IhicqCFcO3(" DP++oqϙ_g`$3D0f?M`UtK_ 8g0ץ42_}% YQ`R38$ 9eA ʡyA//) ];Т GVZv2EװRZ8RIqV9F 8B;9>3/'Ӈ8ŏ㔄Nf!lӺ*4PNXB4CqXrԨV<u8$A B,Gh`DD (*0d`>:tӆ G)MB  _<:YBk?{> $@% /6b)}uА@h1!I :+naS _T Aŋ(J C~S( QK& ' RA@xHS,9Yѩ.0~IEHOE| , Q2٠HMH)ӿ i(r\g=RAQ-Ezc&kC؅cPWG5QiU3水. dv~ ;.EĘ"jh@@D#j,HIK}QO5(\)Y,3 @Y ?cèfC_ \T_jOM 0P pРƈ@)+F1@*G>Ïڼ< @ hWDXҵ$sP"5~p6:S9ŗ2=U@P0y`Rrt}D&vxfb9. DBl/#X]ȢL* Mj9cM @(:5 B K Q(EV0hBC$)k^Z%"K~*pz]+0JKz׆Oa` %!"~/tM$E+׊ƀ ? v[NL%KTԨ`@n B#,X9xe1ve TńT&F!Ak$}oG0a", iO V AiP̂ _K `ʐi! A1! PBta &$(J-s`E4I'G g BV@PAiN FI) A/-;!)) X),VAD)UϔGQ82 (qdH$ gUaT U\}y@ܑV(HhK 0jy_?"xDa#HF1e+)YJ8P@3@B 0!b0DE ]:b?STS!dSRјSn"LU&+? *Sƅ45+CLFɡs%͘E/Dp2*&଑ #|s)S}^ P0$,<B> c,b]/ z@, A@0f4`Y-hRs G#@ P-Hjl 9BF{%)%e| lDeE&J*(thK,&I,0!J,"PḚ4)F5Tb y&ARXéD j҈f21bŒ(PB (PB$P$EĪUG2r1Պ++ i/+YE byJ9:r"^"J<`a*Ra8j3` #A!#J{dpR,'m.^NKn#T)*JSU/kX kP& Pòfg>4FR5 ([!dXI?1>B%yd#R,B~zb2~C)7cpȲ%ȨW0ufzxLrOS#$BPǍQRyP4K%mxٍ|']WIA%~Z`0S H$sCq(4)!TkDA )"`BW)הtD"Aę`1Myb@E+'U(j3A/!̘!^Z\y%",X PBF(Pc *BCĝkBLP Hc.}F91'&.Ll0sqL9_qE)BRH3^@򀎆J"x)J=6K'NOa(̀B"Hev0lㅒMs  `H0" @e!f 18z%Ad <˽U( @]yA-$@P(PT1XIQ-q,K1ybh*Q%jp EYX$h$RRX- ۓV (#ʉ{VÂ5 !DH[13/PKB3`^H8jb0BU!kFSJqg˥7PJCW^BT(,hZB?OdF7IWca_ IC"`b{ WRQ(T-2`VAi 䤗UD9b89*BU*:/^E"Y %EU\ ra>$$lxNbUo>F"qը.K`a0"U%cG<#V FI O%(hĀ >_K`_W>!4'e&1|d9J1jkH-ڳ̙Q%YFH%y%bJ @$" (!#z:aM ZC$[$^c*N QRk `P #&ȹC)@'!`L?ˆ@8 )~8 )e0@> .H@S&Ypx$CJSr89\6 HJ SFs1j#TVPJƱXBPŋ% r@I&U:k\(²x(C9>8.r4|yr,(Y,Uu{W# S SAE͙m+@&QUa p0 d{d$2gzZjqF>(\+QIQi@$`2-DH")u$L@"RGaK&8]cP$%T  (1Q?. q$T"`Z-ˬCpL-JH ʬAtҠ Vc+Z+p(1+v;A WO'A)DU`frdc5+DQ 0 =A(B18b238)IAm!:mbfr,R&(C¤b'hJ[!C5 IF 2a*RN × 1BwI#$W鏒+FEZ*D^1B5A Ԯd+8HN2qd' 0a %@"$K9^#JX ӎQ6dd B)Hm=e۰CO!t^*uM;L2e0^@`#*?P[+ Ӏ"U 3 0DC11WY\ekmHA HBE990hBzrG dJDqB6eFQ+#?=I_\O(" P`@ XjʊE%]e< I:k+ $(  fpnMD-2$ BR%LSGQHƮQ#UPZX)b_,EKa՚f(GYC"4 U%Qŋ!(PB A@Hh-(Ƥ̡YC*y9 `} 4TξwZa [1Y(CQF< >äiBA HV4!8ۋ0eUS~a("xB```̒8[E mRp`01VZ”T j q P*!T>иE*UP $2*H b ȠQ&XӦ1bGP,A$4)(Xב( \ߧ'Bᦘ)ĺdߧEY֚9l@! ʛ$ba%(X S d! (r= DrNAQZU!@I B- ! FW`J0 %B P(-W>Z[_ MPRiNb 0GR|D6=)rap cDŽ GPR-Dyx-U\V̄(b(%2ΆNĒ+Nl#HJ)8'/|4*J]G*X}D: ܬđ@efe}-_YL B 4(&d0H9LDc(4t4vPfdC K?vxVHm5_LO( L @ >C2 : '@MU Ž6q±LH$R `t($ca%A$RT` B<gPqTL+$hò yjE V.%0c1ϐCAUXŋ(PB % 2@(hIBT#Ɉ j 4`M\hR(T圿1LrVܪR1R[Ovtg B P@@QU\Rt 4Ef pℿ)N IlPq9?j9&Suu"!H ٣f. `9zkd01" O@@ F FQh2M0.)CTy4Xx jB JvF5(84$ ##@A@QL8VLZtwXt.!A iZ鋯"KZ5v J&;TgNb@ABngMZ% Go@`&CT`PlU;karx+A%HRJM@!PPiQ٬AN=Y 5MY~PHȭU3Jr5Yldaf#Nd?vt'g9+̼6)YjP# < 3Qm @E %B g{Xq'dUһx!;y[]lz$*8v Yo nqP`<'N u d܄~k1  8;N :"pѡAΟ"4$L y04 {PxVpB@ ( @MX YA h"婓ℂPxk#,D%"-h ?$ J$6[qƟ" Lc3D{x&6dHO+ #'*T p_8_B E$DGBJ`c^PSR"qÅC$B_^2N x… Da: a@dSLjr%M>ʡ JU) Ań0Yjɖ$PbPz h%j(IG\=CH6c0Aha, D#4"(1V1Ud]pY,K%l'd#HGXBD1bp:E"N$ӑ) Id_|'EQ"80СBPM`]\c8nOct'ܿħAH- 0 a2#f]eBP9-\O ys R4@Qȃ REI2TmRIj8d_@@@ @#]e TRr1BCt!j@g @3("T$I>AcA2H!C:u_¢D+,H/ !*#-*qd FUe+ dtY%dv2pvBLB8` ?+8'}.}[:!P0P 0(P@ A(TT[3ӋCE9^JQFyyUhB'+ !BVaoTpH(8H"9KNK#ALa@$ )UA4谅Ad )CPHh.dyU02P)Q $ =YF-q¥? 'iZ>cmM6c8)ϐXQ+}5%(UE,5(6fŊD FcB5cQFJI!y#Cy;/ B  D d~׷agXM# jZC&H=vM @  )adAj@_Pr #{cH h@惮QRADc o BjEH4$* E*`@PV|Z1b * ) A&@&C.k{? H,pDP6"tiDx ( (JJ840ˆDy.fs2PAR߮ѥoEB(X+?/A'G 0hʠ V HJ'@T!a4(x?l(r VI&Q6i 9 ̋ 8FE 64,Ak ѭE(% M~@ 1x6k0 mAaL7,1"`g G!SZFl u=\` ".MpByC g8?>8ϒrLI0&t]E2 !&`%A)KrgPPk< K%\f" :?LKLo4AV J2I+0) F!" ب AF?e׸e3"G3Ɋ@$/q$D$0^ ?%'= >B9HW!%!kp}C9*5@,F3YFB / ,T@+!X*V!\I4|)j/G(H00@ `# p !JHO Z=$)+1h`n`!$YpdtR~xM- !-r>'`:2P qh,FQ= :j8;0{||gj+ɒX8Auc" `:@= mҗn)4cTZaa00*,A J @7@@x @J Rivsh* G:q2b(Y|x̀` 4G5B(tgFa_J  ,DÙx4<*jC1j&`*rqx}@$j[5  AY??T6~OuJz0 ?D'P#;ٲ -BH ?ڦZ@ &HaI Oz*.1]Tk\x 0ʭtMKa.<ؠ!pXBBE5}F )Q3hx:難: DNA֎ 5KUG 3{1qj?xZ0eEptS2d#drX=) P rF#\aXB. T`nˉ1&$Ę"LI1&$Ĕ/>Q,FoX p0 O@CF] p !#8ar'R$$$XUkWO-HD~ 2e] ("!W zO{ܾ+)Y /@h%(=dА' HLR@h#S| J e/W< %"3j@ H"9U\%zCjo0 y( P(QXvj +N;[6N ALb&i.YȎXf1@Ih$ Bp J!j:f"mTTBEQP @` 2CB)B$"L~X`A&>A|6(P T=?dCKN,p_@RB_xYh 6d2Qh'B] @ Ѥxy/8Hj81V?y T )B0B0 #}ʐl#X8QZ^izgL(B}pHmгUޙB J8A^_ /Wr.@P,DC89Q ؘG nS' ?dZ t#\iָ4 ϭg:&)ACUDM b/اgDx8iHS @A B#Pwy0HG؝@QGȫXѡ9G*#1!z C t*w>`NA{~> 0tT94x/g@ĔޭU ui z׺ 7 r| 8UHh۹X 'k_pp!s.t"ОB*A_#bɄAA.,DidQQf9Q&FBfr8ù;>3,^K\E̯쭁hTA<U`@rV!mNeJZ$ŔE9%=j'u[ ޠxcKhH%~* !p >Yz91= PG@B.GŃkP4c̀l)%``!Z*[.ﮬ$8%C">!zUhR@:[K\8f /,Xb (P(YyrB`&4E$ϋ` dȂlRP~C?\*;RcB A"}oX<&8:=JJ`h!HְOIڤuaSHL|a#"6v@]oϏ:`@@E,bUA*QuDjxIIRB_  `jX@v#Z+$!A!𠰊bJ!.@ ZxRA]%~r@\W!@Tf|`tf+tmW~7MNnNO~Ƨ1Æ 1DQapg )UNSFFyLM`2X![+c0iF] )-]:?5jPmsVy: z^:H%mUSUOKt񲶢@ʕpevޤQKyt@Ax<.UD@J9c1b(5.*POp DQ *( ,Ԉ,If V.P "GOOo)[ P3#'QeN9/'A텄ÿ4qd$35X-0iSAH/,XbPh!!AW )% m'Fr OvO:@TGkqx|/Oÿ,$IH,C:B@!1$h>%Z_%? MNLOM.A }>t@]}X!^t:`ntg23Ƅ`Mޡ-@τf=@`6tA#ߜ2@>WA>W@8$PD@ q\|.> ~~?O;@wGtv/K@n0L0P y^~/? ~ G~_ 8]e ^H CQP@ffw_;7|>`5K a,K%} 6l,Y0adɅ X " QF $a 2! yrbx Aŋ(PBP' $((QJ4Ǡ:Ad22`'O$P((QE*s1X$@@@"<bABӾ_;7|>`5K a,K%} 6l,Y0adɅ X " QF $a 2! yrbx Aŋ(PBP' $((QJ4Ǡ:Ad22`'O$P((QE*s1X$@@@"<bABӾg62}X `kK bY,Y,YI`Z xZ Q0a0LPhSB~#:'MiTE]}Xh`@@@@/,X>@P(((QJTCAXtL@  AABR9ϩ !P +EV!!6H (i!(Yz?(UˌCJfA)JR Pd&܁ [Hmp#x.s0C[Wa@`d4(8H0)G14WkRd9qeEq(1&4~$PldqD$ ^Xb (PBPi %@ "z@!C[AO#aMbH/@L4"H5HC#,R ?) }o/=ZW/@ UU@A|/ꛄ4H$I&Qo 1a.CFS(tJ \YC` (0;/(_Θ9>%=U;u"D "໘@_@- <uZV1LxSj(rBCm.<s<<2[m L 8^ 9At16!-'N-ZuKBM%zb5=OenPJwdn@$, ##)6P1x``%= A6z>> 8]) d%ĈH O Dc1cŀ@/PS A Ch <Zp?WHu2 d@'5@ Q$9Y{F`!BC  ~ Pe? fP|ÃN 7iZ4|ؠ_~s@~~@8 \$jKQXg$@73 *|&"ŸRJve0ɟnY#TXkWZL%4 `EX5Ba:<~(P+{MT_'I/ 5ƔǨl1y@q/| +`@-l7@`30f14)M HRB$(T'& $q#A 2%-^p(rHF F^d(!cq?B0 4 9 9 *T4hAJR)JR%!"blqgz 0xG+vo|pcJ@cHB&O,zM p34ɖLd@* ='hV@ ?Ԅ olIO8xĿmx<[6ۥe0r&2+ޞN@&JQ@"pd'N 82pd  (^> >@BUY* @^Xb (P(t t(֐3*#& A/,X.E-Ѧ݆Gp7 FQa#ddg {?@$H-P@4ܯ>$FX*h >ɉer3kQ͞Y+cn  & @@@/ =HB#WB1cŀ:UQ 1!Lap (g9+9 (7Mk~|||trHR9\EY)< ;M=pPD ,tb"P@kɘŀ @Ac;R K@x6# AE@>qk`)lZ`>Z(&"?@ ,KoPj}IEQ) S@̇6@L`Ro8P:0iJJҘęZh@@=`3 d~ |Ц4)!I HRB ,~$ G A"[NP BtJ d;ZB2(0 [а XH'؀9o6 )\_ $nnocc Pb(1A Pa DD$$J1.UB " -`$1@Af D0FHTABw>@?+ַ,D07ލ@#\!-UyADb9V++)8([`t }:YxXB]a`E<OMnMq(^iiiiPҡCG:)JRTRC@@U`Yo@}FH PWVŸ@bg?dB!ᑦ0QrM;*$r Aa*: d&LhAC0fSE$:PE yRF?^qH õF_'%ٿgř\ 7t xq~"tX Rr'G((e[2H3_3&sXI #$+l009@ASpeGQ@*j$tPV/}hA5P$rbW_@dّE}XrjIP$ϠBŋ(PB AE(@4 ]*ǀX(vh I:Jv c!lT=XaȁN” $CܘWm4`3O4(*P 0 $4Gh"AˆI% BV֣==&j 4ǔ@} x;O  7o|Pxd.mGPXYU9@ "Y'Fhg+Wu3R K$oaHW2)-lV "fFR`: OPGN4ǦUlz)ߴC@3ޖz}@:ehQJU1c1`wQBzjFrs P!N[/l[  cBr>B1%ࢹ8qB(*Vs0.N^Y"<7Q̀@d`Y 0tçN5:/`G(}E)@?C.0~"\#D"Q"F֖iYyU i8C+D""".{OI)He$Tx‹ #j"+)C i i EEXfMy qZR3 aOЦ$)!I HRBP'p'8NOc(1A Pb6l`++aXVW9BS)0) R)JRK@E0a !C|o2ɖLddtYg,L@B>7(l F;f~(PK`qZR3 aOЦ$)!I HRBP'p'8NOc(1A Pb6l`++aXVW9BS)0) R)JRK@E0a !C|o2ɖLddtYg,L@B>7(l F;f~(PK`qZR3 aOЦ$)!I HRBP'p'8NOc(1A Pb6l`++aXVW9BS)0) R)JRK@E0a !C|o2ɖLddtYg,L@B>7(l F;f~(PK`qZR3 aOЦ$)!I HRBP'p'8NOc(1A Pb6l`++aXVW9BS)0) R)JRK@E0a !C|o2ɖLddtYg,L@B>7(l F;f~(PK`qZR3 aOЦ$)!I HRBP'p'8NOc(1A Pb6l`++aXVW9BS)0) R)JRK@E0a !C|o2ɖLddtYg,L@B>7(l F;f~(PK`qZR3 aOЦ$)!I HRBP'p'8NOc(1A Pb6l`++aXVW9BS)0) R)JRK@E0a !C|o2ɖLddtYg,L@B>7(l F;f~(PK`q ZR3 aOЦ$)!I HRBP'p'8NOc(1A Pb6l`++aXVW9BS)0) R)JRK@E0a !C|o2ɖLddtYg,L@B>7(l F;f~(PK`q ZR3 aOЦ$)!I HRBP'p'8NOc(1A Pb6l`++aXVW9BS)0) R)JRK@E0a !C|o2ɖLddtYg,L@B>7(l F;f~(PK`ʪ aY3 aOЦ$)1iLZr`'p'8NOc(1A PbbC>'>^ 0s+ b·:i0)S bOiiiDɮ)JRU*lB<cu@M>'2ɚLd` Űb(VE ),{x O``\`L@B>7(l F;f~(Pi@cG pjU}>t@].A |'8pRKAVf0#0BD`P0>.=1dz7dg 0Z#D$ ϨBIHѢ&H?A΂v4a $ F{ "D|yB+'!р X+-0".\.> q\|y ~~_/QP(((@ߟL(7BĐ*_T) xR@zɐR@7$% ^/?y^~}(  @yO'(р-Ӻu#H"2a"`瞄Ѓ߸ ̈` H &E&̆QP@kffw|M8 `6_w|q :`]# `TqB{' 0XOBh(7p7Pq塌@<Â0 `?a"bȒ>sxp,Čxjk<@`" =f1q`B 0  DD#r\BFƥ1s`R`+A[6  , ӧN:~>(p(1a;0͂g \@'Q/g6хHLXQ6:t+x)$DRZE-"  @$a`CT[" ߛQ+P?vDIZ;``  sa\A$-h'(@@"0@.6 BAB)Vs1c(B:$ZƸyD"=X-Eb!^Xb1T(ѧ7;Zr7Y~.hH~S08r0{u!ґ,JSWP B/'?SOC @c0s7,Vi?}ČcxzРm!V{s$PQCgI ' 8KH˜/eCѠ%IȠ]p(@o^ddQ)FIu +N$! Wر^"z9 ů (,b4a_CɱzQ@gg ^0(;0AL#C$p2!Hz%,dJ"QD%(DJ"IH^!D@|q@@~z<0 hj4&h\A+z]#YT"@Gi(,&(*6z47HY? 5F;} ۚ HAflSAʀ #G%`AO{%`G&aX_ /&yĈHEIP:tr???yϿ! X 6 zh\|^"Li T`X`!Rp,c*~@O858"ѿJ)aq-)I]2?KHPAA@ Vax1$;Hv`)="Wn?mC} k1*[-KV#xvaB$AVZKg,$\}рY _qoAvR ,_Xd٬$A)H[!D)Eo MBAH&=l1{,H}ZGX A/,Xb (P !!JmHX8 &m@tLM}_N! ."@?D t=y*n(aÀ5>>:t>PR"$  %?אy7ըl0!֨~2:E`*Tr@h_8vjAL)iZ$w Fpj KDZڰ4B; +U4З1,| }o(IG zu ) C9SZ0$lO(:@4E$IUJth$jvP$ O6mHDm h@4(*s1cFTC: $";A(^p>:Il2huhFf"2Q( J!ȀxF@aa"J֝(T0pT EBJԽ!KE~%1(Q @[+ |o1Tͯe#Bɬ p|L#H 1\ߠ~˃1`=s,2f-QqSG `z< >Ё ?sCZ w;H``sΩv.Tl{`v̗<)|P@@~8 f &G0~X݁7D>J:G&fm/&CZFڕ{4L0/-K% w_j0T(n7R5v0E{!ŴȔA!BD$=ȖD%(DI!B B#5YKB2c0I@XEe8JրVJW nA T,?{b>ivJ8MH|p_{/]{qC$ 0! dFJ.Y7ҀLOSu # ?@*-<>a# 'cg{~(@eTP^bTj*K5~k[_$ 1 1!kY2Aɓ Op#di `Z;r ڪ R_Y 4KA\"6 8%,i1N$-\|0C;P2"9K H  A Wӣ^4D`yKˣp|4a@'PbX!>|bQzھ}|~"LS~@'ЃP;D R%B1>,%(KS}x@`Q!^Xb @ͩ@H&ʸr&ZH*bMWӧe  *P㤱q =-*.FַI@y$H@b\gC@2=ݾHW_ߑ%)D0}`d a#ep!H)$P ;&9$"ԡۛF@Xu \E@E9}0i0|"}ŜGL8 @@*8歈`]V"H`@T!EE "PFtU8th!ys4XJ'JRiA_ӐHg9ctu'76PZiJu6(PR*СR٦D*+@9# LIb @zH$H@z`jL %jRo, ` .TAAҗ0`UK/n;3E@ٕ]ܴ !G4؜xHPDd@XU XUXUQP@ffw: өl}yc|g < 0(!_dWg Xl=XmS#Za0F!bzCܴ:"VR _#Rn ݤ fRBk$(Q B ?Hf@CE6Kf i8~AB( = LJ8%U;8hTPAlFcȀr]YBDT ,,#Pl+ tޑ&Y&,0IH !~c*& P Z_ "8 N ED{ PPB1$w-/vrC0P11N"(\؅)T jxIa$YP6y"1  k~ ðߡ_JmyNz7)-24G$(MȵCUAG~PH5@Fe0 a ڈf fH(KxƢhW@s6Qa?魹+λZ~aKrƋPE%bOiB2ʅLPԼFvJ>#]o*bEТKW%]:(QhAxPj$RP2 R+E)z,FX # ߎ~%@ X `'1k/  E78u(l`acJBj9!p`96H2+F|3DAB_zL?zvX[pya 8@Mu@)h^,;b8a@qa@t!€wct~X+^נ hc^i(:d#&Z C0z@P,|=U,9I 4#@J`cl@GF( J$<#O-LΒBʄd".NJd@sy0s'|"!/ev]131`L bo fhŤ@i%CR &: @Dt z 4|z,-BZ(?# nQFh4:Hh~`6}Y~_$jl/T!D\@Z(QMfQEyLL%F'?BBJh^ PTzxLj|.tpTSFVD D Ỵ0YWa3zP f&6hjj̠ ZP@ 8h\%"|L @BTI=T3RO.w !!B`OߴwN #șR L"0&J̈́WIR`pGk/?(}XXk L[=\TE\,!aq`IG b`}.vhO]'.IE}">tHO]'.IErJ(H!!$C$C$CH8H8H( p"@Y &n,f6gְšſ4t36`:`I ͨ\"f,FC3h#`xd R]]BGк>.t} ]BGк>.[Hs`$s`K )6Acd6Acd6@D^dgTa\Ԧj5P#A*gBXm|K c,я *Y?5*gjT@/_?|/_??@@{ rg rg r 7s }1} pt -=r]=rD=rD2f͛%5)39<;C9vR>;8p wd. <A PTĥ?%%1м `HddZ`c.(P>b9F3asZ=P2V_%~JWRe+)YJVR`@B"DL[(.a~cN.YoXa =`APXf:?+^ACf$YC& Cȑ/c0fJƎ#v(,"I5F1LxLxLh1cD `0 E# STdEeȇ@@=a pcŃ 0c NI A]h``_0!AO.kkQϗ`7cG2apӜWF8F@0QљNZh ,oHPh(t)0l@@ __ǹ*V/X PT222eKdY,K%6%<J!ӭXP( @h$}?+٤+ a)*  `J'X,_K^{.e̹e" `C+@2`!OV|G᜝8"E1*20D":#IJ3Z # 3+|4hC_ u8PitXDVD`"-44U7_jXj~rdsY c a0H$ A  B @!&e8B%A`!1F ]A$ C"LUX=WD)T \U136f̑R*Ea!<ˉ+W4$h/_ *8kK{.I$Ȇh.tHbw}T6vE}">t_X ?Pe e2*0m$@1~ %9+!%"E8G2 ~( _SSm)-$0P@W~(dNa4EA*©eB?9 2LC<BLAm t} ]B ddd>.FH6͈Sd9O33@o/U" PTܢ@u92ZBW 80  L+ _u( AB';@{ il3WX@UpyWP݀Wgf,_Ъ%*HpH@?? () (QP@ffw0]A?A%SjJt%ӘRJ`9:sINqgCY2ilqfCL'W2d9L<`+=DACCFz_@ :@~Vl6lANH9; D"ry Fvy34NG9Δ ,% OT@P )` a&~ VP`C#`OGJ@s@xQހ;rB@z:,XɁv(BpФ^y^~/ Ր..0 #(;LAC((u :<"?E@a|J  t(>}}%@Q5S=KN_jJ`REy!y!8H (c! (6!QP@ !ffwʨ\ :Gc W,"Lq‡}͘@)rv@"#rBnX# һ=R 0#@GWČ|"Aflw݌](&ˌ,0< AH' }ضť-!I HRBd"@? x% J'Q-"RǤyN@X8"`6#ȌQ)gZnߨ 'շ`ހ<bHH)MlZbӖ(1A Pa/BL# BEACB *A9#+an)JqL_3`E8p u? ;RbSWb 1)9?ѯCs?9@ Vh4%+]c<7* @_~WԳÌʹSj 2)TR! /|#؁)ڭ Kӎ Nָܲ F0EM} %$q.B &{I%)Bkh&@l8q @([ b.~ -p3sAgh,õjɾ60:āw&4(Wd6  '`!ߥ ~RS2]_e lؙfqfAL5"d.0lP!;|`(4Av6d2}~i."I UL^(1&4~$PldqD$ ^Xb (PBPg %@ "z@!C=e/,. ( QUc00r|ہB9 } 4(@ BbĠ@0GHE.a0(HҀ`!_Nɀ?$r?ƸH$ FnP,& 8SXzPUE:S" @G6:y$b};\Od S$04 .DğLQxg](uҫ8M|Q| F| r9Ss GRه\ 9At16!-'N-ZuKBM%zb5=OenPJwdn@$, ##)6P1x``%= A6z>> 8]) d%ĈH O DDc1cŀ@/PS A C8%!bI9B-b+G~H<<b<*9dUHKx'0?HΟ< c0L@<{E:tӃN,Yaybҝ`;wN|%-C#VOZax= $744T l%ή 1OkC\R~t?VEB4$KV5Ba:<~(P+{MT_'I/ 5ƔǨl1y@q/| +`@-l7@`30f14)M HRB$(R'& $q#A 2%-^p(rHF F^d@CAD:Pq)q##?@ N? *T4hB)JU*JZ *B\+/P  0`K $@$HZ #(1$J@"@hF:8Ҭ,dɜ"G!> Ҍ&@r@=^:Og>Jg%Q@"pd'N 82pd  (^> >@BUY+ @^Xb (P(t Tu]u R:5#R8@ @^X|rH_aF`yyߍ5F6qD0e!m44Qs 0BÏpgh$Hq$< >DAlQ?el082E:P %@@@/ =HB#YB1cŀ:Jb_~s((QE*sXp (x!G3╬i]1 $0'$"Ea&pm1Ճ檼Ahc{ '|00@0"AE@>qk`)lZ`>Z(&"?@ ,KoPj}IEQ) S@̇6@L`Ro8P:0iJJҘęZh@@=`3 d~ |Ц4)!I HRB ,~$ G A"[NP BtJ d;ZB2(0 [а XH'؀9o6 )\_ $nnocc Pb(1A Pa DD$$J1.UB " -`$1@Af D0FtUE_\gt?Kflp JU[U2bC8x@ѕ쁀*ɛ+Lg՚#sqx@iʠ5Y?e@ CM@snJ/dW8rrrT4iP΂)JRJ- X1Z*mh$`i0*_307O w9ȌLh} ha c_dI&wpg/1{w(,dɜfaɃ0SCTp )XYU9@ "Y'Fhg+Wu3R K$oaHW2)-lV "fFR`: OPGN4ǦUlz)ߴC@3ޖz}@:ehJU1c1`vъBzjFrs h?@G 3<  u#)G ΛNSnucCUi:];̀ ` ( <qZR3 aOЦ$)!I HRBP'p'8NOc(1A Pb6l`++aXVW9BS)0) R)JRK@E0a !C|o2ɖLddtYg,L@B>7(l F;f~(PK`qZR3 aOЦ$)!I HRBP'p'8NOc(1A Pb6l`++aXVW9BS)0) R)JRK@E0a !C|o2ɖLddtYg,L@B>7(l F;f~(PK`qZR3 aOЦ$)!I HRBP'p'8NOc(1A Pb6l`++aXVW9BS)0) R)JRK@E0a !C|o2ɖLddtYg,L@B>7(l F;f~(PK`qZR3 aOЦ$)!I HRBP'p'8NOc(1A Pb6l`++aXVW9BS)0) R)JRK@E0a !C|o2ɖLddtYg,L@B>7(l F;f~(PK`qZR3 aOЦ$)!I HRBP'p'8NOc(1A Pb6l`++aXVW9BS)0) R)JRK@E0a !C|o2ɖLddtYg,L@B>7(l F;f~(PK`qZR3 aOЦ$)!I HRBP'p'8NOc(1A Pb6l`++aXVW9BS)0) R)JRK@E0a !C|o2ɖLddtYg,L@B>7(l F;f~(PK`q ZR3 aOЦ$)!I HRBP'p'8NOc(1A Pb6l`++aXVW9BS)0) R)JRK@E0a !C|o2ɖLddtYg,L@B>7(l F;f~(PK`q ZR3 aOЦ$)!I HRBP'p'8NOc(1A Pb6l`++aXVW9BS)0) R)JRK@E0a !C|o2ɖLddtYg,L@B>7(l F;f~(PK`ʬ `\3 aOЦ%)1iLZ `'p'8NOc(1A NbbC>'>^ 0s+ b·9ik0)S bOiiiDɝ)JRU*lB<ct@M>'2ɚLd` Űb8Q)$T8@q` L@B>7(l F;f~(PiC#\B?D of;M}>t@].A | '8RA0FB+FJg9r#Ȍg"1H07 `F#o"k`g)IK2TR42Y U@ ~b^r Ą  ; w20b@ x`\.> q\| ud=G=^a,((FL+:%:Dt(]agf(? D@-l$#H`p^/?y^~(  ut?G?_₅  tt 4 ttА8@zd@z@8Ȕ22H & &QP@ffw|M8 `6_w|q :`]# `TqB{' 0XOBh(7p7Pq塌@<Â0 `?a"bȒ>sxp,Čxjk<@`" =f1q`B 0  DD#r\BFƥ1s`R`+A[6  , ӧN:~>(p(1a;0͂g \@'Q/g6хHLXQ6:t+x)$DRZE-"  @$a`CT[" ߛQ+P?vDIZ;``  sa\A$-h'(@@"0@.6 BAB)Vs1c(B:$ZƸyD"=X-Eb!^Xb1T(ѧ7;Zr7Y~.hH~S08r0nG4u!ґ,JSWP B/'?SOC ܠ?L4v?`s7굶;0KdT@ĐE`2Zh*NPa 8y ]jrJcĉRFr(|M ́< `:?'BGX=>iZ2C@VZ 567]gg9(d03dk( @c~V B#!BC,dK"QD%(DJ"QJ@"@B 7DKzRAgg8C%,6!_` I ?i(0&(*6l&ijoQ,ݟ Z)O]@'nh1"`$PebrB䇑tyYBM^"?O{ODy@dIr EqUӧOs~B X<6L"Ш:ł4Щ 2C9 )ir^lTB A)yMTXBF"h)֌͡2?K)g#"AA"&V HݓI4ʢq/"蟋u~?`rri#b&r@`OvaB$AVZKg,$\ˆ[YPl\P`y!ik OL5YY@2P"  `4#В#I4tAqJ>$@^Xb (PB#2 @74CtC(. EL.%L01sÎYt=y.iwXWVߟN7jD%  PhQ-6OӈP4DjW&AG` HCD4n^i`pEy w Fpj KDZڰP(K\1,{8q\ +V  >5IVT DRH8]TP؂) Am h@4(*s1cFTC: $]cdK1RI@HA1] Vām2~P#_d!ZWZOEVjUQŋ%S1.GF4|^K_/D8~.~%,G?͌c*j|C A@p|L#H 1\ߠ~˃1`=s,2f-QqSG `z< >Ё ?sCZ w;H``sΩv.Tl{`v̗<)|P@@~8 f &G0~X݁7D>J:G&fm/&CZFڕ{4L0/-K% w_j0T(n7R5v0E{!ŴȔA!BD$=ȖD%(DI!B B#5YKB2c0I@XEe8JրVJW nA T,?{b>ivJ8MH|p_{/]{qC$ 0! dFJ.Y7ҀLOSu # ?@*-<>a# 'cg{~(@eTP^bTj*K5~k[_$ 1 1!kY2Aɓ Op#di `Z;r ڪ R_Y 4KA\"6 8%,i1N$-\|0C;P2"9K H  A Wӣ^4D`yKˣp|4a@'PbX!>|bQzھ}|~"LS~@'ЃP;D R%B1>,%(KS}x@`Q!^Xb @ͩ@H&ʸr&ZH*bMWӧe  *P㤱q =-*.FַI@y$H@b\gC@2=ݾHW_ߑ%)D0}`d a#ep!H)$P ;&9$"ԡۛF@Xu \E@E9}0i0|"}ŜGL8 @@*8歈`]V"H`@T!EE "PFtU8th!ys4XJ'JRiA_ӐHg9ctu'76PZiJu6(PR*СR٦D*+@9# LIb @zH$H@z`jL %jRo, ` .TAAҗ0`UK/n;3E@ٕ]ܴ !G4؜xHPDd@z v IQP@`.ffw: өl}yc|g < 0(!_dWg Xl=XmS#Za0F!bzCܴ:"VR _#Rn ݤ fRBk$(Q B ?Hf@CE6Kf i8~AB( = LJ8%U;8hTPAlFcȀr]YBDT ,,#Pl+ tޑ&Y&,0IH !~c*& P Z_ "8 N ED{ PPB1$w-/vrC0P11N"(\؅)T jxIa$YP6y"1  k~ ðߡ_JmyNz7)-24G$(MȵCUAG~PH5@Fe0 a ڈf fH(KxƢhW@s6Qa?魹+λZ~aKrƋPE%bOiB2ʅLPԼFvJ>#]o*bEТKW%]:(QhAxPj$RP2 R+E)z,FX # ߎ~%@ X `'1k/  E78u(l`acJBj9!p`96H2+F|3DAB_zL?zvX[pya 8@Mu@)h^,;b8a@qa@t!€wct~X+^נ hc^i(:d#&Z C0z@P,|=U,9I 4#@J`cl@GF( J$<#O-LΒBʄd".NJd@sy0s'|"!/ev]131`L bo fhŤ@i%CR &: @Dt z 4|z,-BZ(?# nQFh4:Hh~`6}Y~_$jl/T!D\@Z(QMfQEyLL%F'?BBJh^ PTzxLj|.tpTSFVD D Ỵ0YWa3zP f&6hjj̠ ZP@ 8h\%"|L @BTI=T3RO.w !!B`OߴwN #șR L"0&J̈́WIR`pGk/?(}XXk L[=\TE\,!aq`IG b`f*8N`' ,D4d4ēADK"brR BA`K`!8 !P )CUHQ  PL\d, @DE% k "  PaB(*1J𜾖Jo "`N h  @(@bB&Pq*W   @$  #?g%`!,D+$&P@Q_0P" d hz $#P(F",1IUO a@hJ$A0(RBcd@! <0b!JZ aP"H)(ZRQ@,@, J( a "`@{&" S@A@P%Ce^G*,Wp PA @@$W `T",o%@PDJJIE~ͦ@H  % PDpP1(F*"0Hq`m #H/ #\QA$:@ F""WA @$  <0XY @А E b"P)! @( NV`0 O @ʍ 1(!L@;8p wd. <A PTĥ?%%1м3 K´w$xI2}"E)K!koFw@<PctUb1Nj0-@6Y2r`QkւH(x 3(` $H_`¤ Z}ߣ02$GV4r?^NrDh+4*n?F  ?zO( Qsކԏ%RtXP aB n M&7ɣ%ZQ A| "$Wi_Jbq"4c\0-JF@a" 5[ramy7cG2apӜWF8F@0QљNZh ,o B>L>%B'gx`d4RrT_e's@q2 - gS0E`c *U -?L 2Qrc,5 $?.\ %@|L =bbM!GG!z;u/B+AD )=k"+5efI <ÑJa5ZT I axWy7XǙ`ygLl8 8,b>f/Ӭ @P r9pCIVê >P]ԃ 8@D4D( &@i R %ZW\#9" V?CÑ@z2Ҥyg&l;Xik(z(%qu0dҵ -mq(f Lx&"EL0Jwo5$JB< CCa*%Cx>!`$T6qޠHp+C$X jXb1 t!x`EP P @NXτq&K >\w@hBmkx@d4DC! F,ᑨ@uGq"HŜ.I9'9Vs)X)KV{ YԬB-VJR^Z)b$`ykF#Qs'f*8iTQY+31/@ B$ (t-2,&r)T=~d s(B5u "XF@@ &,h-9n ;N/FC0! n|I6Pmb X~䓻׬<06,P]Z4yFĖQ>/1z&(?7qkj!A\! u>,x} ]?@ p怠>B#8g?Nn;5PF*j24 E!F  S砒(dI-HpZf Oˑ@R %"I|@Wzvv'aYEA%9)Cj@u:[@Pό%^ rcXLHWa"DJ# s 1 # Za0\2yGмLҤa(94$_~D!`@AA1 (ml0NG.V"r 9|@    J٠8E w`sir%(bO  h-t!@PТPAIB_D^~9{5&H_), l(P(@EJ_(x^?@)ЀL/" S:Ӻ ЙVz?P <<@|^B.B">DB _">D9P9@F2w)E`<S,:xLSry  RDD61Ο/dd| p'P(Q He*TWy?lL  `@fAHPpa@JA$ @M#@r&#H 8 a \0pP!EP~XMP  R   DP)(&P6j  0%94RNWU8P< # ł"$,S? P & t#" @b A$)YW;M$H @$0A` H@B $Bee "HA 0p㘂W섀AhB`xYAa`@@K ? ~ ZlC@dKNSLIA #{Vkr#<$ E DRR &HSHGJ .CT @C5+&g@ dNt7>Dax`(Z#X0K rr9=jCpEj)qw6`hAAY~ ,~>?%#&F Ye_B0"ojok5܅XJ,.KGG k@XtUqUh"uu6e t}[Ox N!h3? *~kAv  0 7#AbLdj Z.P F*P$N,"IY*rU&||\`GQh$ [?E+cJޗZ` AHDbBKbu"l 2 !r D(? "p@AC+ @pA oS4౺Kr%$ȈMpe5CD2 LN.b̥xWI,u;E;+3 cl7.P?G9XXpV$`@C1|$Ha"ce@ D.82vy0h@&"B8)22$!_>< \0) I ({̡tBJ))E 3K f䟈V?< >U%4R D0UG#U idO_ r$iX8ƦJ1!_VOɄBՙP镢$?DK`g* ,LPR1@ ΰ$WA!6L]/5Y"w'hq Y42&f>WFxyc3X `bd@`. X➱I2AV!R*s"?T C4B>jBR * r̈B(9. GQs0 ?qHF6)iS4 REM @D:C"ZGBqjn}N׵  Yh÷wr#quRm-+Li(N.z`ޮǞqU" .c\  j EP} <, ȆGP " DO$\ՊF9xJ_<m &Yvƣ ]GBm'ߵH@$: gZ"&P.A0 JN䡤Uy<@AA G&@)L`( M#A!^@*ocxgsvB01P @[ceۇK8 ·+@SU+.?L`dPh$$(STGtҨ;%gՂӑbQ#hܘ4܇$ HqTԐcW0R-H)_0!>1.R8=#2p`(C.8P(BB0 wP;\oJ!EbQ` =;`P |I&XJ*c jw+v _bSkH\;e0fUHF ptmElgHJ$RͧIMʌ AH?BzSڊ`EJ?ҢE<0'{MқsWh^p4R¤k2;L]VdxuTDh & :h\LN' Ax4V]oΪ)>֡uJP $d,$< @ʩ| $BUT! ifZ  5 %U(cE4Dˎlb}u\|f DPU//G*  @!_V2VJDVD$KL4().P"10!U ȇI+."6+o !AhGXt* ^y1{bb! P [o/yi* )їe#.#UE,CQFA2 AcTzQĀJݽ-L#AUuyF, "ȵibhE,b&*$ϠQ4Dr1%#A6*@!.٪z;&IkI{BWd Q`1'?HSWSeJL]cVnFY~g4i pq@$| W_#ِY / 9ZD N )cBB}J5ÀTx00HeBDXJ3A]L"3sv TDATIJ`T<N A \)Uy-R B> QTyy`Lj iFh/Y׵5ب/*,+j?}!YvrZಀ8^ K?6@@bhp(/@ rA +_J%N"f X=*k/d$*'D% eg8yA!M8 >"Lc- 5&^C6v?)5f~Qr\FOIJR? f`Qfhqv 4]NH#m R(jJtK10Oqp' @:C:@ BɡZKC+_2 DF ft..mA#I{נEt) PI@;%@cTE!Ē0"IS2S%Iʲ'pP*&UU[T}ꭁKxkY)/K V@0 COW_,d@P,Z=p%BA.n7i0aM6&R߰ e H D] 2)`r"QԆAUЄƂEhf+2XmFJ qG" ڗB'# ¿`(ϊhAG9!fZSOlT`x 1x7/A(l}>Sj<"J(u4yrjhw 8 0@4Ax&TM(1bD$PI?*(Y0@? 2;I{C!_ H~5 p KC 2lĿ;FO\!*pۼ!a!a@ +tfG0XҸQ b `(|piQ\$reA}LO7A yiz+}GxV.Dv!N> TY||"U Rm *3D%BF>%|7 Cjt4SX !]`&B[(mƠJ 4QK*0X&9k@8K`A T!ջ/ GU!.,T}oM j@FM&C-{BYH)4-'Ł"4R2jARCል$*E4@Go@"mD#?& kaڂq 34Hˬ1!ZWP_@u0HEG^~/? >\ܿ@  'ET!@})( .@ktEO /U\B]-[_q.w@,*(ȆBBD ,BPƄ@;J" (rj%8z)ZHzDEH$Da!*,Xb P'P 6L>D8*5 EIA =&";8ݒQ=ܴ yy F8$)@(*&jVr_U8L#-xTZAJ5b( 5BۄDڎ\rrWVi2)z0m9 J·"`}/+8[rF|v2E|yr#@) [ Qk} { ARwfAS䚇1@lo0I.Q4#0~k@{ 'Hx{C8G'"?@O )%4l \] j1ÜFU+dIycq7 4F<ypiӀ K6{}lIw@rހjo@6q_?@>|^zjjF`!M }R1$\Y膱Q'@ AYi0CnAȲ?pM,_!%'L(/48esIQPe0.[ 8dCdCqun.D^G^>Q""""^4:@sX-3Ӥ0\GHj@AkNO(LB|/ QY -!DMqKB^i%`0XGi{(ɂq*@ C%D (4"0F)QHDL%8JA1(NE( `4{'"@$@" pT IVE D@ `ʂ 8=JWI0Ծ_IAvkyDVtp9,*QANR6ck?*]k BU5/ J (@1u7"Se1(2 ?T4T %IEqa5B5@WI`hBpziU>N((Zmi ($h<>4&$@M Eq䋔@n% @wxdrAnw"L}C[.?T@d?;y&J "{Glɍ1 tqU&h  AzBlI`҈C-%Hj`0L(D8L.""L0DHwHbK )UL!HRJA0~<@bW3 CV$QibTd r] 3HtK5 Fm=?r׵" A}k?}AP1$@PF@ .N?< ȿ =2Na7x5%8 d%`m՗-!p=H @ ^+u6WMWQBt|"tT@w 5'yep0p i>4PÙ% h&%A@DthA,A`2 b. BAJ*ʆP!@aR=% B4jjC @9+a XEa?`UѭM/ۀI:M`\6SW4MUҡj} ȽXw-@l X@bHۣLF`D!#4NViOF_*= 6`y 崑ğ(vB@(4aEკƸC 4=|x}o06bbE|G@ONa\ bTw09TGC&r5y!?W)G1~yx8A tÿ_!# ݺ #'HEgukwӊ%21ːte;_~!jA <8<`$@TT*i(Ѧ$*98SE+<}z Jj2t U">|XrC:1C.!1O( \ A* 1Oy2Qa@~li/ XTr9ZKb,/^ )kK#AZ;H)/F?,_ᄏ& kbDN‰ * 4  pG5TYpX:A8B9C(08lGh(tPiQGXU%3CiLjz|TI4`R9 xNh%v' A%n''mNM""K͢FŘTNTp_̶3#@fzHT "(mfL-9[*@EnS J79I'gyA8q $=JG`5 Py W^]C0""6lo1 <ޟ)!T!S|?[[?!YW)2V4#2fj`y!W( ^y7XƟ҄\Bsz<4$\hhBiF(?~,aٌk7a2$NnnV/*n{. קn(1ӏN h;UҤ7>a/]P" t 9 *Puʯb4"~DBG+@r頊J(X0ȸAZԤ * d@GK8f9!2iC J=J,.ѠP ps?PX( Ě-Jvm J _iQF&Tk UB8A55a)FkB [BXB!WPⲁF5_i_KU@)V/t T@tR`}X \ iA"{8G_V*Ydup:$F8T~NH e2t9N%@XCk ?Pu/3 PQH@G(bHTTt&!M@km^?^Z! N2@#NPG՚ٞ<' C CƄkhr? ds*QA1ńxk+9 $^ Pb @ER =2BU(%B?U  f@'0P0-k/ #n>!!J S< 7=(_a׀EY dbtrFZV*tPf ; *rRJ zaԪ`[8<\'@!&QG}@*u"AR_/ф+>Ki>0*M2 ?`A*PhG1A >a@(w_,#B?p?:-*!4?BU'` p  np@10㳊# +#3(B!:I? - gn0]AL5q%.LA?t, G1h+s:+`,3IjnZT T8ŕj}2)yA,%p nt c8(D3>RPDR+Ȁ!wm:oB?JTBxU$ -U H('HX/06F(@lwJ/SMP;F4%W!+_"K5HB|n0Bd4@-%ŝ@V/#C 3|.1NjY O?/Pſ1@Bda8 ( a캃eJZ #,dj0!gB9@Jb,7 @|0@44Q@0:@:&*1D 0Ui@!AkQ Ah6HGҪ׀ף69ePO0O!!-,WHՙ %)@FҋOWl|C!@,u4qC @#=R+T2/ d hψDY52Y(n "b@(0Dxz 7SE`B@}D/Hh `r*V Wؿh AZJh@+T2&h8NY F?ɴ) ]* { |?@}M=  #7gfbF^W`O*Ur1xZ o(_ʔxٛD0(N?xn@dxJA(G N~( 2PtrJiJw+8C;M5/ ^\D Zhy6*z#E R+R8>/TF`!u>I٨ @R- iShz 'LG $0!=5HY P]UE G=QL4*|Q}?&P$7@ d+6vh~ ҡV\X%hRGz|gaRGf #Pax5P->S^~ ,%,I00"'B,M%AoRR L#2C%JP:Av(` vB ꥽[,},$K$0 P$I I# @db#@@0`@8yFʅ*#%@ 0!p PPh Sp;f095xн,g1'*i?` y ~&ǜ074iMH]FQ,+kKɆUAu ԼV/Ӹr < r cYwBa !Hު%P`:WHEt\D04zd%ਥGITtdQ)j%/f X$pL?ː?y>y(h^.^  B1 hM2#a&$M( fG <+|x>Pj?tuPJȃ nviKQu4PWgŪ#G e em1## "!d(J(\(U( /|$*P+ .+@`@Xbn "y`AԃqI %(r 6' eɢS1@A_%HILydKcxL%p(0g$Ix)"lT\w@xzIs e8 #Ǒ(NE@K $ p 2{ ~\ªLLA"ixM|`w5&2B|bl ԫliWN>?[&cf'i;~PT菩R{@՛GĹe1]޲q./!DS@K]V9p:YQAAěG.y4(@(dʲ#%gJ%#(II:`}CƁfX2d#'#72!3DhK8~t9Yzf'-/1$\cUGP?d;D*Ni3frc< AZBG vbc\t貰gAqp9z3 D Uzv*Z*0LH6U5-+_GG `9L1P m `=tAjLR0kZ0!ThVBY<` 90#T{#dEuUzȀhr@-:X8Iqˀ^ cE G;L{(RE09,Kdٟz`¶P"i%D "+&QzC Ϗ(Fh!_m }TIɶA?$!jB&Xsa;BaA$5 {p4rR%'Tp6re{ ?GP$P6,1"HycL!AptrH˄Q P@aWd]D@#,N! `z#M3 !%"`UiBhT"z=;P_r/s8}V(.q r- *2A $44$D#1"_Xn_[hS^<A +"UQA@ HAZ AI]Vkx_0;y_E xRGΏȡSMX4S'HxZcё4e=Ze'`2@L5?#W \Jh0.ֿS0]Jp%݂Vf &E)"ŎTb| :!"RAF]lSUFS}90$ψBbmg)Py` $Ht&!E@؂f攣V{cu4^rY8g3d:jzD!Rk@Y7"H5BI*P&Lģ@/;,E-52ME0$8$0t˖4Sʀ12IPIڹOYlHY01*]gP! Teoǣ@Ffp9$a1k/SB9)6/%A.B\|p2)RQBPz)]b-wHJ]> snI!2?5P0ትhGtV\TZ1ʔBG] qسCI!a# A(sQlrTQ N ⌭pRt Q|=g#QP1z L ԯ (Ag(BA$ECQFXHԁf QuZOViVN$XFhе$TJyC($h d)J Q(` Iya y|*'Q@$Hՠb2NO"G+ǦD$8D(|A 2}Bgr@HpPR%g0 *.*K8 VC΢'IL-B ?)JC_T$G`,EusވRArb+Abٜ#@ґ !1о:j*E,qA8@Q+"iO;ÈS (ϘqO)ka_C]QvME8Dij4WWԇ,&,)^85#*Q. 14?HE1H,DxD$"p pT( . P$u8z?ʬt Y+0-GW##(گ##4"$@R+Jj@/_h,ʿSZm#q!KE$k]KL%JaNފHF׾B#j'cH*K<" )Cg ~H& Ps ,">CLm!"I м\Eix @p`0-(/AyA QEC rÃK``a(@ `'TtG*%B|t63C! 8$,Šϥ΁&C9?Qy.=.3y (|z/Gp}@-E`BQv]QDZXI:'֑~/ʑye'Oుazō]EBON a)<\!@$X. \/?!#x^,B AiXx|d~P?(7c(\|zPoFy@  #@T8/5#"4P"(@(@! D!B F !@8n^@,J:C3ׇDQC*hS? @M(Pz!Z(O^@Y4 ^,)Ԍ^\@vF7 =L@/6dQ?gB"\A  "-PJ0GԎÇ`CA/ zi 'VP5(r,@(L XdsQ@c3`wDY aA~+p@@#E` @ "5I@*QB sFV@ Hvl N,晬F-W # 4 ddd1#Nj-&`5G'M!i*  %4'PB#)D!_爇& @ ah _0p?4 A0aK'!((AoHs搘Q%w6 K#L?\a=N94uJ@ )3APLU|$ .6(?ade 2* Fbt8@<@P5B(\U/3(})?ojTt=׌I]E\\DSA{,D[(B@T!Kf0&1?s vN jH"'etÓQxVиG@BYg53 9 Y#& 14UZ< ՠ@ hI - IB> ]y,L~0T:6m CJ0$xJ]@Xպ+g`a<n*IYBH (qܑA0 q/z5+Ɣve2`ʗ`gEA9EZҋ$5CN-@ BV4 M7(%_QE W$ P=  @2?aHgL@# "L~G(W4HNə~*#$+<V?M@@`4\B-,d/(i$iZ X@Bt``  $ D^I@< RN $tx`%@ Ҁ4n5@/VQHY]@| Ӂ*0NH DEFȀ }!b(iÕTf/hd Ac(-I`x!I Qn>!!D0D8 H¤/ ,xMP$.-X-(RtE@RdK1 :a&!* %,gDuN~r 9UɕծE_ܧ`AJʑH\9W~`W_W(]`Q^潏 |1g>Ph>" *,(Ddɓ&ij t/$DCxΎ{tl{8@\B8R>oeriD:F`<"LͰqQ-qH?i, 3a؆cEH !H)ȴ(H (Hadc8d T"1貊 T"1X1踆*Q #@"Dddd0 %!!""Ai^t@?\.(?HhDP5:1޽(u$R`Ϭ'DJ)}a,$zr:if&*+0B1tkeXB#?F@(FTJ)@EAja'#GYL?!UT6= 4<d@Dbwa s&?@?5|P`D`" Rw$r ! Zn!h h^$t%B] A^ KC"A[J3:٠Ba{ `S%h1Ά{E9Р#: gBиЩAjt  8>hh$Xdx!Zh|<<]>.JiC`LDM^&^)oen uj| oX~N( !&184b,;W#=0c{8^M )f0^ bq&~(m"Ɉirb+ 12QJTBPA* B QRHm 0%(i)쀇ݏUGڱGfsS>P[/W+W-#ZCA:9@fBET>HQ# '2mpPJ")i@7!aCGo󞧳@т]i d\V@ R]0; Zh8&H$80Z ' Q6hUYДf2" ̐P,+@`B0d"Hi UJT @Pd Ex:GyA,`K ^sii-]Sba wu'!Px82'! p,GBwIJ)Q [ɑ@P4ӆD DqwpӢvSEw{Ԍ>"y!-79u9prr" ', =@+䣳$A"ʢ 8s \bƏb`q&N3ɈxAP @b!\3J Ck@P) Q/XU`R_46EVf 2F0D8yp @&B2PtP)ChI9$BVTF34px4@T"y!jppQ  `1$kh5 dj(ŀ/TQ sH@BÜ&hs 5 sh<S44S8f(U3h>ī~2r ZPA!H 0)@ZHyV `B$NB"jR#v (!0@h(D? APP '9Hx!xEV,5F0.!@F8!Pp*` [nCD$ ()ӯ"D Wc-*(b FBA'ZYiSpATpt JD(*!PqB$z.DOD{"dmE&#N]?\)2@Ր|(ϒ'(b(,CQgL_2?HD ʠ8&\C 4jf $AĜހj>%J@6s* z92 $= X)K0XF G% qB%W))פ!(qHVJBY4)sd@E@$6)k@kiD|`7FHH t4AZzGH8@h%A  ] 2.0P!fBH)aBPY <4hk)O}XP8ro` A/QEb$GJΔ$K(HpIEt17EI($`؁ɓ/亊K`@(_h>~.J8%0LңBEwaSWB H_<'E{#,pTˈ@KUHi@vS*wfۊ#;` ^耢V)"p4b҃ˁUUY !ƀ @@Ph(&q=" l!Dq)&׿hno((! V$m ``hh&aNo)(gK̄K`(88)A:?JߣgKmW8e7LttŔ]PNeVkGq40 Bϖ&%bz^Y`U1'AE $\ko:(ք MI B{aDk++-TEe1=A 1 $賈i0*!\$`@D@K~Y"!c#PJ*u&w)B:wa(<ĺ(("[ᒐ_Ĕ)" 0-A EDPX*.#ʠ수`4(>5@Y#D⇞8etyHPp$a&R@<)_hZ H ;C xwHeH>h+: :\\ bЂ5NÆ-#/ ]d)jBlI|aGЂ>DT@,ϐT[?ang{b#ةA+ ? MED%NO`RM_,Ru30+wbCqL>+"tK74HU* D`FRPz#"yn3_q)U zJr`/0_J`+3X$?T &" Q:3/d@խ  `$@slGT BR$$ pjF (Zo$hzՠ_q Z " UGj4w$3|ܸU~=MSUtlXY Rlh'ȕ9Tv5gs%owNdbKh /*8=$OPGH0o`?|NRn~e* +k ]9fu%ҪYsH kNS'[1^s+Ve0UG X@0(:zDN@`<j5B. q~9Y: Pr@ќb ? nF91 M~""M@1 y,!APF/5 j}>}J# @-EcCڐ3t5{9p`PHh3@@p@$|vF|P x!L q $ kB$PA 4n _>C]A 6GZ%^AXaad 8hy*V( PM&J? .(=A@! o\=րS`{!urgpP+PIhPӅR-786$d? m`#&J g%ʕ\%|hAt x/ɐ_ $@$ p2ʁ  0B^>}` @DO x,4A/EЀ 08!-18hhC((!K  x`x ʧ83)@ @~H4h Ѐ  Ph(V`@4((@D"rR~}@@T )R`@$    @@ p pʑ _TAP, @cv`A|AN8•zK*KLg.{*VhT\H8A."<'$N%Sp@! KnCU X QA$ygZc@`Ba"-$*(@I0,h)KCY $28_op,}𚻪r0 cJCo maC(ҏ]lh<NhA= =9P `i|ifP@ME9"/3,($Z trꃔH<)XVdAfAwkɹ XqӇ~7 \I÷=C PO˓m f{5ZqІ'?w"C͙g'uDP]6VD }ʖ'EA )`2N4 MJa/L H` aWG  b??<2P8/GAY,8Q*KB2$}c4(E -Uȳdk9ꣃM̀<#(Q|rk,Y i/ :P ^ؓxvz( X<8ڋ7P!mNjnFp/PJn>n;a! fJ&Nd u@E,2h$@<} h41 ٣ /&a6#iM3QX*Gz0t EIRd@FNĊ$g32$ ̇P% V@ J%SN\M Dا*1+s Z+Hd$$IiU&5/v^4Wqje8M4l<Ksr@-K #Y?O~K4+P?hH X ̌Ļ(e6`4Z5AHJ?p PA^#`  jEN@G# be lXf02Y0C}b0B5F?,_ Aʀ$0(XaznDXF@b7#QU'`bMaG.xM'4 ][f4Ca8eJXV"s P"2ެԠxE3d(TajAZFN_)aIG(". >aCm)VX@;ZQjLSKOlUfڿH%Qg91기bTHT*2PF'0 v@,Y-@4Y2 ( 0=~@ͦ-@ @B?~T#I+!JPVN`1DM񭊲 z0P8IY @ӂiuJ[OA`dVBxy)"&ʊA%%c+XBF^O\+a4JQ"&&&RV)1@P}o VRβt@"'Ϧ,dmXhU).4v6ܸ |` C8+ZNnLM(DgM`Rش1V@t -JP`2xFh-آ)CB,y. BoȮ64R89S"I +1BPuSO L XAC 2K-)uw %/9Lf|̺jAIdTAu1 x`2`J  hc+(wLy8,bcJ-& \9*ܠS @ KIPG Aʬ`iDW"TaP h1h,Ql8zAYT5OQ {C:-R-GK4" i5JԬfGp %BB0 $z"ބt8 /qIKHh &$A%(hJ4@zND}VL4X 4k@xJɎ@I*5A:@b &P`yl)8q\L !:Plr_V!G~A[UbRH@cLR( (A  BrQ(BX$BHzic }Mq@9v~Qr!W)s<)@}I)u A #C?pF46{"*N0`s`Y9"Z sFt*LP1QS?xfℨ鑁iJ]QJS!Cy_ hʒ6xΚِVN](*ր+,nfT25 N̕*mc ݒ .@a1 i'^ %!B)X,.=0'x&68 }55oDJ2\ SU SZ !`yZMo$KQ|(刁kpdHP= QFź[R#I1(3>YU.E(ԦX!'\JP )GfBővqGQx&l)PQ4ڔufG>z9}tUi"epa5o!^8J/Zl3EEIȵzE |D9&B.`]hw@~$>,Zk^KP!FX9ʀՎDQn}$l *+KV46@5H7@4E4@/@R z]h -hOx  EU ,I X+HQт>Bp)#Hr-=0!g&# y]xb$ W$ #"tB(%ԪJ: WEPUH*J-QKJBHH)D5Dq2*&P@`?:E? fX$@ ̍ P\*hĉ .zC!`U*/T!J@?P]O+Ny2i' ?-$#O+I la@AH9@J 3rzF(P9d=Β 0*5=":]!u #>l/ wbTzH@XQa N"TLI@3D0RXbuo(U!`l*^"@` Y|Wh[XW{ ,p`p<?t01O!Zp0t%AÃM (d0ʆb(ب1G0GQV$pD$< H Az!HA=H@m@DkњЀA:!M*&*&<4b %Hi!0()OEAޅt)-P$,?]V9@ ɬ"%Y+1`TYA jVc ý ~ Q WD!H݊0JX)F G_ZF\ l ?,h0<"e]EF,l$xc< &e0pGWz89 393JOl t r w!rgK&{OW@?@?A=ByrLXNš ؀@A jUG<0e .r ((0/y?ǒ4dA ($(@"8OA@rx7Ar t$耦)v( CxMF O) 4[0@"!T,0:@GH i$%p   TfgbYo4t#q,@[3 h0(W((p @60p$琹qs !4_@0.#P) jKB aAe=$P0,ŵ"D0Ʌ(0M) Z :ȡ`,Ga醡! p$6krD@]. a?#C4$F ]e0"t`,_?8ħNN"  Q,M@_qzG-)ąT2O#%X!ن(\ey87 ^PJWM1ඎ$ t %T QT%@Р6 (  .m+HT:? &:+?W?1( 'Mp;\Zaw =nQGQͳZd(XAr0>meOpA;U8~k  )BrxGK6~lxHJ(E11@tEDIpZ9T!%I_!%P ȘQڣԡ 2 #5Wf1eD xS0`@6w_`ҕ@xV(^mHH0EM-ApuX=#SLX~сZ( /6TĴ^/u H$ Et'-,K0Mf(L%Yƕp6@8Adx/DP ڐ\B#M`sp ,_tBIm BӨmodpoQYaQ/&hJx4 2LWlHa;7(2NiAxB0 1hxABPbѵxꌥ+@fUG 8pZ 1 I`0!! AU 4N.L瀔w^V[t@Y z$ dBMBEԲsw;'}{XrnmGEahG r} !" uQEǴ-&n4O*_b-UcH(דGsBS4f0#R,ՌIʈO)EZ=X2 HAH "A :Ta\zMP GEB;@h 4iWpeoz Q5tpBȏ ĄRд%Ҡ-kF%7`xJ (c UhEHD;s`S:̅2"ؼMGs<0( %ɿZfm5(H0NU[ p6qMꀹX=##dz* ` #1D!@3F@P'Ad^~/B  K ZQBEP A@Дz_d"9t1htBN(@@ۃ PUhrR/E -5ߨ R>A(H7lBW6H߁-C< O~2> JCW0x8ܵ^zC.s3XAfh0 ?I@F)`v(ZLS>@ "\_TO& ?xI*|*_* wdXE^f˱`MT}@D5bToCAК2V"Ǵ*JI@6=p BJ&0\"ha DD Ea:Xy@.\b4P hCtx`#xFb(S pSl $cPQ1XqDRo 'sJ` y<|`,X<')e"oGJ9Ƈ P>FM (@( g@PPr-G.W]@z EQ@&U+@m db!-4"+o#DI8 %ePf_!Bl0 QO?Z? :!r9gArdO@PHP H.+% )$"" LpNp&E!@b@ b(yoBO\Ipb5!A(!k!eT4N (m aj" tpΙچ4 7@(; !T >#C%G"p0+p݊jpb"Ms"T%J cW:8YDŔO V%`H $ **a&S]BYOy+OP[OG`*> A1OSjHX O 1'7BcbM!~t1PdT ` D+d!TB$6<#}lr^Db/`eJGBp7RzP%/ 4`0Fh"8?44y$ xa`>2Wr';~V W!\r +.5vJ$,Ǘ͘8U!p!еpѡܡH-V,1k %@/,  (4EbN`PxS'W+H$LFwmhB^D?H#0ra"9l["Q]6}NmEW FD!,9do!$h&CBX ~(<J8lQDŽ$xi ?@2GhGڡrBB^(0`݀K@%#Q*?>PP0>#H _ BPB?'JP?=A[e@@Ɍ1]jA]آ%XIÉ $1__ J 4{Çaa@F@rsYz/"𨭃͡j3S A[a7'&Q0K?(G˗/XL":KЈntGj'dF9JI<W:^tOR(@Y5ha GhC^h- @¢,6 Y  ХAhg8D1{VS_L`RIIC4&P&ȠQrP@Vo}Hbt1+!,g 4j#QYd1} p,; _`7РʇD (ԟH@P_K #)%! kzif~[ACQFX)QF+A4*]}Dvq Hq$Hao@`8Y5h >oFhu$0X=$UCR! tpUQ{(Py8@\ U?}i  ԛt(b1#/ ϪtȠ=Rj(v`@2 Y` uX@N<@2E14@x:2^ZЍ V#E+F" zqq% CF.F.&*gD0]bX?( (IL ,$a1Z8"чP1"ZAQ,ߔHao Y]#ʜ(, O%AzCtڅ Kȓpr"Qq8e B4(Z1hj%F`%i(Kk3Q?Վ! xDʝca(x)%uBe A੹l%9QD o!ܸ |b 2\|l7 @ A UH!JRa ȆɆ1!n4SnʐJAEZh?0ae 4w0 ',>fZ#-Q@  @io@!yu3E)_Gӱ@pʎgd?Cg o!۲ab!O䁀DB   Pa1P! dh/A 0<tBROH+GY(PU5@GF^nnn_B\ J8Q]Rb+#q BdQпN??@OM #!~Hdn /DtE  Aky X.JLR hPH2 8pTP$BCah.P裃1ZaG-I@kO{ f)@G0@%5|HJ@Y."#H0q(brȍ !! Ѩ$"Qac$i*!@3u$POףeRBTGk:=lc\!dAʗj5w@ b4D:)U 6*ҟJke,H^A Q*qԏkMdBfuaJ42\s>A~5&/˖'1zR %HhD~6x),=c!=-߷$i}Wr >BJdcQ@Dk"n!!}iBW@M E22)JP`eL@訡)5!_pݏA,]9%Dε9gX1&ʘ:fRB;,)  !R!I@PQTV  tVy1W u$myxm$4础Ej(S@F,j\Yh +C!XNȮVr%kN? o8:B2bﮥKMdJ1F+Rtus"0@@AEj PbBF*J#Ɖ/NZ~|9w( "%BPG (ZƀE. dRpA^@ y4P^R%<)JP`l&} $(+:A o$"հAH,q/0FTP< u4b e)(s5ĸGƙ#HNͧ<1{'̩zpoEWa P+ .',wV`Asi5P&d"\J˼|eE£&s?!&XcP3` ݩ)!'H!(j4V |lG) ;ĖJF/(M=[)F GLTb}icEcC0 "K RbP>V4yDN0SWFK%b1i0p9tv AB9@*Q?(U8r!x"F@AHݒ &XON4ij4@gF"(Vanj)0̸c@aJ+ ec  AN(3/2)`Uˮ_i,'ȭ*遛0\)`1Yr;)4z};C )!$!S]\s}) w}@H|sْ8YXB!_XCOv t0B4HЪv  `&>xw! |hfp\4bH$"R,++ŶxO^x[ɨ\hj~Pa†Q?#.C\-#?4Hb )?lם8I{aToHFNrZ >8jk r4}:~ue=&>dcfJ{@Jg1-@]M@Mjh .4)@M X5ZіR.B L.&!@Le9 E}/CpCcHAE OiqBQ2y*?HI8*%1,$H  JQZK1͏g X3Fl<\sF E BUN;FGX "@00i"60q(^,>H6ؓXЌWL:[3נT 0i!dI $4CI%RbBD4>yU:L $  @d٘ P` ʲ H-*BAHtIIREP @@ @C3R Aq@%TȀBl@#$ThQ0U(!` ~8 8hnAh4Ka@!soN $ʻL0,nD$hbRD8nK` Ɵ T„ r p8ZQyٙPn@$!KQQ΄P 3Ğ@UTcz"A4HjȲkx @UPˈMwJam.PvW99@d(%{+P@9 r'$(Ġ#DR)81 u) BTHPk&[3j@L mEQI*F0 _0DR*&i'@3g1p QTCD@nAT2&4ZB(B Ɇ@ȳMX"2 ) ,cb{sIVI Ae>|X T!tO@l$`ť PhT H`|/FȣNFOóvv;;;;;;;;;;vvS:uO ~=@A A PH" Wy"@$I0x#(%(}P0V ht['zwl(4@NECJ8w"f~4b(0 /?}f~C@tANY Pj0!@t&ܠ ?]=PPQ@$5:@%BUYs1( EPw]@ꀈ<P.I*T) Td(BN tδfħ'S"(q!d@0~@<!@0E ' )K'a0H$L ؀ '!b} >`x0Q1+Z?|+2MHJ wZT 5@u $G - h! e&%Eh8QJ8Xi AW^a.YCZ:-%R Jx9w!WTА0FU, jb3!@,?ؚülM:Fg)0A:_FPS oHR1Ixu|*HC$K#`%S S ‚0kӱ#LQB'NA,`bUq>Zu䀞#)!X4Aж(=J h (hw~%DJV0|$^}  @="0CH b % D3E Ғ3X9 ?.WBXO[JYb!_zu Yqr@A|Fa_TRBWW'nC60mQ>U\C>1G7hiTk+ "Z)ptS 08b paq zĮ橘Љ~@cgs':'e콗2\q&$k$ ""iNJdswM E}4GJH"V%מEF-YںFF Qs5K15 ,UXPdti f>o2He68Y.5Т f8&*ۍ@h44Qoj5FQ̀?@HX" 8-l$k&IN]$EE^\X8BW!EOGͯ Xc&0{П.IJFDZhl D6#Kgu*pg"hNmEum#@0$r WzUf렆VG` =@$٦tUU- AwCuJ(Hi!S- (Z*h)Q j RVI|4(%Jo2SNt%U@ (.]D`UO'E䜓bLI1%ϒbLILc Q|20`1:%!dQՉ1R%?n1+x<.IQ w:LƔUx׉E|)Jro, BJR,`!Al@Pp[ dbA iV(Ђs(BD'm' &Ij3`C@P !Be]?)Cŋ R @E&C Q LЖ^! `2 |jdjM&81ɀu#TWP P@$acjzɋU ,Dɍb@B1e:FTyť* i @D/I`Ig^VJ!H 7G  `ԅi ~:#Hĵ (& ?>JhC?-,^G?Ner?DDHOһEfVm[p9c@(PI#PBFG̒VE"|\xL -A-̀?mخͧo?yCy @bbG!)Ԁp.Ftֹ#?( d|+_dv.m2$)^ M )w+ s?ZSHANhih=]PG&E!74s/1"A<@M / LUP?Ŝo(Di^IN j2nlPFL4`EBAV*1PQ)Z.i$di .sD?.z@YV P FԕKbgiw :`TҖULΆA=\ F0 $!V$[?WW2;1ii">fX\!"'Jp;X2 b*20("%'͒ ]AP( J$h%v.-(@4@`T) !0@RAiQIE1ꠢU}8䘓"f\˙s.D̹"ǀpA!B J j$Nv(b PW!R*Paj(%5Aί/p8>+O@^` ĭO, ~BO!GzX< dXh^ b! `U͋99`~i!܆O3dZ2#̞ Qɂ!I chGBUv]dF1EQ:p9Nt& nZPKB\iB:P$(EtPfABdRipj5Qj4 |@DH(6Eİ$a֠/@Q-RĠ$ɈKR@xR !$cR1KMv (LgL) C;=3 up9P=P9f24T P< P Fn`PF(A~^7 P ijkCDQ:`G%1"[oۧOn=ZyV0P `!@B#Q)$T_Pq~7oRx@SwU-7i=b`~8 xINpH(}Z@_BX ea!Z‡5ea)ap4EpP P-ZOhK??$H+)PC YQhQC07NNGASp,\ $2Pd 288`0<&'c?` 0$7TL@Zv$ʢ364bX Dh~S,ިQA:Cj9K%(Iv ]> C - A'􁢭CZ G a 3P_{:׀{-7GSaC(ĖdqSnꇒQ >: Rf6 zp@8,t;=|>ᲃ&C H\S`a Ŋ@A4nZOl°&ɻz<2$V)C'ʏ@>.X9#0%"GK>֡7Q_Q[PDLBCEQT~MO" Q$ [" tA\,n2ZoY`C( PLQD P|*e0dFAq10`IB ZW1@N@TëG q<~ ;Ljp*OD  Dz$#aɹIPn4qJÒ6lF1DJ $<@!$W(CtQӦ}N;YNvv݇m;q / (~!L e!@Dٖ>RDO`1B0FI $IM}TS%&"uȇ o)_4Y Qh j?K"H*=9&0B0D2Mk^Y M>`App0B D Jip XATuF8)&u+;,VBbT*A /ɧ'u=#ǜD OڨQDŽ""|ET?'W |P($,WT41}9Gc6}'t^I9&$ė= PEs' J4AE EXdZpP-]5+A‚"zS_~tU_P_yWGf8[$?ېFNUVpؒ)'ψ@ G!PB*M= Xt"̨FIB"I/O/r: ,<#0F"@@HDKHpTXA!qu@a0 Cp= xL$@ 1x`} LϤ$+eZ:0̠V((cRR_xP)Ad e?D@2 F7&F"R H+T6)RT_l0[PNh . h!l RhKD>=;H6 4H @(MRk@5@5R!x^_YnSۧOn={t 3'8E`a$m;" x^N'" "Ax|fYl'Gwާz@@v,B1 ?y@j aA .8a(С3HaAEOj|pƦ/lbUzC#,6nJ h!&] k`&Q < I}d"͸J(A@ Vj p r!\%Ϡ U1c@LP#1M B@ F(sųZD91Hc6 "cQ *}A]`Gr.y<WԆu)邟G|!Hz"nlF7(@d/62b1pQAm@-PE+yK:`B_0L$ A@$ 0 TЦ qUUx44 yyb ~adByy0 `b\-=Z_0@ arQ?XJ7= pbp>dFhdJ@-{_D?4 1,hH/@`FA~4ѿ ͌Yl`Ў 0 (XGl4h}c`/y~B|.B/!`rC\m{=g ACRDG(Q]N p$(E'^=eΖ>XLC (d TA 1EPPJ  ,i9N@J5D[e bZdIUą - $jW@@ CHXգB4ϨlS\LpçOA4#jR',q +QwXLG^F 8GbJxa*Ta,C$CXAb!(ȎgȆ>]&0ġF(J4yh2q@@ A Q< 2h:A4_?\|HG7oT;x =tD AP#Bx#,*1?>D$\@?(Eʡjq~ii ;R5[E%ɓ^ht9p%v9j 0&$")l CM^K<ւf(K a#}`Q KG# &q?q MRU@)}feFU<㙃z=/N@H&2CXB LZn}0+d Nе-X`y'kn`i iNmو˘d5<(0X 0BnqPDMm<Ԁ:ҙwg-eA'h|53zY GYOf Z[h‰$D"/GP Ӂݭ%u×ŋ8 T_ΒE yv\} (A@൤7Q_&%aCD&,* ϔ{G / ق:It{ <1Ų?003U;䐏WȀ/1(ruT,0,HE@EBIDЪ!e;;F|ȥx-5$C}EābU@M`S/fAǩУ4PdR ٫*rd1R\xlaGU 7`2 * n9\ҽh('vC]8 C4|<(=5,,!я8ۃǫO:ҧ&:|nNdVUկuץD&ߋxCʕ hA4t0.ҫZ&3Z(dHVhvI J9 @0jPJZ0Pq. QAWG-ZPWֹ X C(GSJj,R":BqBjG(<:dT %%u#)CteKA]V-@MCw9($6h"(AVX>jҙ!/׻mg4`gJYa}kNgz^Dy8Vh K؄9y_kol$p_?q 2G$` @8F!'Np2<` S| _YZ, ONFt@I^m>@yKr5N!ˤHAtĜesI1X[~c \8C{H@JrfB%*Wo"is&@P i ]j EZR&vOCa)Ĭ^Q[J$+! BcJA T_l43O>8\\f/A%8 @>BrvxP q[0>b&P}?9,/]PLFs@[c֫F?|,a#m12q*H5 @@@gN:`>CO t0΀ v/7@] OZ +T0*VR?KL[ T> CXӘ/pz4q$4F$ Q_";H= [y$̎[}xͧ N=`3h ,x N W38ʜ d `D(H~ Ӱ ߰8Ѡ,5iYYL@R#ZEj@ ͭ0>B@zdS Q(? !*{ +\J@8g<$U*JjН 4 bCT @:l *0.5kG I)K IڔM|"|[fWZij]dd rk/` a(wb S( $__ v3 #;wlݳ}zxZtXh F5L%?'&ߏbf 1+ 4|$`Qq>Kʽ`@Dyw<@9TPVܶ@v@u DS[P  b0 4B%9 d }[[_0 8 <jAGAHև`3_`^]Ÿ0` A0)@(c33 +d!gqZ ު`˟/`~haG EG3#oݑ-Gp©FX*Q>:Nc` 7_ !E/@%)^9J,h~&Z9}T1ÑqTPȪl>"Ap`Th D%E)vV@7dH #DCpHz! C$Q@ QBB(Hj.wf>IMRYڨ@B A/EB"FF ABɈSVw/@@ LW|zm m6Ͷw;wlݳG`΀At.iwNr`"+JB7E 9$HS@_`9»cCp0|@(  )J1cAB)P]]*R-@?_WTAGQ"I䕝 (@=\| @P((8.tiIDyA09/zDt,BfATX. 2`T!K6cl6;;wd9eq% $8 Y@a ‰H Q#%Ʊ )#% &JN:tNmBk ^` FT/!Q"B/7@ RDRC(( 0  ̆DkJ~p܌@~G$ PPE*9\X(N;08N K ۂw B Rώ 19lZ2TAR K4pJ?ILZeH1|'(P )0EizX vV%PhM,d yydH6`bn\@\L@  Tg(NƈP Y YXQP@`=ffw@lY`cL !($v ѯ>ˀ,Wf Hx-PfIc`aɍ.*@ So+-Z@>QA B 0@SWhJ9hn]c0@:1re`Q%tyu-g r w*0,Ei4#I#3 +1%ϫۡ2m |q׈窸1]y\x>3@24`&dJ00AĒ*4m d '<X+ǔHr򢯎~麀sc o;*~rc,JOV@1%(zZd #9rFv}jmMlZb"Ûbl2ts `T _@B?7;, @[((%z;:>?)&^ٱ[HrݦޫsBw?cAsVl@ЉKqN~AP&H- K,Cy BD[*OP 4gӴMKjSaUV4XSd7 OA;38ydi Axڅ.4t 6\>hΧc#,s0٤fMg4JJ-@BIr`["N是|@ъ3cH'@4M%J@T+ME(Bh$UÀX= TA F5h:@(JCh 29C(-QB9 T3 +,bsE5"@Ev&J@u}+ZZ;j9VM8QA@`C8< ']Mw䓣g. `I4"Šӱ~A"tV#\#g:ޭoUHKkr@S3QD Zdba)_A"թ+_(l|>"R4<(+j@ |"L ̀5gx3SlF )$DHsX Ύ%b@ jF )dPzEBԤyL Qި@, <"@uŹ5 R'%L$(Aq(y&(Í JjOE 7$؛g`pƣ#S%KU,tkB)Bj R_,|TT;h23dLnnd$=\E g$Z RTHxODRRQ#F @Q- !5bBCni9"4B[SqaB(>YANЇ-jrG , R_DT%T_|;ڇa}mh0XdAl^D'V.*jm]k톘%"\ $Dj}mu4(s-W(!NI(@_ausF.D+4@"Pi A$Q!`R,8YhKzvRh|+iG:b1ZVIL 7- S!ŴtiI\N}$j)Q4 @P!!AH$SX@!UR:|HVbꤊJ`@C8}SOu]dxpsci* I0ʢ apHex JUSb> R4Vh"#@% PGhij6EI 6*d3D H09gձs 5G(bQӪm񣅑J(wʐa#* $:nx^n m @lH̞R1آMʻ9JʩNZ/p Ⱥ$F Z RaZG,!9U(Bp UH2U6b!E+2.wVHHK!Խ "`cOx #f@!I("\$\A ҴP>=P -P#|$C?"ڿr %CS:5{)"jaE'gA(JHTh=Ia \VN"SZ[/!P@(@ Ddn,7I$Y.i- +rdBe@O"R)ƾXǍhuS5əPt7y :3 vڗyCؐ|C]n"ʠ)(=@I(q ')`$J‹+$5 ' t`4 (Qԉ]'ħ]4V`9R"#*ZE2o |Al *y? yvF@(OC $ # ްy΀H 4Ėt=>$ýBlP44A=B A?,zm% 1!K~^?,۴Ʈ<g !Ä!K̅C+`J?@TPf8}i7OPS?(!8 )}# @ /\f ǺD$jw &m =0 d2 (z⅔ @"3F y:!2%)@(Q( " 0I  *\>L B-$)@":}GF t ";4P'#b@gqL,=kjy!6XAIcf8.0Bpf}n ` C퀈ǺAv4)g}j2[ѳ) 9K?V`s9aH8؞ ]gŚtWG CAHl,0(1薒(FR7M/+Z/=&%5lFZ5+$\vL@˭µXi_?#UAd@xxM?(Ap>`5@fr{SÂ˞$^Dp zxR||䌋OZ$($0X8 ;^OR Ƙ ET? M_JT !HQRNHhDZPVEN?Z{:GzqPH9,I&Dc 2@ ;Zz{R_b!XDH\_帏vu,o@d 6ހr31a!TOabC$#d送!>(xjz|0:"tX҃)*0 G"i`HGDIN cK`$x1|jb+e)Bp_B>EAAR4Tq(AZH"qJ 4@)g (} (Pk(?U ce P%hQrSAL. @0AI 8 ^Z!xncߟ  ;on 4'^<B@x,*0 s!PZwԕAY-lV@Q3=T4> O ˅aIY 0QC Cp YT pUipPkKlXWi۸p>Q"5\blŒyQ0B j^2HT,A`{7ZԠ|x/)] P/ YTyu-6a$C rD$= ` !(\πA{@*(C@+JH, X+J-h(z4P}A |9I!*$xЕ'E47aN9UA)`e{ɁÙB#w1, TCbrAOP}""4_0ut%,&c@s "8hCttX $z^!MH<@:Xč06R"N(GM$@QAOM:MBw<@mAd(rH|Y!@ z"tC)Cל!ey bbIU%*10 (\ T#?- 3PǗ  <@9^BO<EmD?p`Dsb ; !yZNL  *a eFzQb1@? PX&tfР2+ F 9==p7B vJcU Pm A0&Ry0?h2$ w ># ]:GiyB*~vqO!B? {͏x#( ج fU +aOth4-gIFL?.`G W 0U PBi@Q?K"cՐ'n"Ys<"sF+|\+Wwv2?j@+IyP$5g *@#;"2Ec€#K@Wc##^K}⠎~ J'Zx s@%@ z< (^6p zBH.(Pt P@s(dɤLCH΄-Z@Q`J|#BqHMB}9w(P]N^Ǣ( XC"F'Q!PAgy-UFٹB0 nJ#K)|LԘ,_@5RuƘ+1ql\JA6g=m؉T1",Hb@Bt~NPA/!"HLL@$D8D6A T@=@h +$5Hj+A -DǓGHjj5@Q'p9G\Hb A8hZ7B MW~$SQ}p@R)!mE߷+< ˀ"E#G1 tW9 0s#@%FaKH8 qDh-"ar$(nzHPZ`_K.FD H3rdBzrl@LVdwL<H&A &"aFdQrI>Uо~`գ e ZR0PLyƒ) 3@ zDO$B$I$៝A?E#@PJ6MO!ܚmJ .  KLc ~FG b\IJ Ze?K[j1x @ \*dcv`?@h€¨ᰆss0ŀ@Q iG~1Q(h) cqcGԎ$b!~(A5Lm8@i !)ñr  t?@./@t\`Jev/!sho ­B$%ЦP*ų_`,PVӾ[)aZH4X@Z `q 7HGxPm q_61l яhF(la}ckhl7K4>EW 5!x8z4mbxM 5E+! F'#Cj!!!!0PQ  (aa/7߄aKxSc)3a~SȌS̸@ b{X#}~O@i3z@V)FR֘i!tM=:Q G1tCH``4`%O:-v Hk3O*?$@B~H44 sP)D~C"P(c`ؠ2#,0F\%(fvx݉0km*"Q?ϓim0s>U:H/\LA 2 7~f7 8L@ߐ !<^B #t  +;XQy"NXZ(4Y;<P$p<ѪVj6!1oq@" 0Rb/ |b/6} O" % p 2ȏ}BSx*(0ZS9@`B-,+e\@;zp&nZЎB0# NXjAB¨-CCRzѭ ,y Y1R TD r hHP +6)O^IUy܍@(Q,ς(*00Z h4P7(8`$.&AHL Y3ЋGa~C J& m?)˄!T"1yk"k:q)#BҤ0`p+F`BX1=&!Hej  0xyL1E*IH&2I̒DTQ0?%QPJáb= EG]>> > N+P } {ާU" IQ5"+|P7X)k$h̅CAxXK„Pq'd<ՌR|{wSܨ4tpC:TT Dտ7ʺ WS\ 3p@hoтfT ;XzaDF;Vl`0e W Ѕƞ%IY^dYhSh4T"J*XU*B(.M$(hY HXM!#AFC(hƌ~p*n(Ez.Ұ0A׮A[" %<MHH~1}`h:z8 !z$LJWR@Mn G.zZ\J@ Z=PGZIK@ HA4ABbLF_o>MS% lrwUA%1B ?r~ 1Cp^Sɉ&z2H@Aϲ}o EwNp5+QQA#XIQ-/ Hvˆ@HAp&"yihLր%7ʀT?F 44Q[ LD5tBX`S-Ԫ(HBP5>H=+0 @UD?C q+PADFF>9b |(@xXTiT~ЌL:5/:dޱ rDFN0Ę04 FRO .rK"̑"Im߆ժcTbB*$JV~M uY 'VD*2T,&CXbN 26y\"Z (S2g YwU4x,(- CE"xnEE62gA&KJ228kPa&@VR`T ӇK(,UO ԋ:8>RVf S~4*/D 41(M2_MAL3?#G8c@-iJ+-_r8Cɴ % t &4ǖ!y wU\K|%$B/#ȡp($haQ!YKrrBQ U_4 @`E eg@ d %R0X4v$$CPN=xX yc)EGhPH$2TJ$I4@ )T9"r(q  :AH4@He8 PRR@3S) Q(#E! PG, ("C x; Pϑ,@@mBzpGw@ػqK7.1,1бh "9V@0)"/`@Oe  p~jQ2CGˆhq@5(TqZ/4 J0փl?FH!C 8v3*. Zuߤ6A~RzPE_*}$;1HB7:xlgƀ 6@ci(ųĉ \ &H&2^:^8rI )pUp?/\ 'Iih0󁯨wtjPCCQ2%!!?efbR`*Ԛ""j_bʄ2 ZaS?4+L 0 c#YJ 4&A6)vQ8g'eYvF|-H8CǺ~0@t9GEJDiǠ&78F}Ҡ G `Bl#BހQGi#D#Nq J#bgjqJP 6^CB* mX;2@5@d4b$Sހӿ̉ o`Q:aQq A91$[3["َH ŤQV?0`I h8 J%~Y(&$&7}hCZUP*?h7‘ƺ! Cx$#t"y.AEX:&n$8V1#5`F⹡@m9A7+@A) ̀<id">69S`&2օƦt&PE,B)(RB^4P^TUnO5ͱ"cɳ&ҐAS:J:FnNP† Xd@ (OIY WP_QMAjTBv UJU#=p98=ގ‰ `n!hܛB] _`;cgPWQG$0@@@E*ǔe)"4RyybŋThti@]%)d#*@((80$PH )IU]\A$*Nky,@=d"N W_?S X :D HO[Ǜ>0 qp\hLbCŃhI2*y ܰ,A`$ #@Ag] *<I-x0DrK!<""+.@p!;NdT @h,JΩKyYS@8V2R?P8IPCV5fPCU]Q[|+?lN?iȧ4'8` S?݄`cvNLQ 0q EgNF\JJ G0v#IE;QLJ( pWq; #| hxBTFD 5aO˜;(bPDBMb %r* ir_s: aK.VN")Pj14B$*HQЛPJU@6J"A l[()@(*::P$@_WBQ/vłn]h;G GFV P&x̙\1?)i  HI1GQ!]JPZ@5/ABl ^OBL/!.s^p,Fj=! {9(@!"ňJ)BnRR`2KCYVP{Eh#-cڢX(9b0>-A ?N!`o~ v偯R1QBKAV%WbTR1bxQ' X#!{,DDT1#šL @]EVo!U7&\~%&r6< )1v JC JZ#w䬠 !ι!+a/y^svohB5ED]9~%Q*2̕Qk30U/P$ V b_}VR`D? W%:,aETrZ" S Ta VJ 1E$BE"  1c@0DQQ(Q&AgY@ehb JgӘBOJ0R֤BQaD (1$a84V  :$H1"A`z,GP(}BxnIb7ؕ *X1S-8Ua7 sr+QJئLh냸ҁ6"5 pE֔$ Z(Êr-C=JDcD-!]0!ij^,+s]AcjGBD&ƏP/E}** b$dr9? ~c U V#%⨧ (q#G HYL-yz_OY,#:b{MP傺ȌF@| 0KH vFԆ0#uPRVhduGQ )UC]C{4BA"ʌ4(bX>L)"]9I‡*v<HeATbTx $QJ1Ϝ+˦F+X⥋^|ʀQ|pv=*eXqk ¢^0I/ԬH8 @"4q@щ'FJo|2"JJdJ[oKH^ыnW( "."iE;_($]-RrP@eT5 24C#P Mg@]HdW ԖS\U,y+h-d~0 @5U[PA h #CQ4H@DOi`B娇{$D$-*< .Vؘ|J ?m]f>:Eo/uD+u%po1zR(qt^C,`1 SHp&~l SJ*12hIr_N?CmQ@(­#eUۺ0̞S`9נ TWV4s]8LۣKpNXXw1$ s_lq(ӮɈ#N`gN+r88‚I4ߜJq!WDR;ƔaH@W|a[TbGOš`o(,Bkp,3zeaQl H~cx$3 oUɤa ~I9g*Q w}a8`}'^*Hf@ }>P< a6"&D5. Y ňAՊ!8IUAX4="bS~Y~; FD($U#̆(AJb UJ(pM`UH'EKPAzXc ,[?s 9 STj)"b֍\0iRтC 9H,e(@2 zLퟞpL`TlE=i6*%a0d aX00*˃Cf dO#%Xpc 6M**V}_MiirAQQu01(`sCqD$r0 !Z-AL`hh@F2+R8zxu_^$C|?$ 5I2˔K#!iK2g$ CQp&B @\PTWb'ʈ (- $Gz! =` 2pc?L[z ȑ~ 0x##ɐ|x9p6@,WXt藈 To :=? H$= N PqL@K\VEh$1eF "5(A "8;HIa0(״X]vp"Az=@he/d_Cl\R8e -paO(CR ̘ s'px : W$|?S/a  ^Â)!@+0h0ʰSkEBjB? }~y|*! V" E" EBkBEr(gN!SSyKG4Fn%8d_Pj ̈ yPEr4K3hKwMI?Ѹ5'p7 [9sP]9˷ |Ȱ`W[>Q@B*@+>c ju,6x `,@2k$iOHz )U )6G0õ'Vm#|? 7/-ST.Ly! &Y!f>!,9ڕ?Šƛ(ߍ0TH5A4ap G1,w_8yh'nE,`TuIQ|0d0|Pgǀ' 1R)E HH UP &> " yNF `!$RHE*|n!!!!!Ogm!Z \UA & Gʨ$ht"J+9m>X k 1[LSO@( +P"u&$FJ[`@YL,m#  Y`1r9YpwLZ>sAk3C,2`$i  @ t)H5">VN^BDAAA1 z AH P tqf/G:tT=/~n A]rY VI !Ei D.˿B ߏ5@$S7av@I1.z9/T\p, r'qsT))MDq j"~H0{$629wf$l @+`3 ,|XK,!G1G`1siCCP.TChCJ} 45uqꖐ3Y-$ X a+y AHd $|zzgaJ Fʪ]BA'd< Hjd9A fHB"` A ɥw(@XSǢϒ+FD Dt]H$B>X( 'XO@ PD@> =C1,>g ^\ @4F%<ҘԬDFbB餰P"0P!pShJr!RƸu]X0! q @ťN?hqR? ,bK<$P `X@aL` "HZh~ŵ8x8aL | D8 \ F/  "D3Fxe$UꨔhNd (: 9it(@v@*GQR_AIeN,ד J"fx$:!R@g K|0CAA_ P` FupBWA R U0H|GHQ% +'Sۄ=G&@?6K;o&ri@ص1_xQ@\Ɵ(7SX#0l} B 0!H,8ARޟBdHYpZa‚(\ػ0 @w(?$ /f6Ux @' C< D8B\5 W,x( z&'  R@0R SQLL3l2LOz CAĥ (dR?4s֡I] EhA„3"w;ŠdqR,b0WJZ(o =i#6exFXB k4 +'D1(n~'5D$X5pGtH& [ Fb@" 918B#P/?O!styW#xcP!gUf{-0ä"$G(DLDt.Z@¯_gȋQJ#HVy D&ށ8i2bάgM' 4zBz]M& $hpe~&GALiD)xR6@} 8 H1r \$IvQm;*zC 9 0TB( @$ dc FC!XEz^:ـNG-kgL23C*M 쎏o7Ԑ\h ׿ YVu!\@`X !O;dIAYCC@U'܋ (Ae4RB42*@1PP84!ļ.Q1Vz82$R  ~%TE! -U@HZFӗu3ZBA6XM,CKR/Bh4AM_0aZBz ƨά9(:MQLVs%hЖFX}芇 t!)dCMyt A *|X7cU?*VU@nV^j(h;taU?‡ٰ! F]0^V8 6!bݤE? )H<(NfH` plB=!"?"" ܀/ILh8v JH05 - ly(BĠ` e(@`*$W`)v mMZ% ŒGSG b@.OhMO f] -*썢 $jl sGh ނ\w=]@4@`|C/ G)AL? >_X3h4C: h %L0( Q713vupTUD3j؂!kb "ǐ(k7S *[XA'5K<289;3)Wα MF.<!KZ*ҳsX $V$*Q*ViD3(2CDrh $BKA5 }<_)^ b+CЁuU!ږFj yc1%n=$U%D;ZD4!4D(eOa@bFEȔ`l& mg^!TUE#3P-~сtAypAJUNuG\? * Z2Qw0S[BPq20l\cZ%b$(B AB%"le GP9 GZd/(J!Iq*KT!^yu9+O5SS.|*;_@шU R&TA 1Zc$!ǜb0 [$Q+W $A(9JB (.*!J8 1DL8,y 4 6Q!2ȎDK􍆔(BBgI q%(X"3M!#Q `Fp@l(4+ B@h`)ԃHE HxA tl%䌡ePDc)JЌ҈H4UAlv0TVrkG[!|I@Yܤ傴iQv=.#TaDDvjMjR1@K* d!J` X(VJo!60%QL*;3d\i'dNM-UBP&*# &TFP_CaC W CU"()?6=1=\ʱFQI2lӝ&Zcϋ;Pч$HsUT~4 !(Py +4Y-?BET, yiP骴FPa3Z%(B}꾑XaJڕkl2V It~^|9$Q!O`H>3@P"AG0(A*j٦ b6A#L5 AՀdT)GTG8j!&aF@2xX@ʤ :B JT)A`ht|T $b@"X,,$|8 **,%HB S( Sa>O _* h%l*??bO1$ : #/t 5_~B C`f/FH-D#2HEX}o?lS0? (jд$b [A# FT^D_@Q:5$CB©J8]𩀬M$MAE xQÒ2G>O< ,d4 $nV;bd4G8',GNJހ@Ë ^@Oo;179v#\)$$ mGa40WPp0Qwq_ Q.\y* %VX`l> \0`#ДN^i|r_,9V?'i@21eTicF#E(wQ Ezғs33 "!UuR#?@@`~@^#l CUAR *=$M(Aj/#Gt%90@D2(JT 8cTZ4 B=˦Ut;Y!x\QW.CVnTkSc Z N@f$؀ 8,H8TPtRcX(! ŐñRdαQ<)/.W)r $/U;B"nDU (2 ,G#%R!! @+:~@0N!G51pQŒ(A" U]c`1O98}@ `yHZ5JAn8 B(V#$2 !vQ @DXDdz@DJ{)S%c)@rp)<+ʵoג Tu tVL:WtT j-1x  "b;0R0Q b(`Ӕ"z  {CEXI),R?|ULBaBF+LxgG"P`8i-(K|ٔUH_o36(}6FX D> ":Rz 'jh@iHǤPR]OEt sy$6bXb *C&5 $2Ux&tQRRrnAhRY!$p\A%AtXqv`c-5(zd,:O J hH?@* &#Aĩ-4q:!c4bJCRrzWtHV!"ԩ!{*($fA̕.RV:@ %A@QJ! dX;01 S|Xpv/З[k/.c`8qINGS,dZ2^yDɧ^j9clr@( $BD`i+B% pr @t4 o4S%beykx_q e. CG\0 D@8Pm z $  p&/[)1(H @QX/GHKD: C.-TRD! &D2(9Qa4#$4R`lLBM]$"B/ׯh!ICR.lĵ8^Uz9pqɔM Q"2,ZHʢg-ZlF^ ::nNYWI7}o`X!iZtP8.t! EP<@٠DAC(T UIH?A-Zb4<ʡCa&)vH˽nPM=Cnl-r9v0><ApD@E 0$@DRVegh X CNXDxn)f#"R .\$*axD 89ژ o>*UhYv$ 3Ì`]U0$ GNi*,R⃐W)JXPV H} :ꪔקŦ!]&h!:bB#STo7‰ n bk˚HT$3D T pQbTe GHţDL`D "!DaűL Kh`) @M4IQR HE,$PzH $q@ R 2(fáT (FhN Zu箜!r/ 6z<]hzRs ,̆DFOX`lg`2o(HC QkXkH6PdT@LB^ LGU%3K+N ^lS0U0]h(=q6@h!PѤ,(QTB$Ic@E -(@46ȝ .@ @68">a! @tX"gԛH bEA*P2IEADL+83$i @s24P8!XFfu_O]zu:zJrjP4V<<ބt_.$OG 5WX*4\WTU`h1Zf”5jCٴ3CHRyj܇u P/iDf˭qͫz Pw1eM%R/%vKfUt"r|Q h&p!s@!@4C0F!LL١爃l̼hlB!# ☂ D|'A>@o  B!X/j@5%FJ"S;%"4gdb`z)A`{),xEg`MBдV.@BhUQ,Hi@4q#5en@B/  @A?>hx-D단ҏ'FUA!K0r$'RT#aWW؇d D!I@oHt̂G!pK8A-b"MDGzEʿ04Sz&(L=@JVq R%^bH'hSV h (T2$@6 !Dh\*Q %aR4R0B\@JfEV!"qhĂqNх ui/@EŊ$4ՏTh{ge,dH.Gx#1R)R,G5 Iy+E5s(kb9։stw=l%K5 ի[@G6l:(h qA@FJBzQ1"pHLrCFLD:r% aHkLe$W>`6SBxGxY_R\& `)`@'QKMcAZF[y&]ɻ7)i SBjV(v-+XK[ֶJՁȯ1( fA@Pjj : >R*쿢" R5Ȼ:8B|A+x:#gQ!_˶Q(]QU/ԋ$'ΓPpj%kݣn i%h ŢZ|8 z=F[ MEEg-B9GpX@QK|kXK?i-H*4 H( HE   JBj[@4,"EXȭfQ"B4Tu7!|Th"$ F'.:~ RvPl W?}U':.ԟG˯CgѸ2uxpiٰ)@Q- pb71P! ء=c0(wGpǟ ? !"#IX)Й-5vH6.Nxk Q6bRR1x1ꕉ~EuB@C C4 WAY{_$S4` (Ռ: Wzބ [BV)gdaZc2K[ ōAk5pejҥT$hF'ձc%ȹyd%P]*!ꔨ{DžQ-P0M2 I(3r(0Wp61-y9ʻ]pE/{> aD_f.=0i=7i˓k=')~&襡v]"HJ B^iR+B9DBH'(mQvdB(JiLst)s47`,yp%1EYQE=V#5.D`(ʢ\V^K AХX9DV=^A `B<hf;{FA7 d# !bfkX!bQӰY"A$(‚X!L4j*V4@P!HA$IPb $BAdiĊw.SCXhI %h!YQc0(Qd1嫑!nÆFƄƣ@i|j$*e$F$ QceMPO$V@h~($~;xavĐ/fBGQ"g3C؛& H<C8N 8 ,@ @8Ro` 8үcHWͤ<0sV|f(4.&0h@58`IA G!u0= E (2 Aai :PZ~]5߈5^`qgZT-p5Y1Rח-SFKN/}9 >)zr `=ӁM0fw t B&!@!P`o1mPaW bq* , %LD"%lK`,ߜ@" Z@ ( %J"UsUDPoV1*™SHQ_A&ϥHc f P~8dvs1_kOislAif `N J@T҅%銟 )2n&/HRz$Șcm"z44hbd .* b*K r!Sg $#$uKʲ\Ir K⑎5ƛ`F1'^q8,(D%A`iI ST Py -@RZ/W&3 RH%@LT!M:QZ:$&(bB A@5q$I7UͼDYckQK =7 "B<D$k+"+W5ﰿW#raC?S1,4(%rg BSB;lC@e^i>&yn`23@vA\Zgr QV7@@?Br-YJ 2 } (NU@ h]6]>@0H:-MFLe- GJ@^~F@A 8d$=&N-?JLD!D`/@hqvR@8?*`5}jcH($v 5SQ E*>H@vAbp'| aABpnA%B(-j (%!@YWB P@Pm*I@["Z`}L ''l@4P|EIvRPp#DIg95R4 0(.U==E8J?P~9 4Kǥ]3 a!$:śzJ_$nC ӰB rd=J`7  FADA`aF#BZ#,kt*Ki|@k.qFh% CZ$upi\m4 bAG}F$t @6L5|!-ڿ#5撃w^I}jR!.TWdrna8K)*6X/ ĢGDXTb#d@B NXS q"zBaQ8zɤ(@)Hyā2!036 d+A@]9!H":cV݃U]s4+ 1 ǐ-8Ât@Ll)o?!QNL]cW q0)q4yyr n4%N*俯o@Mm =4;ZlQK-k[Y fZGhqb0C@$ 2(ș> /t0 K 0`I*`gKiTE t0y8BE9*8CL4:IXH@Ҍ  " zH3Jh}ر8sTFJ_* m[YHAHAeAD!HN@Щ h̀ W:+F)H`;UG221@JR1JKkm7Pf|.t́5 |M Жztp9@h&4(F}F(V@SA4N.&4SRIƃ$GB tH!A%B4,JRmX@V,X*0:@4f T BBzQ -@d@UAdn"BR@ZD6LQ@DjD*DJ@X= O"CcI2`5P\AOAy35P &-(J:@ JC*`$xP'Z7?PA@͟S@PYAD(˽6@;D6(OA Hjȁ @$@LZ 9HH;XFg y!2 L FH0Kv0)/ .(15T5G X{0?60 A;,bA .G| j'@ &j ©:@ (6}OhH @ q *K]Hӽd2_H#XU$whۑr 6 W@qVtX0G$DEAJ;bZD(B JF0  Tp %k݄W I2FnQ\AG D4k=!d|CuC#Aq8AkI(;9$&Ld،Nu#Rb~HYW"+&@W3D$$A.4 V" l1 q;jq V&39#fF$+{T8Ŋ R1/)yÊBT"TR8; W=rZ2GXb(5kWaiDVF$*;ƊƊV.*p!GPp&>¡(@ҘHbG(.o4(0"}cF!Р;L|),H! NKxd CyS@\ǠJgP CA$.-t"߯$e6 be#a*2IZnKfTDqȦxjÆ^-Y.% )IhGD"X*8G bXE!*btwVMc̱|X.$av" ;Ic^[䱚2: U%d J$cAi,Y*UX#n?-ң8E(QM7:_ؚ*Ğc4\qt̕XZ8\#F 3(Ni-ax Q+FPEֆ1t4N/K &vc? 2Q\쉄2@T!djFH p yvA`"S+ȆR}JNzBH0@ h䂃A vfb4x~Fq 2z4U '0!ȡ.%ƒ+ABժ@\h# ,?{˓7%g)HKf#H1,#mׅ4FC!Y- f߆I&"eC1@@a 1ɐ!baC5X3h}xFd# scp\AR#@ zUO w]܄j?\4v'9A2&/ѢE& f9]r#ʻ m $rZ5"m (a(b dPx<#Y:y#IU*c ") Q4k hr44 QH,ye4\/ @LV`(,Q M!\BdJPPAխKr 8w@HRCHc% Ak1ubpa`Nc5Ueu;JgV&hΚBHt$B)PMqG*00QJ(H1(@iDAB)K򎘬V(2WKraZCiU4B+*Ie br%$l3 2D) .v] lU h e4k4Y@0,A厂_@HSJP5̾]ӤE`B "UJ1kM  jhREDXTQ1BcZ$PBϐk9czR4ϐSjYXH,I!2#S88DF K0%A+BFJ\y`$CbA &P@xT-/]BI%5 #4#TH,ADDTє.jo٢P&J`(qYp6L"t|}aPdt#J  ERU"uqRc;\Pŋ1-^tcJP*4Pfj F9բQC(ҖV0Frg^~GhTBH ;GWhE 1` ](I (] o}DۄĢ$Wz>RD7#X8"O9hf7܇7R$bQ _ (8`()xP F Py(!1@hZB+X  )]""Sv+A(^?׮"y\$yy $|#&""B1mtݖB ji.1kJ.H'Lϛ0D@8#lA UB)qT@x @!PРGnXd:1?(q]S8Caok Z+jc!b@rE@e&-R*M :H4&v0DH@7!\n tPjtE#XHŪ:ӻ;v|wrDtj|6烋5ԫreDNS@lL褪  E? PЫRh,1@M)2B@4Ji %&FQlv)Q M6x ֘o'<#ջ搢:\%+E6%-QD~g r;Tb9ʫaAqO#1*Un%;K"U& 2P4^nXɁQ`  E & i6E:+/,tt:: BE7/HxgpBsjyqYܘL;mVÔCL(@91G@?KVmntt  m 5S3SP`Kju Ÿ@ H J}h* GHC/.F 4{(,IHKɩa^C^֕ϖ+G+ B W_B 1F(ٝbyW D c=]M0a9"+N N,EFY9iHR?g 2| *ФUu#'`r`<D<@5BAp/@b\[ d7usxt-nPsh`6ߧ]>A􅨜 H" 2b""Ł2e$Ġm-UK)1DQR3a5-jDHWngZnj!V#p#D)C/:_VҦeǓq1* (B28C AdtH^UPeRq+LAtd) FS-XZ<9.4Z'0Mӫ 0 Ab(*S jƎ@EaU$@ ꔡRoS`t"PJ2@(: CSIHvE 1A,Kv5 -Av-U\ *hUuu< q%(AC(-CСar1BgC1A(>@ACEqӒa qrAJͧ]Z8Sġ(`:t  @ hĜLAp!uZ$_0HPpd(%/jR@sqS1$D+HvFh1MMV(@8\QnƊW9QG:?X0  @ D>3G308A䴯E|P((%AR朣x&7 9rqST%G]*K$;zQ$ nA"EQR, QP6@kAq'py"!ŽA! ]:&l,.@CJzT<&DJ(P@(t%!!p~% 4B~H5C(a@VS[ _ BAIUF |s`eNY(,AYܢ˜NTR? lC+1R  ,BΕb! ej[ZՂHB({MC^ hv.VeAT'ٓts]S3KDfjX  ( rׯ_UI"D կ ,xoP{lqMd7|i@rgI"܎~׫*wkB:1hXij3: ?<UTœ @J-(A LZ&U!m-5+hwZCB1f w|/H\b;H. )Pp qCI%#Jc!ZR%E*tB_8p(ICLda@6KR4bX2JB:P+MV:HVJ` $@BsHZ05W7R% GVxis8!,G$$]=.1"`>I  i,i,AXKF ԉI``j@h4AHYbaVaJ<̑F@$_4@qopq4+IΨN{qBĂ 05pM7LW3~FsF(HľqXQ#ԴC9%qꊬaňl!gJBVKT1F}LqР x>:!#_XZH!_5@#?7@̓ [lexޠ]@Bh(e-/U8ԌORI( (Z:"7UbAZ@ 5@i]q#+ !nk9NCoCU0A`DŽEs+&D*:Ox31tVWB (WHPXhQY+C.pHK#߀,15_k:,%~_ 2N% VqBlT[r jB\ ZT!POK-mAWxHe"!Py EdơG4 L\R@ ?6P<h/LFMT r $=]vmʿӂ`<6O,A$A X@b4B%|S3D; g86 E PIj J>#CWI+ 1S@.a(,?d>U~OѼk40 (07)XH!*^@z&L!K7(^PfꁠR[8T)cD+3,$Q)!ֿȐK*:EHA!C*Q* nsbLr*AT&_ 2@nNrbBK%0_̫zz",=-*sq3<2S™"ÁӨiWk2i >oPmG ;C ?{ P`PFל, 5.M\ȝI-؋E[ϊ 5Oa  ʣ,\PÄ(H]B  _$@FBvF,qmH ,w@N(B1PI]Pvv!} :A$D݁(@ J`q(- H X J@q*2JUS%LT xdg!B AA I!: !^H\9wP˒-?1H;GѣbG6"/y !u(x(\W K_pqBwgR@jewAƔ,N,%U;@fѐ(EE(a`F\ hfD(OC/a}~hy¥K*3:2bQ L8CՒKGi+ G B]/hg")N)!h+[HdAaV- LH AĖ |1B:_rU[p-(xdZ`d~Rd|AHJ,cO(4 _i<K2{|&!KG_BsЩRKP,Hur bLA pд0Y-$ =@=pPQ\jZX2? 9 1 R'O@QJx2%7[uJAftqDE5'PL%kU"{w N\(hgvXjhBe$4~<0!o rQ OQYn $zHpRd $yr)% B J:B>T399gPCVЂ-  K|K`Lh@P0VY9k# If@ @R+ r^HfW\),NPv+ "c F;F|tɜP. 53šasT$dE$bk`Cr!PA aJ|%KVzT9+#E+A]h6U)p8b;H;lHNB+Ph dbgeⴄ]|F!}81dA0> /B贚9ljPay@-ez$ IFZҢzd[ 3sT$ʷdU,QM]XJEV<OH,"L^i@5V$8<4TdR(( Mq^H(JDA(y 7hA@A UJ Pb  PH Ti(*2$[UV !_.+D/h+4Q5.w ='_Zr/<"#gF<\iUs1+HM9Acя==lñ(MVPgjV)p}bs|@>  (k[KGy'E&J)d`[I-PgEIxJd,JCG/kkߝME*3U5 }/ OP^V((6L4!@r:THaEPhm 4cBZEe0ĭ(=PCA@:_MA0h5ttւ+RQ+ڵTpGxT|N C DACAxP6~*ј"|XpEx8R'!c9Ad"wDڰooojʆI#h@a)zy" ("dG$y^#ULzjJ2oB 3#M 0ބQ. AA;JHf!zag*TM!grHHT>zN$B8A*荬 "!TPE%$4}(@#Nl +K}JDɹ]_ 09O °"`Dr V{":W†do )>zDO@v]= Z]i", UN)hqY"!/bbM1LQ܁-1 "2&R"05BA^(\R Bݿ{e7 v(fRd)>$ WzHM+fR"0,5)gEY`DIEOX㲌< 80R zN>q%q i,?G c_ e7e_Q\xU3D";׮P .t)!STsrD%Bc(aiAn$% rBP p"1aI:5/)XƣP,U]j,JnӤYQ}/R H9F<!,"\1 ҍkh 0*< khx`S1DM jП/< "!o Q3$ Ogg#H- G 8WL JJD&Է򎽂gJ 2RWQX``)G"b+m춈E &48@d`L:GQLmj[\~0YǑm@p)J"wئ̺ǐ1ȄbJ:yjgPPVգEwI-(J}4+ʝNLRHD%)E/s  *ϳj5*d] hDd1, %w".pW $Jj0 @i тF" ƯҚ)'dy Ў?LT!~:$hJB4bЎ@j*sadV0*DR刅Hb`t^}X'@gExwwt45w*@I52T0#.(Ѧ` GJ="r-.&EC~FjJ@ 1ZP9bRC#R0͋HWDӒbbƚ:4)V QQZ(]t)5i7!Tbxtlx T.jrPǓ[, (g&[$2PҌхDsdhhU?ɐ8*q>Fux]x% \##p.MMO Q*܇deA"Sn)\Y̼26%Ghf =\щCO+(#̐NÙQ)>iV(Un|A6RMbhn>[^*,!&bW4 1^8#za1B 3`pV-* `\s}B9dfL#1xZ ga !'(O"46"m|/@:JAA7Jd'b!^Z@0R$@Xg  -YY ~ZEiV<4 5 'UZH!Bi*y0kkCʇXe5wHȌf.,|+ơ+|-2P̋&%H"Kk2pfkp 17wZ @` ):D% XRDְ(JM)Lf38fxgN8+JD%(ybDc¶BҪjMP ),$e0S`%А&m-7$<{jz9-bY-YR0is7˘+ h50YZ?Y"T-~ _:_7#fb  IxG"K(' !`e(E'JFOv Nf}CE $PKQPjzщa $ $bD8qkG?(@@MYx&`c0 ߨ9wC'yIp֠+K L? F4 BY Y $_2H rp?‚zC@#8@@D @9N” '`c@P -XAd$vUAj~F$!nw.r, Hw:L#_Yf!;f!(h$$ QphPe)"4V !&}ɂJ.rZI0'j*JR m+G!֊ R(\>QLiE܀HI.  L 5bq Q*̌~))$S ~h= _&@(wdX0T1H R Y@cD@M'+J @]@TM:P`tPaH2DIeQNPЊWʱ^<Q`S[JWPX#j$-~ q&D(a$q li0 b #ǰ EkVP:zHaGP 1P{YlwhEW4 = AܐJ@CE_Lb q M4 r`MSJ7,@ C4P 44k GRX,1^  b H$% TŌݫ6~'嬒X U,'UJp> EB4#acc$Pm PA*ІMj!BH[\BZ#hz mD%CE rSs Hge0+H~b=_ޑkqY TU;<`_zD9$QAOJX"NPyAp*DG͈[F+`D/Mz1m}fAD p[KU _%1EKgKL$ytJbhZcO) ;HǠc~'.YI;B0ΎVp*+ZtɪqDEtѢ;@c @]HZ+,jPP7L("PhG&;$,tz` !Q:IvxIy@j09U R R h%A R Ph BFH6 3B4C֎,6 Qj(j3IumkF\O*Lb.B>*wuHYMJU?i )Ef$2L$j1 dcH\ $KxYi9 HɦfS ?ՠh)Ҕ;+  ӫSBDLQ>DO" \qH 7D Ăj]9wvBh}B`B.F>E FWț $)JdQ ?ԥ@<8T7WԿ'Z݉̚Jdk%2IjL"H۬ES@y:@`(yEJH_S0P*KP 8t" -+Y\AOAQY'GqZl6_[P,[,zm !Rf `@ r ʦy@,HXE"$ &ӁŔ$. ddY J$GƠ b=l |  ,kXFS0̌3cTjc;1W#F%hH"C.(q!00Ae40ILJ$XKJq#L):HOUβ- Pa&!z8jcHbHΘ Odsg㌔Tw&,(IOw`4KreH5 zi:JGF(2HV QZu? Bp@ʡ ]0A&~ )&;G/T1 :P(Lf{&L2s¥ҏ ,&uEtB|jѦHi1N5P1$5gh3##$}=@MR]x]V PCKxGP![nvh/,FD"]g{:!G 2PKby !CJ 41Y0!T *1`+*g$` ,<$D?wo<(Q@ G 0dm2i b0c uڠ'Ggh 3U F  @4ED1Xiԯ I,4Y͐E_44ZI?А*,1 R,XDҥnl<:lW <( !d$P'4Ag~eZ^ʣ[,i1$Ua%B5ADo:O< &xV.N9HA]N`l6 ~`jnx_ n=[S/hTR`&j))RP% X/~(q6_B@ hbzu*$ Hb ]XL"3@Abή*|fؓ@.Q;T@ϰ `!_`p64Q^tjd (LP0'l"SkG%{ U @?Y`H ( ,0  APe }~ d,J* q8k֊b&-24Ap`q)i@6qvJ2\SA BzYQ "B#ajCtajCtBԆ RD-Hm!!*@wA_B:_nL<-Ps,t~KVY:THQ@4@nj鳠~>? ʀ#4Bi> c]? vR?ҝH'tˤvC1Vs2c?G%e, r\ÀI,D@@aP`U hAZ3B2Jv 7#!_<0JYox`ࠠ ,dC/^"\^ ,!nC0(AƎ[g`$ %@hHOr19 AO~F@8`Ü,Q ^`Ţh )}8J $ QiQ#A_E~ Q$ P%GC %! _zH )j} 4\-7|j)_O31~]4 ?ӳE(4~NwMGlKcDY NaVuߧhHLEs`(Dt JQ/.4kӅ$A~c>_,$kP!Qr 1ZzF,oG`6w @ Hd H$^1 *=!D0E'HDrICw"n*c[qB?oV K/$P[JH/݌a=ʀ傅0`#s $EK  Be?VۀP,Pc0F~C0 R"(x#Cn"&b%$T %=?2$($[Pb I XhP>8+0=!!C J= }em+ +ϰwG"W@%RkeF˘΅ :bӄPSix)%GװE`p(q:C@rl?@/{pAB]($ٌ:.HP,3dxHه`Fi`%FqBI05p8r,HGDpZ3+#ѠS" jNG_L+O*1 7䣋-\("=`& ^ ]p0^% t!3v@e/ij!d@QSJ!Za0ڌA54`Mo 6F#I.K  L*.HJTONL ^6@r? FV4 P!QPGD}|.4_pz~B(BJ(E3|W'g2?0 G8_B쓜4B?|@:!' 3ViH e"Yv%DUHkvG^H+@( k_f"*A<P&,a!An &xjAk" Jgv$BC֩&ݣ֑2Ȳ 9<, 9oHQ/bhLFrrp{pW;F O@ 6MH98w ?' Wm!Bt0? dA*^\*q-Mq#7pP}!LUfbim?1%#T_i<R Ѱ4 P֐@ @dSk(,8%HȢ@zѡF.,$aK yB@PUt4RF#`jT2 +` #)P(& !^yP|Hx BRz&}ӧU$Hրh01M6Z/ZGꀖg6q48Bk?E}D5S @E)26B|1Zމ:~T)%JH=/A^:Uj԰OzY"?}p:{ "tr~3A #t1X"zQVCH<S<- YD0L~uXrui EbN/jHmOI0((`$ H PmA O[AX, i53/E@,FDY0O)ɍ K.Q!B !!JaS)߂b lAFԔ@ /f A0$K|fEbҟ, I {'A A rvF g@ HUǑMH т ˍw8`vE^FȐ1/i(:j 18`$LQՅPQ+(EbaN&S(GXE=ɍh\vEY s<|@}4XUyHGCnyT%q$w4I@A24QĦ6TZ t %ڀ- ;eurh=rP)ɠa I JJ!BAh"?͂t|BbYVhtR4Jd!X|- &Mm@ eQ !X-B<i*>A(?!K%O dԼZ@d:߇]sx@a ᱉E3 | c@soS$Ul1Wa(6a @dx)6*I<g!'Za4o VJW=Fk}Xl($ADJN#`ELaotJY7@1lHDp y3z e(k_'gʇaY&(\(+LkQ!Ƴ0J(BD 00Z!N TywLubW-\u\9[Me(Y1TF֦.V0LN9BykO(ATH#AjoN) v $ Od`_uFQJ:u qHOYyQi肝^]`S2TbGR@Tt޵8xC,D8JDF>HQ'?i0^8O.(!Bj0էrg)W#t9P30LY>HMQM=EO6z$4P%WY(i!1k.0h6Lr$Ve3W𡮰c.1jm$bɀl8p }!rgFQ`$agQeM5K}#« B е+ ŏ!Uu,LBN`в P"h"A !8n!JZ mv(䡑̹fF砶x7iHW$!F#lhLkH[Z%DBHBWGXV?e,Eb> b KNLEǕ,;I#Q@J++fs+ΌƦ@-ЎNV%%:$LㅊPv~j1T*bU\Tf))qKa=@ /o(p#( qcb@701]7)c\8@RB-<! _ P ¡yZ>|= xS3BPfi0h PH`Pb-` $FxHT`j42!xd^:/ *:@TTXt]Nq K*ȡ(Q$2,FPX@Ih @V L!E@;F P&@6< V<:x3-@P\"Aˀjɝ@"qd,S4B@kTmP->SEiʯk^R 5$"#kSdB4팸"CzAŪQ-x*%9P( lAH d] ܠE/7E ~.%; T!@rBd\iE)^B )A e0mV^NJiU? )~ `4HbA$c)H3kw P+S@u1w h$@ PDl7VxErBԏ/hnA@ { ߒ4}/ ]xOq!Di@8B %  D@1K($1^AJgg)ߠ [ A@[ `Ly/ #D xt+ӣ1&+Xb(;Av+E+U{0(pu`(`<+&Br fph$8:Fhr4p3@DЀPܦڎZAJ=Fhp#z ЧKl3?RK2(x&"& K9h6NMPhE $}P(JRIq*f:(PH1D{rP1J +S" PZ ^kNB E# TaƫB(e1LD?D1We|ZI@\ᒡꑟBܠ *ˌH`(C򊉂S@bÕh[(M, 5|u҂=1f_1wR+@/uh O9(,&z3;^"hY)QF#G|+!k p@DUe2c ANRQ MK Ii1Q I0&WJg"&գT  'V)*,!A=?4@-܈`_Ԫ!yȂufAoX$l-J,+c>w&zQK@(tCb!OIGQ( `2 sHSt' `sׄ`aG&Ң~GUӚl?Nk0MXjM24)G Heˬ wVdPNGш\.Yc\r:LF i,'~ j9ƳEe%li($ p( qj E'Ql2R\Ik{ejCJNjY$?P|w!? 4Ru6>C)GnFh"(L䑥DT0s8 }YFI)/.3S3b" X (1#E ,BA1p& =c;eN Ú8˖|Q|0p}/N1UtCw{ .B{&b56Q{0y 5 `A%5ΐ%)DHA#r2>۠ DkUA{-h.ցX{ׇ &r U D :BcA(fx.Ri+M]`ygXuI5-s?H9D"b%YȠ  K9@ji(AM%2,W#֜4Ult|#?E<9?E]>S@+By-l Bk_RD+zcB> r8}x3oIH]<=CKh pbX<%*BLt1KCCm>=HDo'~\M$ P ޮKwsڰSH+ &M(ZY tK^YvDхR) /"]( wC 6ؖ9۵;dʆvs3 2"!bDŽ2@SaBt J$IR:Dڱpe"£!!x)G4sf B+"Tgd2+H RM?Ő(B?`hp+" 8~1"g<ɠand3҅Thx8y1d>&~ba 0G̖ <(L#Bt[y0W[|^J̟ZC\Y#INO"PV^x&"!,$=i?3-s>CCqTxRI'qq**Q"hP`ŤsbH o^FaLS-~b d>Oz!X )$[T#%bzf2Y4& }̹4>&EKDOtCYCJ_(caL %9H жW9x ; 'lO'gǁQ(& kr}aI0j5eB Q &2С $E{PuU,`up[\RV!E!MdoZ"=2Q auJv´GE13ȣ [?̵Rz3ȤNizE=٭d*~NHKuWW Fb+4 I22BC: BS0:-OL9\!-4`bj)e#Kke]HIc$]|*+u,l7%J%1%pOSĬ%#ۼj[BzbZnJT0@  HrF! scȚbXJ\ yX}Vej8Yd*? ]esn.&wePTSp;}!n[pAkkQ&*_"A; ]B!,j3$DcI(RolS@4N1C.FIP {P z0 hSK3CE!Cơ?:?ai5<@ XnɊ !k4 *rFRJ @4Qū:¡RJ(꠲y%ED$dǘiJQΰ8i*2 IhPxQJ$ +J8(QGDFA 9T5 IQE'!Z)H,%;@P4;谦`kBr<)r%AQu1 ?la҂"!aIJGZt֓C^gf.`ٜ˝ VYx?-$%dT$?iDb8 =3 ȃ!à K% \0 tw11b!r|(:CRd'$C'} ɰQVNnY$pP2qȷ*$D]Io( E]`Swh_՘huaO:v`Är B} [ !!jY٧;Qᔚb3E-*_D܉AEPt@yE3 `$vJVeQH_U⶛?»R%]wh %/.,P1I[ %R%Q*r5ВZ瞿_>)u[DԱyvE"{0DG8#D!b?,fR ֙?\vsu͜v0ʏ$D "MY#P/-IE8VAS2v%*3)S!5.G1FZ)!Z{OFy' IQ0'f՚%@0B F+*a 25#(ZJ-J24H$͂)@ BiFqe&J{}0,tׅ0MhP  )hJycPojbUň Fm1l};%+K"ZfcA('hiEIf,"--a$!OQCBn'H[=u"ŲE)Yd{4Io@{o| 26 Z旄fS$Z ˢUM24ތW`.Kq)68i2 `, PB  A,h?usXnU8C$wCiƎPyIVӨR)|pG[敓FO{Lc#%Kq&%A:,DZ!"/c( nm SW|pzisjT*jQ7f)AcYA!踖U;Ul\>2JQ`AzZO(yp>>;1+'k7$Hs< -O\ :$㕮t{㌼QVIn L EJ5l( BD, XK1#TXBQBSUHQga,ո f|&8:ejԊ ÙJ8Q!@2@x[E"R@m$JBѥUgPKQ$`v*Χ#"TU0`AMj\9D!VsbxΊK, K֌ *0a EZtQ⃋p;ST J3ȏ!PX`%ҩ,` ?6?9,&X$B?c1h#bPG=O!iXE$ =ƿAJܞ8.S)(QԎ0x(d2#}<-jŪTMbp'c“! 0XԼ:P餠!ap c./&#'V/D ^mzb!\)e/oN)RC8tpȂ8S ɉ@o'(L`]oE`*Rc@HZ+p5J)bH$H %E]|d@ؘ%cz a օ"x)da^}Dw3ȋd!sN&n͙`m*殷2pW_DI8 Y6癈pxJ,M/3qKN'a~ǫ2!6 (`9# 6_!">r-‹Q Zڅ"35ɤX&1{g))̣"}6)o> =gP-g i#` xeI5 zG* )QqOKGC3eɗedڐC $$lj  5.:(-==)s`s棡 (|ײrp +rgQ;IR[ffF(f?j"yMryhּtM;.L{͑Hc =*Q$RP9|I, b\v+s6 =,;Fw{NCf.*#1m#s&ֹIM& ՚ 0) #CJɡ<J*R5:@b!6z `Y.,4l)D1E,җP. h U X5fP+E!JBU%D!f$D!8ATW!jC$ fp!F<^!UAf<b)*T/iQhc'B_FWE|%{KrzPd+^u֎H;Lֆ"EZF#aXf_]tLU1h! ^":N/WsrFLHbLVtP0:* tTCBQs2ϊBƏ_VJ$!UJT& +> ZdڒDϘp>ZR q 5!mLbʨ, ??cELbJ ,4&WB P:eL9Hf`a1'Tf ـ" q,R8ȕKԓ$ %Hg$ZLS6mR'2JN$b SuA#iPx3R!C!;XBAV= Vz ٠PCf`$Ha*5SG Kp (} e|>@q!r<8 8ONe!5t,FU$RS$MO+5EJ !Q$8$@B2HD ) H0{8[cCRHPe5c,y@B B:Mi 3ծұ/Ys xZp9qG2u5Yv-_`E/v%` @ RQDY8 7&ʻ Pj<J*IYzJT=* H*`:ƠzHya*`UEiuLAeq9' *dtxA# z9Xxe|[,^4\Ӣ+TG @2v!)0vu3F5[ 3 1"cWR)C%D1Q^"b,NDB(̀!$étjA CeΆdH3Ll 9##LEbrC)mp< TxEp%n 60*(%xnPF^e!N:HSSU"su2w 6~D{\JA .b/+#cCsA6c[ȅl M2o;) 4%iaCh"3%l;K hq`|b$88BuOlC xaèt=*! O*kC$!P &(!$ 1u' <[[V IsZIηAFs @zj $cFJ*]J Y6e.]^K <@0M~AJR+k ֑RDZaVB-Z;-zBNĚqi3Jx?($Bv^<#hRȑCVKA+` BKȖ "B/b4xvqhMUV )B]@*Lҁ ЉHB"4dEy v @%HH%]8=Axj RqU ^_G^@(o\#QHHbRZ^JEiłU0%B1q' AC DR0 HAY_"|#x$5u!f<fXlAgXb D~^򪸓(0¿N+tme›.o d J_I|<So`hQ\K|l0@QH !*WJ@ I@w`!puuu>N" H;`DLr2b P:xifaIaFqZH!IW E  Q䅖N>""Jd5@| :*/> [%g` h|e26H%H" ! |dB(`GB:_HSғAc,hiha[0Aޥ3 j{IKx@G "Xу` ؼd"Ù%/Fޘ+Pyv@ `)G(,ʄ҂Wu3y v?R>:4/:sM&E/G$@Q89*򤯊yA:BR)iPB<w>`A,J $0<&HB#A;@@2@@C/1Y'IS (y`%AFUIb`L.:|;8Hh)6i Q%UB窉R)8k.|t֛P`pbDluCk] ,Pq% !Nmѡytz @[-#Xhb~T 9T <Ձ'Ѣji0UB EҎ= Jz "`؂DށűD,[i@X!yŃ/.,(AC(jIAׇ`ԣBD,Hij&ZUU/XLO 9/p ɉaPkL!3R91 v;1\XE,\,X;Ò@pƊ' 9Ble5QA F1^>r!`Ụ FcI@BXkS!BE"QDr3Ɯ ӥ0YW !΢:3d9 2!%2+͇JU*@.DH!%2Ū#"|/@$  YW:vǙxQ$-8d඄Z[V KA5Bѐ4F0KSya1g%{yYO^xOf 9!vWIq'#ʂI .*,HP$B#AI{{aiamDC4կ_ 2Rx.$~8W! T]#Rg@I,!W bK@hFIE*d(AA2+7qdP3uĴ-qi N|&~:I"ZkH΀?u0PБr7 0Lt#@t`"#%!*$4zJ:j,Xuf)ñ !5f1j#IJ$h`Y$HuS R%@ɴ!Ԇ; `f/` 6 DUC02mL%X'i dT!bdL3ꎚGiADR*.MI T `ZؖIq@ {LHe[E "Jj(鎄e?Ɋopt 4ED`c@<إ@qiwʛq bHK0?T䦖LC`Ve:!H^^ u=1aI(QK2-w0wPH $‰`)R<W42@Du8YtGṑKE PpRŒ*sZCWF)}}&N`R? OUNOUv@H]$#-Rw mnw_L0rPn`quÜ?DF N$ C9(er;b4aݩˀ",H$C _b вF HB? H1Qe>1oOT/l  a0 Jp[\Z): l`+F<`)xJ<@2~`4ETbG`X]xwLВE?},KF3h,4 @ tJPЬJnQr[㒄 TW3"ɜz,Q-xZ aآBH-,h@H>ÔC{xcDW0 Xq$@Ďzr~A| B8Z60x0k`Od@G_΀0v r?ʑ!D#M1@ 8V?U>jG~bpPjDHX҂rt-N>@)=>WP%QE/FgFX 7XQdQG̜# ߋHTJ1 $# pHp·*aւi "DI*?7YYrX+@)D)I<ch#+06?,ӥ.C|DQ(3  U>׷+J)# ɼoW0|/KgN#|Qx)mEJ$nXcg&0 N5נ za5~5>5ßdkyPٲ$ Bp "= MV R5]AS܀e-QXi@MUҕJ(tZ`ii:EFӫNKԀXiKFbkTQ zpDd`@hO 7 >0 mPIa%H?T@zb`/05@, %_$|yBAgыG/81!srqRMPF=ӌa@hV"J-#|CH?+?@YAؠJґ _xᙃE6a-)!BD@e..,%@cާ MB(\ u\boE(x d9U bAƒ 2CJ!҈iD4-XWPIڳBE 2 gBvT>Q""]@B` paŐr!HJ#@[`cL~ADATB0$3![hԑH 1"u0`O=NA* t} J hS Ϩ 3 +xCNPe+E"T;MjT"ؠT|X *0BV(! h y+p= a RHe!:!AńVH +`DhPB*dҧ(MlZ%U䜒髤$cB2&HBH)$ L|U"Ml*lb`h(@Ő,JD)Ϗf,4TAjLHOjH)eň@CCBd (Cx&b`F~MP^AL#J@]%?J?BxI'ա $ -/&h+wLrDf o6eDJ&L? p07́3@ L)5 7ǂ;'a~NxD`!(.ғe骵Wo A@Rt߇`gPbd"4b) ,R ?V]U9 rF^F $@P [f&iVP8n͂(TIG"#B e)q& 8- A24[܀e,.++A51AM_[ۮu@#OlGa.R3M\ a0fV0&@Μ(A&5<sl&t@_)xI 9<,_>M.:: I@&4+C ,xi]4Н  hev!dx|8Qͅ`*02C( ::t>/Ҁ:!T Ȩ. Pi7 Qi0"tL4Q@$b(PQ44/ @ & 8cHAtІLO0O4 ε[`0/Z&R?h! qR$QLKY kPt}r VOc <O"ІXP(!S2Z8|#`HH`3Au5`U7:\""4d;HaX, E!J#|> Py@,r^0C4غPCp&~Pl)Y8zZZAU/ 4XB^ZGh*_(d+<`^$CyB!P& @lACAXnZ] *20Q$C )>E?R%7ҐF"UGJGZP ;/`ODo5&o˿bfDɄüw$_-11c@sЀh̟CC4Q4tDdqk0řH/-J&~dߴGgD?-$F"@15ZFz;J,(*ihkII $  h*hZ.iOP! $M^dd ZA rAJCDP:c? DD4Q$qeb=hf~ B\_5!* Nƕ QFVj#Lq.b*S,keBVjLĠ,~X%r1@J]cA' 5gV00ha X фAUP  @z@PT AUt@gn ė PKbH5Nh\P0/P 1eBmxxŌ!疞K1t**;Ÿf][? q S}w@4\^^^"0 ~G"XY YwM裓  yD%Bk/pl\yPf#$5k2@`N]Q":i)Tq.E~)h)P`2_ h I )ESSDt^BtZm gfFZb A~Ø|AEYP RJS$+ShH$FJ*D6D9X H2%J*T$t5HH",\ԠQGT-PK&s ,.@$"BfHFh %`?vCyCa `9H*i<_/t 쀲m4W~ 4H4i!Bۿ PSLzͽpsb@w K_2bT0֯e Yu@ PrЂ'=ATI `| 5 L%< 1$99$2%[ DLxJК0?"A9Dx@I'ࡀ'E DI K  $C =0_~q耞7 @-EVw` PPheh]oC BB#U4iQxM5mϋ^mH`=@=ba˕.} (QIV*uO%,Aw$𐡈 jA^ } \y^03D(P /+j4x,P\"P_}$AzE$Z@ ?IhicqCFcO3(" DP++oqϙ_g`$3D0f?M`UtK_ 8g0ץ42_}% YQ`R38$ 9eA ʡyA//) ];Т GVZv2EװRZ8RIqV9F 8B;9>3/'Ӈ8ŏ㔄Nf!lӺ*4PNXB4CqXrԨV<u8$A B,Gh`DD (*0d`>:tӆ G)MB  _<:YBk?{> $@% /6b)}uА@h1!I :+naS _T Aŋ(J C~S( QK& ' RA@xHS,9Yѩ.0~IEHOE| , Q2٠HMH)ӿ i(r\g=RAQ-Ezc&kC؅cPWG5QiU3水. dv~ ;.EĘ"jh@@D#j,HIK}QO5(\)Y,3 @Y ?cèfC_ \T_jOM 0P pРƈ@)+F1@*G>Ïڼ< @ hWDXҵ$sP"5~p6:S9ŗ2=U@P0y`Rrt}D&vxfb9. DBl/#X]ȢL* Mj9cM @(:5 B K Q(EV0hBC$)k^Z%"K~*pz]+0JKz׆Oa` %!"~/tM$E+׊ƀ ? v[NL%KTԨ`@n B#,X9xe1ve TńT&F!Ak$}oG0a", iO V AiP̂ _K `ʐi! A1! PBta &$(J-s`E4I'G g BV@PAiN FI) A/-;!)) X),VAD)UϔGQ82 (qdH$ gUaT U\}y@ܑV(HhK 0jy_?"xDa#HF1e+)YJ8P@3@B 0!b0DE ]:b?STS!dSRјSn"LU&+? *Sƅ45+CLFɡs%͘E/Dp2*&଑ #|s)S}^ P0$,<B> c,b]/ z@, A@0f4`Y-hRs G#@ P-Hjl 9BF{%)%e| lDeE&J*(thK,&I,0!J,"PḚ4)F5Tb y&ARXéD j҈f21bŒ(PB (PB$P$EĪUG2r1Պ++ i/+YE byJ9:r"^"J<`a*Ra8j3` #A!#J{dpR,'m.^NKn#T)*JSU/kX kP& Pòfg>4FR5 ([!dXI?1>B%yd#R,B~zb2~C)7cpȲ%ȨW0ufzxLrOS#$BPǍQRyP4K%mxٍ|']WIA%~Z`0S H$sCq(4)!TkDA )"`BW)הtD"Aę`1Myb@E+'U(j3A/!̘!^Z\y%",X PBF(Pc *BCĝkBLP Hc.}F91'&.Ll0sqL9_qE)BRH3^@򀎆J"x)J=6K'NOa(̀B"Hev0lㅒMs  `H0" @e!f 18z%Ad <˽U( @]yA-$@P(PT1XIQ-q,K1ybh*Q%jp EYX$h$RRX- ۓV (#ʉ{VÂ5 !DH[13/PKB3`^H8jb0BU!kFSJqg˥7PJCW^BT(,hZB?OdF7IWca_ IC"`b{ WRQ(T-2`VAi 䤗UD9b89*BU*:/^E"Y %EU\ ra>$$lxNbUo>F"qը.K`a0"U%cG<#V FI O%(hĀ >_K`_W>!4'e&1|d9J1jkH-ڳ̙Q%YFH%y%bJ @$" (!#z:aM ZC$[$^c*N QRk `P #&ȹC)@'!`L?ˆ@8 )~8 )e0@> .H@S&Ypx$CJSr89\6 HJ SFs1j#TVPJƱXBPŋ% r@I&U:k\(²x(C9>8.r4|yr,(Y,Uu{W# S SAE͙m+@&QUa p0 d{d$2gzZjqF>(\+QIQi@$`2-DH")u$L@"RGaK&8]cP$%T  (1Q?. q$T"`Z-ˬCpL-JH ʬAtҠ Vc+Z+p(1+v;A WO'A)DU`frdc5+DQ 0 =A(B18b238)IAm!:mbfr,R&(C¤b'hJ[!C5 IF 2a*RN × 1BwI#$W鏒+FEZ*D^1B5A Ԯd+8HN2qd' 0a %@"$K9^#JX ӎQ6dd B)Hm=e۰CO!t^*uM;L2e0^@`#*?P[+ Ӏ"U 3 0DC11WY\ekmHA HBE990hBzrG dJDqB6eFQ+#?=I_\O(" P`@ XjʊE%]e< I:k+ $(  fpnMD-2$ BR%LSGQHƮQ#UPZX)b_,EKa՚f(GYC"4 U%Qŋ!(PB A@Hh-(Ƥ̡YC*y9 `} 4TξwZa [1Y(CQF< >äiBA HV4!8ۋ0eUS~a("xB```̒8[E mRp`01VZ”T j q P*!T>иE*UP $2*H b ȠQ&XӦ1bGP,A$4)(Xב( \ߧ'Bᦘ)ĺdߧEY֚9l@! ʛ$ba%(X S d! (r= DrNAQZU!@I B- ! FW`J0 %B P(-W>Z[_ MPRiNb 0GR|D6=)rap cDŽ GPR-Dyx-U\V̄(b(%2ΆNĒ+Nl#HJ)8'/|4*J]G*X}D: ܬđ@efe}-_YL B 4(&d0H9LDc(4t4vPfdC K?vxVHm5_LO( L @ >C2 : '@MU Ž6q±LH$R `t($ca%A$RT` B<gPqTL+$hò yjE V.%0c1ϐCAUXŋ(PB % 2@(hIBT#Ɉ j 4`M\hR(T圿1LrVܪR1R[Ovtg B P@@QU\Rt 4Ef pℿ)N IlPq9?j9&Suu"!H ٣f. `9zkd01" O@@ F FQh2M0.)CTy4Xx jB JvF5(84$ ##@A@QL8VLZtwXt.!A iZ鋯"KZ5v J&;TgNb@ABngMZ% Go@`&CT`PlU;karx+A%HRJM@!PPiQ٬AN=Y 5MY~PHȭU3Jr5Yldaf#Nd?vt'g9+̼6)YjP# < 3Qm @E %B g{Xq'dUһx!;y[]lz$*8v Yo nqP`<'N u d܄~k1  8;N :"pѡAΟ"4$L y04 {PxVpB@ ( @MX YA h"婓ℂPxk#,D%"-h ?$ J$6[qƟ" Lc3D{x&6dHO+ #'*T p_8_B E$DGBJ`c^PSR"qÅC$B_^2N x… Da: a@dSLjr%M>ʡ JU) Ań0Yjɖ$PbPz h%j(IG\=CH6c0Aha, D#4"(1V1Ud]pY,K%l'd#HGXBD1bp:E"N$ӑ) Id_|'EQ"80СBPM`]\c8nOct'ܿħAH- 0 a2#f]eBP9-\O ys R4@Qȃ REI2TmRIj8d_@@@ @#]e TRr1BCt!j@g @3("T$I>AcA2H!C:u_¢D+,H/ !*#-*qd FUe+ dtY%dv2pvBLB8` ?+8'}.}[:!P0P 0(P@ A(TT[3ӋCE9^JQFyyUhB'+ !BVaoTpH(8H"9KNK#ALa@$ )UA4谅Ad )CPHh.dyU02P)Q $ =YF-q¥? 'iZ>cmM6c8)ϐXQ+}5%(UE,5(6fŊD FcB5cQFJI!y#Cy;/ B  D d~׷agXM# jZC&H=vM @  )adAj@_Pr #{cH h@惮QRADc o BjEH4$* E*`@PV|Z1b * ) A&@&C.k{? H,pDP6"tiDx ( (JJ840ˆDy.fs2PAR߮ѥoEB(X+?/A'G 0hʠ V HJ'@T!a4(x?l(r VI&Q6i 9 ̋ 8FE 64,Ak ѭE(% M~@ 1x6k0 mAaL7,1"`g G!SZFl u=\` ".MpByC g8?>8ϒrLI0&t]E2 !&`%A)KrgPPk< K%\f" :?LKLo4AV J2I+0) F!" ب AF?e׸e3"G3Ɋ@$/q$D$0^ ?%'= >B9HW!%!kp}C9*5@,F3YFB / ,T@+!X*V!\I4|)j/G(H00@ `# p !JHO Z=$)+1h`n`!$YpdtR~xM- !-r>'`:2P qh,FQ= :j8;0{||gj+ɒX8Auc" `:@= mҗn)4cTZaa00*,A J @7@@x @J Rivsh* G:q2b(Y|x̀` 4G5B(tgFa_J  ,DÙx4<*jC1j&`*rqx}@$j[5  AY??T6~OuJz0 ?D'P#;ٲ -BH ?ڦZ@ &HaI Oz*.1]Tk\x 0ʭtMKa.<ؠ!pXBBE5}F )Q3hx:難: DNA֎ 5KUG 3{1qj?xZ0eEptS2d#drX=) P rF#\aXB. T`nˉ1&$Ę"LI1&$Ĕ/>Q,FoX p0 O@CF] p !#8ar'R$$$XUkWO-HD~ 2e] ("!W zO{ܾ+)Y /@h%(=dА' HLR@h#S| J e/W< %"3j@ H"9U\%zCjo0 y( P(QXvj +N;[6N ALb&i.YȎXf1@Ih$ Bp J!j:f"mTTBEQP @` 2CB)B$"L~X`A&>A|6(P T=?dCKN,p_@RB_xYh 6d2Qh'B] @ Ѥxy/8Hj81V?y T )B0B0 #}ʐl#X8QZ^izgL(B}pHmгUޙB J8A^_ /Wr.@P,DC89Q ؘG nS' ?sxp,Čxjk<@`" =f1q`B 0  DD#r\BFƥ1s`R`+A[6  , ӧN:~>(p(1a;0͂g \@'Q/g6хHLXQ6:t+x)$DRZE-"  @$a`CT[" ߛQ+P?vDIZ;``  sa\A$-h'(@@"0@.6 BAB)Vs1c(B:$ZƸyD"=X-Eb!^Xb1T(ѧ7;Zr7Y~.hH~S08r0T _?҇\.T 0@)"oȜ'H]C i^6 !51E_](R(e _^ FS T7kx2QP &8<b C DȖD$ 2` m(iK?ajM`F `bU4s ?G"@ %JpHf@!xQ\7@4 gL +S&Mx怟?~`. $1hPR^ŀ$bOHo?[Td 0`n `.d( !KP&H hQ$]KE$HF8I%XY I$55AI%:p-w ($4 x^~/-!t ĂJ  y|@ A#)z@WUm-}2<(Z\IBC'^ k[vA Mǣi )LZ ̇0T&Rx 0%;I!؁$t p\|., 4pN %(P\> W R9;GҨj*rD %qp jT0(7/ ;Z%O@M3! uhʈ@#%|2Ce}<0 @`=pdpd}}6 6/g6/:QP@ffwN [!X@1H9WLHoZ_ / T $OȒ_O.W̜C" $AwA6T)P30 p: F'٩P$E7 q^!bTlI'xjPS(@M 3(-te0J|55fϤN .ښYz=g~ gp vT BBsH ̠$]w  &p" @BB,Tagx'*L(SB^4 "w0(4# 2d?#$r#Jv^ic 0} gMۈA$V  8A"E'"ƹpQ"@< "`p--05;gŅvpjVF[)hl$U_hM8B8p4. H$(]RBkkPS`HQ*a(PSҩ'zE@L0~ Ԃ%{@h44i9 LoE :ހ#@7Aj 8 Yi*Z4u4)iZHDUҐ!䂁JC)Yk!F CE L|JN!q_AHA{a19 pIF!YG QE/x&*U"M4;e ($*Qh8e%sNT?F>"PAB*O!rPX] BG~PH5@Fe0 a ڈf fH(KxƢhW@s6Qa?魹+λZ~aKrƋPE%bOiB2ʅLPԼFvJ>#]o*bEТKW%]:(QhAxPj$RP2 R+E)z,FX # ߎ~%@ X `'1k/  E78u(l`acJBj9!p`96H2+F|3DAB_zL?zvX[pya 8@Mu@)h^,;b8a@qa@t!€wct~X+^נ hc^i(:d#&Z C0z@P,|=U,9I 4#@J`cl@GF( J$<#O-LΒBʄd".NJd@sy0s'|"!/ev]131`L bo fhŤ@i%CR &: @Dt z 4|z,-BZ(?# nQFh4:Hh~`6}Y~_$jl/T!D\@Z(QMfQEyLL%F'?BBJh^ PTzxLj|.tpTSFVD D Ỵ0YWa3zP f&6hjj̠ ZP@ 8h\%"|L @BTI=T3RO.w !!B`OߴwN #șR L"0&J̈́WIR`pGk/?(}XXk L[=\TE\,!aq`IG b`}.vhO]'.IE}">tHO]'.IErJ(H!!$C$C$CH8H8H( p"@Y &n,f6gְšſ4t36`:`I ͨ\"f,FC3h#`xd R]]BGк>.t} ]BGк>.[Hs`$s`K )6Acd6Acd6@D^dgTa\Ԧj5P#A*gBXm|K c,я *Y?5*gjT@/_?|/_??@@{ rg rg r 7s }1} pt -=r]=rD=rD2f͛%5)39<;C9vR>;8p wd. <A PTĥ?%%1м `HddZ`c.(P>b9F3asZ=P2V_%~JWRe+)YJVR`@B"DL[(.a~cN.YoXa =`APXf:?+^ACf$YC& Cȑ/c0fJƎ#v(,"I5F1LxLxLh1cD `0 E# STdEeȇ@@=a pcŃ 0c NI A]h``_0!AO.kkQϗ`7cG2apӜWF8F@0QљNZh ,oHPh(t)0l@@ __ǹ*V/X PT222eKdY,K%6%<J!ӭXP( @h$}?+٤+ a)*  `J'X,_K^{.e̹e" `C+@2`!OV|G᜝8"E1*20D":#IJ3Z # 3+|4hC_ u8PitXDVD`"-44U7_jXj~rdsY c a0H$ A  B @!&e8B%A`!1F ]A$ C"LUX=WD)T \U136f̑R*Ea!<ˉ+W4$h/_ *8kK{.I$Ȇh.tHbw}T6vE}">t_X ?Pe e2*0m$@1~ %9+!%"E8G2 ~( _SSm)-$0P@W~(dNa4EA*©eB?9 2LC<BLAm t} ]B ddd>.FH6͈Sd9O33@o/U" PTܢ@u92ZBW 80  L+ _u( AB';@{ il3WX@UpyWP݀Wgf,_Ъ%*HpH@y!y!8H (c!y(6!QP@ !ffwʨ\ :Gc W,"Lq‡}͘@)rv@"#rBnX# һ=R 0#@GWČ|"Aflw݌](&ˌ,0< AH' }ضť-!I HRBd"@? x% J'Q-"RǤyN@X8"`6#ȌQ)gZnߨ 'շ`ހ<bHH)MlZbӖ(1A Pa/BL# BEACB *A9#+an)JqL_3`E8p u? ;RbSWb 1)9?ѯCs?9@ Vh4%+]c<7* @_~WԳÌʹSj 2)TR! /|#؁)ڭ Kӎ Nָܲ F0EM} %$q.B &{I%)Bkh&@l8q @([ b.~ -p3sAgh,õjɾ60:āw&4(Wd6  '`!ߥ ~RS2]_e lؙfqfAL5"d.0lP!;|`(4Av6d2}~i."I UL^(1&4~$PldqD$ ^Xb (PBPg %@ "z@!C=e/,. ( QUc00r|ہB9 } 4(@ BbĠ@0GHE.a0(HҀ`!_Nɀ?$r?ƸH$ FnP,& 8SXzPUE:S" @G6:y$b};\Od S$04 .DğLQxg](uҫ8M|Q| F| r9Ss GRه\ 9At16!-'N-ZuKBM%zb5=OenPJwdn@$, ##)6P1x``%= A6z>> 8]) d%ĈH O DDc1cŀ@/PS A C8%!bI9B-b+G~H<<b<*9dUHKx'0?HΟ< c0L@<{E:tӃN,Yaybҝ`;wN|%-C#VOZax= $744T l%ή 1OkC\R~t?VEB4$KV5Ba:<~(P+{MT_'I/ 5ƔǨl1y@q/| +`@-l7@`30f14)M HRB$(R'& $q#A 2%-^p(rHF F^d@CAD:Pq)q##?@ N? *T4hB)JU*JZ *B\+/P  0`K $@$HZ #(1$J@"@hF:8Ҭ,dɜ"G!> Ҍ&@r@=^:Og>Jg%Q@"pd'N 82pd  (^> >@BUY+ @^Xb (P(t Tu]u R:5#R8@ @^X|rH_aF`yyߍ5F6qD0e!m44Qs 0BÏpgh$Hq$< >DAlQ?el082E:P %@@@/ =HB#YB1cŀ:Jb_~s((QE*sXp (x!G3╬i]1 $0'$"Ea&pm1Ճ檼Ahc{ '|00@0"AE@>qk`)lZ`>Z(&"?@ ,KoPj}IEQ) S@̇6@L`Ro8P:0iJJҘęZh@@=`3 d~ |Ц4)!I HRB ,~$ G A"[NP BtJ d;ZB2(0 [а XH'؀9o6 )\_ $nnocc Pb(1A Pa DD$$J1.UB " -`$1@Af D0FtUE_\gt?Kflp JU[U2bC8x@ѕ쁀*ɛ+Lg՚#sqx@iʠ5Y?e@ CM@snJ/dW8rrrT4iP΂)JRJ- X1Z*mh$`i0*_307O w9ȌLh} ha c_dI&wpg/1{w(,dɜfaɃ0SCTp )XYU9@ "Y'Fhg+Wu3R K$oaHW2)-lV "fFR`: OPGN4ǦUlz)ߴC@3ޖz}@:ehJU1c1`vъBzjFrs h?@G 3<  u#)G ΛNSnucCUi:];̀ ` ( <qZR3 aOЦ$)!I HRBP'p'8NOc(1A Pb6l`++aXVW9BS)0) R)JRK@E0a !C|o2ɖLddtYg,L@B>7(l F;f~(PK`qZR3 aOЦ$)!I HRBP'p'8NOc(1A Pb6l`++aXVW9BS)0) R)JRK@E0a !C|o2ɖLddtYg,L@B>7(l F;f~(PK`qZR3 aOЦ$)!I HRBP'p'8NOc(1A Pb6l`++aXVW9BS)0) R)JRK@E0a !C|o2ɖLddtYg,L@B>7(l F;f~(PK`qZR3 aOЦ$)!I HRBP'p'8NOc(1A Pb6l`++aXVW9BS)0) R)JRK@E0a !C|o2ɖLddtYg,L@B>7(l F;f~(PK`qZR3 aOЦ$)!I HRBP'p'8NOc(1A Pb6l`++aXVW9BS)0) R)JRK@E0a !C|o2ɖLddtYg,L@B>7(l F;f~(PK`qZR3 aOЦ$)!I HRBP'p'8NOc(1A Pb6l`++aXVW9BS)0) R)JRK@E0a !C|o2ɖLddtYg,L@B>7(l F;f~(PK`q ZR3 aOЦ$)!I HRBP'p'8NOc(1A Pb6l`++aXVW9BS)0) R)JRK@E0a !C|o2ɖLddtYg,L@B>7(l F;f~(PK`q ZR3 aOЦ$)!I HRBP'p'8NOc(1A Pb6l`++aXVW9BS)0) R)JRK@E0a !C|o2ɖLddtYg,L@B>7(l F;f~(PK`ʬ `\3 aOЦ%)1iLZ `'p'8NOc(1A NbbC>'>^ 0s+ b·9ik0)S bOiiiDɝ)JRU*lB<ct@M>'2ɚLd` Űb8Q)$T8@q` L@B>7(l F;f~(PiC#\B?D of;M}>t@].A | '8RA0FB+FJg9r#Ȍg"1H07 `F#o"k`g)IK2TR42Y U@ ~b^r Ą  ; w20b@ x`\.> q\| ud=G=^a,((FL+:%:Dt(]agf(? D@-l$#H`p^/?y^~(  ut?G?_₅  tt 4 ttА8@zd@z@8Ȕ6 6( 6(QP@ffw:h. XC:͐ K%',;p5hRo7)@ 6~XHA8027!H IȄ2 Ѽ1P Cx OGte} zD2PX74h?Wz\~@qAHN'-$&*5QXhH[-ӑ,cX{#3 x%7j ji)^ "7F@կ pIrE.@Gi %C4T*@=~@n K,dKX$)(FH( g (R PI`y 4!tJ| ih%3BPzr ţO`CCEHhG_d8\Ww,mJ)> ̙DB0, `f !'z Pf i  G+b@IҰ qBh7{~$+0f3c2Ya d8CS%u DVGATrw:tŌ4Nu@Bp$)"pt#7 r&@TӿPIbL* ] ބ`KrXs Rd7#tsʂ XB;g|L&'zHC蠨 ZhL*gaUSG0P9`ڝeiZ`A`t  SAA)W䋢i LTt/HEHJ~IQXe hRt` )h@/ } !Dyb%D&fU-8~2!Ȁ 4U|IF@DĞqd$$ A &,@pJyJj b P @(Cq`S6iePfDe$$0q+T% (Pe&R|1@S( (C_y; |H!E$%30gጻ0z2ԙQҳs~q-oC1 +,cV:P{hh~Nifb.*,IMϡ^L_" pF,A:Рt_3:|aYoC($<С~ ((B>*zTP=K@Cɱ,> ۴P%()< baS%F?/@J1iؠ_P@ dѮ#>;0(K=ѤڤPGH2Cw7 !Apd5eBQ_[EϞ(<B |T0 2%!Ժb> >) bP s)gzcA@w/Eh7<0iUk@ͫ)? ٩oHR*P@!ӁjCE*8t Wbtkyд zJFZa^MkIxPPH  ̸QP@@ffw`biPNyI(QcXM ,`B PhQc 1X"zLd&zLd=&2=&2 OII'BgAc!3c 11DLq3z%,dK"QD%(DI9&PBHTR*EH"{u:Xcu~'|Ojz"<$RJP F{(O`%I= '>IOSc PbD"@@"BL 2D$I ]!l1-׌$*0 4`hf]v=dP"@$ƈ!,<a܀cB@<$42Q`86P 4~AHBA$($BHPI !A$($K,Xb (J#1`R@&h5JFJeaS}+EhLٳ D}pDچPr%@b8,P8ƀ/@rhPJ4&ҀPJi@M( 4&9jf1bXb @)F+zzlM nopH 5Ds2wpPPpPa6Pa6Pa6P` 087@@1 @!^dK"YȔD%(% "@H$$$OhTR*EH"U:Xcu:Xcp'p8'8 D"@BL 2D$I$дZ;Kqqd.i|@ B#,XB1b@2 d!kL @((QJ9c5ŋ(P( l a˫;88@@1 @!^dK"YȔD%(% "@H$,,_83(e 2PC(e ؐȖD%(DJ"QD%(DH#ppNp''ʡ2PC8 I16bhщ&>>i^" P'@ B#,XB1b@2 d!kL @((QJ9c5ŋ(P( l a˫\7871 @AB!K,dK"YD%$X gpe 2PC(e ȖD%(DJ"QD%(DJ"@ p8'8F(e 2PVblىF&M4^<&!xXD 2t۴xN@ B#,XB1b@2 d!kL @((QJ9c5ŋ(P( l a˫ ʦQ~)2bw@ H_4cy."1,/4FǒH|@#ay?Hy 1 f0^ic2D:F fP^hGsQy; 5 j3/4@#f(^hGr2BHu&1$/4G#BHjy$/4Ec2H- (%X%Ǣ^dK"YȔD%(DJ"Q'5g(&"d Tp(@\@DV~C$Tpş.9$0) "H.y@iWGzX]$%.Vޮ`)̀ڴ cq'G{ci k0o3&?8c Pb `0ӹgS q *a_@ O4A ݣYۄC K8eoyN\z"`D4Ѡ:gzڥ^L`(pj:h[ !xʂ&B (hgz=HYARPhJ(IZ&V&PC(reX/,Xb0`CV)hzaxN6:$,0/DΙ'; f3^"QA" Q<KШ}$@=r@ zvs1=PBA *''B#QXBϏAs $!w 9'CN7$8PTFkem+t(QMG}`Q2J@A!rU"Ȇ9_@OsMOj2_%m ( + Y(ⁿ%@Y%Tg] Q3 AA.p6XwH_ O|7Ĉ@l ` bTAC hHC\C U1p42gyٔ(0 LCbTqvMIN#EA~-F?AB)V@}=.(Q h0@! JU҅Yss ag].K%2r i:5!DIGTԛ9K&d@"@ ^Xb A)?t4|`1գRӖ xF`_ 4(Bo"?<*@C? ,Q ^bI0Pp @YH!`؟ǐ1@X?_*r[cp`A5k@HGDxo" xH7Ar>0H1Pz*Q(Ô8к#O?gQCԨ;$ v_!FTK$ߑD,Av!ŋ(Pe0Ft`Tcu̲` @p"$$adBޅ,BB+GA8GѾD"B(~ HHyH1bUAM@B:<4 `ꯨRShe/x&t+]T<X!`TbB~H?a|P-Lt8%AH0QOI"Yr?+|ɢ@ OY Q8_$[l5˔ #R%?]VSJxPI>AL $i HA @3¬1.EL$`YUpg $=  c--~,Z`?LtPW; P?كBE ,/O0PVH8?14^>hccK,I@@L H1H(!xx`ƅ (h-EB)9CwQ'B/c@?]b$0?` <4$26~K6"OjuI)Ho*ɵ2_&@, p1 @sd1 rB Gz?SCJH0iF4*.] 22+HM$( Qce}O27]+ pyd !H=!;";hB| (Q8penu^1wn`r E?eTh @/f 72c ͈4<"Q@FGbvDˤAH H)I Jff/~ 2Q8҃x @PHBvtGһ-y!jJ  B#I@#PP?JR/qAA"!(HpE/jC 4"x '@F!"-1mڛ»pP(F]`P't.Y "q4A@4Bh ICp\|z::{sjA5:PP4( PQJ*vP)P P?CIʯ5"^.8Mo+cbĥyx,#AyS (4!n|p&XH$am!h`$&+N `rV5H9@I%^ K2nL 2 P? i$¼@#U=o"8"DW  W׀19&i @o< Q(l #o@q_!  ?TBTJy8R* H$DHK@e/]4*)LC|iP.PZ r 0M"O PF"V@0<R(-Luu(Ñ&X2IP"Ox`Ol0a-S?٪iMқjr4W 86 0l~fx Xao"a@3x@H,8sH&\֌+?"X6HRDoGIRC)P>H+D.T/ W #L5@[NOܿ;v[x,,< .{pD hA'IP[ ?C\UP\I=Hj3\>6pvަ)E. Fԁv~nw=`AkbxTѼ_&;:beTPJ``N0# 3@LبDFD'S! _^R+_@odBNѤWA:f|3>G"gT)ƠH(( d DFB *ҀE F@BZF"E&9 K>V/;Ȼ` bG$ D =5vRJ(jnS"Ѓ7d  Ⱦa׋b HXG4}H6 P]Z9J"BxK"#,H)B`\ZyQJ]I#I$# FS>]>UspB&P"^qA @hDS(ShOQ+@m?14?x1&"?Ch@B,FTGpT DvT&=HO#)#xMG\Vo@AXƧ,e#ʼn(+0Oh܀ @%1 C@>^ė#^W&1y1z1Et"zLd&zLd5&25&2 MII&ƂfƁRcA3Rc@11DԘLԘ"jLh&jLh5&45&4 MII&ƂfƁRcA3Rc@Bh@ @0|Y`g ,I|A $' D I}@@$p' 8  Gz(֎ʒ3hip5E9R@/D`;p @Qp  @ M BHPQ!Ha!Ha D4f&j3PFja&-@%%%%%@((:( 2( 2ȺPO6mh6#`LmA Pð Hv ad,  ,  ,  w!o1#^bFčy5"5"5"5DkE!Dd!wWV,9#''O(ϻp^J<;&lGRfJUxьr%+)[VRj`p )~xdčy"5"5"5DkIq@+̧goE|uq O]:#ߏ4R|  $IDM7((r9ObٕuTQ+B!a*]tb@,0Ȁ;ZB^>HR%oFlDMz1dx4>;#Q/1S%)!r#cH?tIB!'Ԍ)1*|?F5|>!j"{ 0P <;SEό(( ~xۢ܈F7"iS?lԃjB#P!,Jc (I# ZLNbEPn IWe@ӑE!6X}*2K(\H( zG|K 1>jt?4 5)ࠈ~p($@"hE1k 1;@Al6zU4((xyQl+`Fh=LP9h|AQ,Zk^UBy,Od!Q Џ." 4'@ $ $}}KJu]8.>..|]I7(^AF)Pt"|#zuIqT@*?#K@`\q7+0oc {xa@&MPQsJ2 R~\ddC (A#CB@xXXN@P! D$*K ,^B(A D@@A\8  @X3qߜʷlYKpR& DT R H%MIV;l%ff̎, $ @fR0.6`8H37_ B (@ C,XB -_d^Kf(M%,~פ+~4ST#잲C0-+QPac ?12ƞ IGXY2n !02 . ,$r @#ـJ("6\Sр"r[ hpDX0yFfIOn~ueDf@nj  I;x@?B +iQQ򐩥r Gc@PD{5(F ?`Wh:P@`Fi0N_ꀿqbݽVժ(hi\@=2D$ZI+r@enbB !HU!].C/ pP$D@!~p@( vrzGH!# .'ѫ-[ Z 34If(0W8@lT ꀙ)l$l D!x& WE**z-]:*<Rpjpjdx;N. x&nj t ^2@F~$zHXNaA:~ <4Iź6KG=4d,頌@a]Ґ`ܠ:V0F0BTa ? AQgFH < A?*QHR!?CO<( (O&'B 'L IBE q3#!1;$ЏЂ  Rql?Դ89MF,NhX&` 818|HH&$#e28>@44? դ`b@l zl"?-5A?EB-Q3 p H?EԈ"ABJ0`B Qp;z4 Q͐m ßP|Fw&+mH"Z#c'9}Ϡ!:afTR@<d1&S\]G"ֻ ј" -w?$' `mp@Z?Xs/=8M?B!T]O]>("( AYFDd4# q4Jr2d K.+8RSvqPM,J݂iNG B8)hlYE'^|Q8#Xʟw@OI'&[䈂$ɃBR@v0HH <tWE"҂EK@/`wo˄->Y|( H#BN #` L@ ,> Q _p">(; љ `@s@@ <@7<;QG0#"JC-D F"?e?12B#  ""H $>3@b,FA$@ˇ 73cXa〵V,;]( ?0a@H2zBS0rA7:G '`,`q@MgXzڇY ~P`8}Bdl0:qa d{8 "& %.nU~/ވJ{PFT#!5,ħ|EVDZ= ҉LtF0a85RA@Vg FwEd間,Bu)a*3HJ3>;7$7%5)/Qc ($B {`d7 0p$PJ4BѧbSo,Ea$,E`\N&09>,|X|uQƍqYƀA "e4Ml]>@k9`wA0n40)@SH!M !4k@8/HC $0# i@Q e QʀCry* 6=$ 8A>#ϟ>.|\K@Mvh64@,&ye r@,  ,  ,  ʧFAcYi@`IYD*8  06,!ٵ"A!$5HkHkHkXט[HkHkXטט! +S"D[Gw_ۼ @__m<tN>ee9╨=,hDFy'HE кfD(P4r<"u<ĆD z z m DH~b]`!e`"w,\JZTT|].K%@(1c,$B b uH, w;Ϳn:\K E@ ED&ܚ:e@#8DS( ,f%=R$t.c#/dP<kaYyuc %a)e̤$Is|P`F1bnG.@CzP*`OȸH4.qJ`@8Dg?'`xU*Sm~ɑ{ g̽A?,',^%MؗlQ>k 8UwPDʁD?vT L) !Ֆ@5O@_kCҀ%3|U KPGp: 2p`<i5p $28azx`rj2I?bqb= )Ɨ-P0 |__?|/~ j /D/ @/+Ew)T3-}_9#|࿘6H9l, ҍ1Q!JPtѐ9z`Wcl4ȍ !mڄhp㦏P` +8@Y  #!{ORquk4*(]U%n@ [<` !t]O]>t.ES|B!!ϑQ H Ht BYqn-^PnP0mć):H zbGSԮ2av^"g0CH' 'l aWqo0ݓޙp`Sc"; x݆` z< L˻0`DXX36 L蘀6 @Gc,Kaga#bO  T z?GBC{0=b-6T4P;qC ~r  b5 ߨ`,~ _!E5A_!̀WH~  ~DG`.Àa D!e#-@"qg7ti] &XQDTHTIBʉsExAPH4L8 &6 X$1Z EseF*j>@|X>|>{R}%@|l>@FDp?`  + ;N;D/0MhC(/ R(E1+2 p]*JIwAyb{d=/ ҇Ê *_&@/g^!3ooRwaFle@.r[3ls@И؈؈؈|. q\|.> £ }@%ހ6O245APx.TDŞ.@+hs敐_ "܅tbe@C^@1)] Wzu$ L ]s@ `00o :bnpttDʰ'A5M191zi1E4"ZLh&ZLh-&4-&4 KII%ƂeƁcA2c@i1i1DL"ZLh&ZLh-&4-&4 KII%ƂeƁcA2c@B B}X$' A"}>HH`HH`HH`HH >HH`$$O$$O`lj1f5L3X k၃ L:P +Ҁ8 ul(+gqD0 º@A<#Ϗ<,xXGALr*2Pڻ|#&퉡/w_RVAPm5J _h:&yA{' 0x`8,  ,  ,  1͠Jp#)M~\E5J_ @i[F3nwrKz%v+KFE܅_-T9{KXN "30$xC!Hkh!Q!Q!C^C^C[DĆD z,!ơ҇46lT+bzG-h3Sf!ņAh @ʠ~zbpER:hZZ.́ Lh @A'th4i$5$ DB@u|KxϓNZޝes :?bӐ>DV   A (PBI?j5Fl, UJx0vOy96#f mվG+@,^1UX[J!7 AP,!CF S@N; JQA^6cBwK'` /]"B5Qw6\F $DXL !LbGW1į0(Ef!˻ AF RR!Cċ d9IA,nf7a-W?ZDxH0ZDTe @Qa - hդiv?ɒ[?r#lPa1s3&c'0B7{)HPt1bד^q 5b` `Ġ$Nd 2I8f8``!-տ};8DA :oϔ!-PI{9900`w(H@GnR@}$q``XS3b]-m){ESp::CTC Jt[Jծu&)<|Q̢]d:H m@[6]ΊZ} *BR(.>..|\f"G.>\M P$1(F j# DFjңNᮯay,4r`s8@%0)8$*8EBa2L)(cKEH@T/B"AacDžj F!P$#SC"!PsjVh$Aг~'PށvC$J5 SA%}G_E x) h<3Mj Aܯ^VH儉 yybŋ(PBnFQj5FQN`s E_P=J6qiKh'@`.yR .!rp !Qr@:ÇČؒ~~7BHK$l{O˚ n@`܏bbe:p1==__F`gOT%5+0:Nd_` )E ZRg<#pP ~mݼ,Zh` DSCQ DELtHb("RFM S-(ixHp'$FO*x hCCl m m0=Xuxʦ+:.AN5F D]k tA5 D]k tA5 D]k tA5 D]k yB<4~7`llB<0E!`G;G.>h ߲jJUpk Q NY>f^ 9J t/IpxVY 2!Yz;1hJlp&6yDZ, T@0|p (IU" G^,E&8J`)~&G&!H(@t !&Q@aoDzG} cN q H@葁1BH oN '`_?|/K dlr >PO &>LT` i&U nN)V@+( ,`:Da" QK-8[@9 8ŀb-df"DP{/:, -2((CП (QĥP!0]B)A ?PzA\ASBZ SecP!FʱE:M191zi1E4"ZLh&ZLh-&4-&4 KII%ƂeƁcA2c@i1i1DL"ZLh&ZLh-&4-&4 KII&ƂfƁRcA3Rc@B @BB}X$' C"}>Hȟ`Hȟ`HرaņXpD>q65vFj.@ * aU/!`)ap!M  i)Wp$A<#ϏHC $0"jS(\e#*2} c];Ӂw_NVAM5 @ M4|Lc:=up,  ,  ,  6@?5(kHkIq@+ԢbG+ԑ_|sXHu@1p?U6M$t^1:*~/&Eg% Մ o@Oasx`AFMQC^E z$5$5$HR2Pxw!m:Lʼ OsEb'/+'-:/^r󗫅] )KS:h 8A `Cs* ,]s8j,ZEEd$#on>N:p?|bצ #(ZGD"#f3T׳LMq7|Z8+iWxB!@c,#СȫYa,"B;YO$:9RO |41,1Uڠc` LVFE?W OWwG5" lQ'SҘn'0W9̗ Oڋ?BXPՇ6VAh3f< xDBe:* _)JCu9I^\Ґ;4yG-8K c 5@wv˶j/oYI@@e(#/)!/GHPG /Pt$J/A@ Sndbn  'CPT{'$@Ri+ X KIwK3T0P0 < "- b Ay$4&J!t F?dfȍ5v'ݢD /B?"(`N 8²\(YbsJ@ݼ 4  -_$(,&5"o%@I+ SeDMkʰB>^VʼnZz*S4M (0yߤ F@H>UUТvS(T|\\BdRj`t%!+LІi4y%6T4!C2D@*J (_HSOM*1<"e'*P*sB'٨yW63i\ŀsk甼E"F/#Q6.7T$#ZP?xJjPjf2]f T(GTz蘴CD8FӛoÖsq4G]Fh|7#2#K VJ A#B%]_gQQԂqF,#$DTTfhR#odYP 4}@9R08sk;EXVj#2=@ 1bNܹr_:Dm6c#Dp[gq GRQ$5 "E#!CUB邷OH3?PfLGi?‰(cNM QTR"S/0ú;1cL`?ë8jBJ.{"|=rqQ GKZ{#['#_3 m#t7"XKˍ[! (4s=WT_#nt#PxV4o@w; >$+lv #SnDD1nP|hM:YN99ODaitT5<@ "(\0$ NH?8j``g~#TcXff c",ʜ:eJ9'Tf=ʚ C*yhK e! Uulhy@W)R}TPhaE ȝ#GKd YtYKJӋ(OABOtH 4ʨQ/@ W>rH0ݡ?N4T^OT: DBQ,b d!@WIJH-E 1BkXQ`rQF1<*2d͞Y1 WD !(i-Ƒ@ E5cC a+,DPhR)fsր,GGRB?j!l됔V/gLʾ~nN5(D]ktQ5F(E]ktQHgOp-) hhK|HɠK#Yk"dP &.htHlզQ#XhTC e z($b39G$K|>aiDpA'X~SJ !@H@H` +S($hFZ)1 v1mUœ&)(/r@JJ8- C>GJMpi'rKhQR(( 4Cl $)@8 DG''.L{dp6H7'ހC.V1b (Bp^/0/?y/?*QRtLV@dRE 0Q"B%8 !VN&=T"jLh5&45&4 MII&ƂfƁRcA3Rc@11DԘLԘ"jLh&jLh5&45&4 MII&ƂfƁRcA3Rc@11!hQmKbGA#}@$p' 8(>I O3 D|@>14u1 4K3_*7K_]7 i~'Cmy3z'9lGy30v'A )N"8C $0C $0E@Q B5H6#DDDA>@( 2('66h@+AbgYYa;Hv ad$ ,  ,  ,  ʧ4@?$-(kPט111b+J%y/ "W4= F\ۻl=G̞wO{*DIOuDfUv8P$34a28`£"Lg$M$5$kHטטטֱ11b-jJhIݟZ'^>QXug$jȌ@ nx$'0,6B?#FbacxTC'0س\j|+1e,h`@`CP1{?SE?a𘉏!ޅ@ 0z@d` J0YIJ059pA2brZG {(J >hmX}O`&a ?"JnI$nH@T>!+}BwzCߕX|q C<5$cR5!b(SMhW]34@HG  i];x ` $PDBjl^íһ@$ W<- yt (@+%"X g}٬B!D }` &{;rdY3 Ap 2/_20У&x{<v>C W6c7-۩'!m4w8@@z\Ԉ U ΃ʍy[IP@ tjP0 ջ!@d2> I=1|0}٬{|`P" E™1B8s0 BP`)W8 IQ@D#&$ =,krAII<'QE UV4<,xjU' (+̭] GD?P ?(',R Z, 4@ HJ/LHpa݀ T')s!b  AbH4n_Un.&m\U)ӵ0˲'$@ChQEJwT|˄vB Q6aQ%bS?ڪ7hp`cX3 z@@ "DE> {`` @ZVHoZ .1Ă3 AD 1Yyb! bNWJ$F#LSzAMEAA= (.+@W @z%1 U%:ƒ]Y$..e!:XeRyGY" P6ddP B"4UHjf! "(SSP P4rʚ|&ɀE]5 dpk#1d؄]:gt$QH#GZxEV4xkG: 0+G5, -e. ,f. 0JZ%5Y @ ?L@@YAP?ďe((%jH"B?D3+!hYsР!By^(#FJ6Ko=PLÏp +:V3ov`Fr`0@Fp # (&h0P8Oas@^l$(+(*sEt,`6@ȓ> " [TaC+i z(+ UL0XBl 2 RbF NN/#g_53APdaBP@FBGB@z+FG=#!0h(@b0AwMh>$yM(v(:V_ $p[9硵hXu ,o<$.?hYl cebbbx("&K  @F % UjBK$a ;KH-TFHTc pY(=F#~m Btv?RZMĨ #5Fn$HY!D(R#5HQjhz s_? *y*)2> ;f,r@Ɗd,Yp!С] GdGA픔q:_;mNBe@?ӥؤ#}"b"\|.t ^~/ H!ED#Rz=PH),ZG2CXD  PV"C@nd)С*@Du1P9( SٮpAB crjiLߜ'lA/ /0$ATQYև;vEuOc$K5Q|̭z?Rl< |_x/Z1z/$v|G&e8L#g)/K0AeP Wjdlt}] l,G47t)qH+D3HN0iA(#M1 ߋp( y2q?ށZ|ror =OOI'آł,Qc4(E ,`&0E-( *p\66{;*(=1@T3/F3``ֈff_H@ 8|J 9@P((H~7 Qj5Fmf' ?8bH?aaaa@  `T  b0bC -2(&a9 8[k;9h?e $g 4)U|TS)?d Sp ,1P@j@1Ѥ@Ùė҉ 2!>Hca  $xʑZC)Zյ` :{~|tIo:EǑp)]x3ko\B#m<,9pP4$ /Ќٳx6l66l{=g!0s9s.}ߟH~OQ5@/n(p?A! SDNL>l8fsCH+ފ/>vx B(Qp5FQj5n pNOcc(1A Pb2 ppP0a@  (P0a@0v 22pE0N^(O 0ah;ƭpdeJtV@T BO'G~tp2T.vAԣB(PJZ$X!$c,XB 1l36a_жrv-?:Q=`FB1JR?o&ڛSjk$HBkK%dY/ pH8$ 1$ )@ hYבh| ʗsMH`DIlByA(ElR):v{?䆥5 # AGO=bLI )K-&ğL~ c *{Sy_ 4`  Aŋ(PBP PPU1cŀ (P  (O)UYs cF7~0: Ϣ$P((QE*s1X4@( AB@D^Xb ABߟ:.ʧZC6`l o{=g~`$$Qj5FQ N ~ p1(1A PbA  (P0a@  (P0``@ @@ D"… (P1JU1y7jmM4$HBdY,KH>A pH0$JpqCO'bLI ?x\˭p Aŋ(PBP PPU1cŀ (P  (O)UYs cF7~0: Ϣ$P((QE*s1X4@( AB@D^Xb ABߟ:.ʥZBݓ6l `llٶ{=g BP BBDnFQj5n pNOcc(1A Pb (P0a@ ( 'aC !Bc(PBPBE)VsMM6$H" K%dGA `H0$ aڙQIL]eԽg"14} gQ4q3c& )A k"5DkDkDkH׈׈֑ a@A,XBI$nQj50D "ϗ9(M))Nmf =*ߑsuf?xB>&44zcPP!( $~7 FQj3`(?ݏv=Ǯ=q\z Aa Dv*<}4S(HcՂuk Aj?`D `3d̄ f@d DŽz?wl" j~G^dGC˼@Q1 0$@#7 F3*Vn9n mLL4`=\`|Db>rNI Rjh 4b< A /~Kj 0\A H8(3Ŷ>jH@1p3`3,8?H {A:[ QAxk?_ 0cv Am94RhA qQcӁKzj@$>T\X,NBՂ"D0R%AI@BUYs,ߗYv;* u9P"|IVhPk~TR]= RPMG@wTT,9?xNsC-Q=X^xlB4R)9rd(s5hr(*PRTЀ@ A#,XBCxO/>.]4$χ~", 4<,,x"*(p/,RG6, S*`|Q!`6>RIHQJ4Rޝtl[.O(D@M,6I1sauQ ~@m5 $MxHU#bNEycR (@  5APHM/ 4U5 yhHwXG~A4RpfPd%!T}|{*;OK863O)cV7}0hƤxVS4yd(6 ඏV<4cFx5cC,-cѫX51PY ?ą H Y_ J, VB4I?$)SŪ1y B EϘ:Dkjh nxp֪&{;eė_@@HA<OB A2<&@h:{H0# $3`SP#v2| 3Yb IA F\6p:s%k p #<-YCח,Ѕ1I~/Å  =P( ?$~PB|e>`|Q@1t _ҙ^N0M̆1KI _I>3XC>!EU0K|Gg.L8 : <0@Y0̂G=PdjE C60qこ4IK&@<^@B-)@P ->;hIח'RHJ 9]Ɓ#X *|  0z:d@`Y}>_E5d%YP B^U1z@zz\&(&#ˇ|zċ1b1@xČ+ }P-P+)988UEE9DDtU9 '()= ܡ?-#!ҀK?/=/A^I$8$y0$BR"u~LJnLhqg@$A_D a8=V*DF (B=*=ˆFN%Ec([TIG<ʜA8 @E#AFf:Dyi!GPBu!_')Y0BP*@C`6 Ed{Dd(>$@H_G)I Q gB OT`A^_ACЋ<>D~5?4Ë@0lzZ*O(A~c0xp0c%HG g  4" 04O(! dq =70y#bB(a*!JYQh`('5 L$'*,`: (~sst 9A` n@g4P ~_&w@p"Hҕy "eF&"PH:7J9{ 0@hXX҇FI'*:w0,GB0P,Mb=H DiU0@f9 X");8f"4@ Ao.$+ @zPu*~'yDUP"SpDЈGJ Hm 4@hdb SJA@}вS Bֱ|}8%Q (@Od`r3[2ː]|lb9a+(|@/^<}1dE%ڲ.a{޽O`2P2R`A  i@4Qw9LUfs!I /E$P0)d %,[%LX",ff s:%d߀ K`$ )@zKgXLG&"M7cJVVi-x+ L{6aE Nyt|#Q?d'8O]Ls9) B~uVS5i6sAV<Z$ @AE>w]glpvmjHPf͘a0L$ 0L& (PH 9 *T4iPҡ D"8#MK.!az5sJɫ ;l'0tA:II(\[emrOfmv/+@Zq3S/rDX9krA98в S|N 0M?(` !`'Nb1|aD >-q@8#HBA$($YyybŊ(PB pdE6B%hFg_:;DbՏMl&łp 0@:/QJ4RqB ;wyf (dG;6MȈ}2<:^,J2Gjw$ꂢ-X" [L6,FjRPLjkuu^t(UZ ,@WW)Ln` |DT#zLYQV Jg&FZZ>Uimjo 1,1AԬnE N "Eqcy̞d'8N2qd& Fg&i3ILf4&i2BD$I%)JcUYs1c9'$䘓bLI1&$ĘS (&-r9,J2BFXl4bi0IĐBZX:>0(I&0 BP%t@}$ $g?.y3R8R*ZA3[V酨F!RQs C96] ,CL&af A D 10L&(PBiiiiPҡCFB!DDD(R3 DzNfb5fWˈ&a W%f:)"Q2L&LF2",DXt]#Hdrq98Аm#Hm)@<A 7c "{;6FJO/? |a@@u[ऀܧzS@P>j-u@ȗ*SԮQ4NV,7UixP5%<@%0 < r D93W5&$ 5 j(Y-R"hW7*{QEkd.1?d'Tb"E"G+#!98~aP26Ap`|+<&۰ah()I/A@((QJc "V<#jBw )P&{aɜ@RIER9O( <`@$=&  GrOhA "9n}O2y̞d'8LdCH4Z~L3&i3ILf4&ZH"DI$)LbJ9c1c}'$䜓bLI1&$ĘbJd,xBZDA{RRd@:A) L)^c2כ0p;QE1 D 9U.w)\M:ttb A |L& 4 (PrrrT4iPѶD"  -SL2cRX_> !S d+b"E$G+#!98~B@p=$w |b4 1?\P%@A: ?F:PP E@S4h4FV Wn9#@mX&XgI,`U1,XB (PB @TP!D$StC-Oϋc֘,(10Mb;4E@ 6`X4@SQ @+ ( a! (T@X@zBLl;`0r!^Xbc1c1`P u#FFGI$nrNI$HaD (0 I9 fz`,fiT$Hp92wp>Rሁ$Af@mMY:b1Pe G3ԐP# B7#35 dRhD}>|HvidԸCЊpB͛鰓1pA3i> KU 0#LA:tӧN:`cG8Č$a# HF0HC;h'xDI%#1c?>9'$䜓bLI1&$Ę@\n"YYƅ4od rBx |!&[!Ġ Z|:TbD:Di[ mfzpL  qN0PS @OE92gXH$ XN8S~ *6D"7JDBpSY b@ @ b-̣)|ύOn98`hj^L!Ai_xAa~AECX* X@ <@\F#]PA#_*׊A*G % */Ww@|A#b@29=\U-%JJ- i 2*+<|t> #,ReD(&t5|OA.Au*BV BH~`@<ˎ)u>5y8!( G9Bu3 W+ZRpzlX`dGT*UP D@J H:$FN@-+WSZ`eBnGVe/,\XIJ,I^$)9#8! ;cv.?ɒ9Gh 6ZUI3ܐR]Zv@5شLE 3h `F"a)8hY#Ta:X xymZxpFCxL@" k[>:t>ODh.$q#HG!B P1cO䜓bLI1&$ĘbLIL`/~pu`B|Fɞ3,Ҿ?N04U2TI6J@D@:D Te/@t`>|A $ ?01SrrrT4mD" !7 \MP$|`>@2Ld 3  QÖPiw8980t%2@HB" +WNtƌA4K+&h y}}jB  )T W¥@\*5&Ix0""RIf4^󓸞@#Og񰄀 'd|>`t5~0ϢvTK hQJ:}+[6M%|/`IgT;f\@7k/ *ھTQ o_ӐӐ!A X" 5)h! 9X0TA`CѥEبM`j'p t`#g (<n囤T` N$z@!КulGzFFk@~P%b@j0x qyaq\|. ,%@xll..( JQ !B<X YnHyMvfD 4U k0PB9ց6 !Rn]*fs(D wB$ QpF]PRoل PE*2hRZґyb(aL0j)f->4%0p D fk$"/rqƒ'|.taB{> fCsФ"%!H@@BS0#ni00/6W*mЍCnY Av,*l( D8xY n + * {yHeipQPFthDP r 0aF HL"1(y3Dڣ"cCCTcD#T uu X`ũ^LdZa5qc$@dhVrdk8B88BFtEj<4(#R1t9`uK[a&!4A[< *-G8MR*guP-dۈ;1 Kj!%_R rH&{#@p b?)?H>~' P{-K0dbRX^-73̋!&BL !D$ tRJI1&$ `A@, D?~a-{(p&#(q1O~b8d!r$ÄyJ$B[ ^i)/ǎ>!$ S@t#&Ow0~p  $ :t?cPPTJL@(8.@@Ia5_ȹ'QOΐ}H I xgdII)"LI!/ʸ " sG@s@ >8Gk\Q H%7LP-I,\+#+hw! #UDq'ݴ& MfmpXPއ.Z#7E@D ] 2YAP v43d4CQDUtN@to e#<E z[ 4RCТ"KBK#ʪ?W&HŲHӵPvH`X!B]FT(vS zAB  M*iPt zacp#g"X@R $W PdcNC@%DTP-3]:r `' ' '   ̥ QP@ ffw "W1ֽ@ E|C9\/!E"%^(Jva`9y $XX"~0ά'̿uhH@Hl*HՖws×tL$hD;<3r/_!4A[< *-G8MR*guP-dۈ;1 Kj!%_R rH&{#@p b?)?H>~' P{-K0dbRX^-73̋!&BL !D$ tRJI1&$ `A@, D?~a-{(p&#(q1O~b8d!r$ÄyJ$B[ ^i)/ǎ>!$ S@t#&Ow0~p  $ :t?cPPTJL@(8.@@Ia5_ȹ'QOΐ}H I xgdII)"LI!/ʸ " sG@s@ >8Gk\Q H%7LP-I,\+#+hw! #UDq'ݴ& MfmpXPއ.Z#7E@D ] 2YAP v43d4CQDUtN@to e#<E z[ 4RCТ"KBK#ʪ?W&HŲHӵPvH`X!B]FT(vS zAB  M*iPt zacp#g"X@R $W PdcNC@%DTP-3]:r `' ' '   ̥ QP@ ffw "W1ֽ@ E|C9\/!E"%^(Jva`9y $XX"~0ά'̿uhH@Hl*HՖws×tL$hD;<3r/_!4A[< *-G8MR*guP-dۈ;1 Kj!%_R rH&{#@p b?)?H>~' P{-K0dbRX^-73̋!&BL !D$ tRJI1&$ `A@, D?~a-{(p&#(q1O~b8d!r$ÄyJ$B[ ^i)/ǎ>!$ S@t#&Ow0~p  $ :t?cPPTJL@(8.@@Ia5_ȹ'QOΐ}H I xgdII)"LI!/ʸ " sG@s@ >8Gk\Q H%7LP-I,\+#+hw! #UDq'ݴ& MfmpXPއ.Z#7E@D ] 2YAP v43d4CQDUtN@to e#<E z[ 4RCТ"KBK#ʪ?W&HŲHӵPvH`X!B]FT(vS zAB  M*iPt zacp#g"X@R $W PdcNC@%DTP-3]:r `' N N   ̆ QP@k ffw ~O{Q.KW V/1]ܧBV+Z[iP(vfܒƈJ|@k0 70M×d" 8;<3r/_ 4H(Q AD $H(Q E d8B*(0&wSHp/l08?GVEY(&zQx1܌@$v:?x'{Nw(~e,X!CC@p!!2- Mh&{ݱjY IrI!&BHȢ:II)%$Ę@(1@ S@t#&Ow0~p  $ :t?cPPTJL@(8.@@Ia5_ȹ'QOΐ}H I xg]q J0`F&,zO䜓&`A7?̼ p-BNZ(Xsuѹs{;d~oyԀK9A`C_! E%\K! €&@ہcxqR6IrU*Uj G<ܪfBSs4|Ƹ>,丟ID#,%| y|w['H$lLZHPI0 ѶؕH  B_%)0R"*; S}_LGJd`p.I娭* uaֱ  d$ht;s,b1|7DU1c1`"CF #%EDR`0PPE/x&$4 H@X(rJ)POHtaBD{%q1. `ʦxjahdC)p tx@ɝ?ႈ,*pip`PYpY@Nh@8aI! Ø1' `H.2!B#`D J'f@ A Dyyb-a"s@ IH @1Z#jr @tGCC 0d) /aÔ ,\H.2cJ 4l69}PyHG6s%PA9C"gNgZap 'A+ 8b>?(YP8(|A36@)Vh NQ)ʃHw`b!c $a B$0w@@6 p. DGt]>)@((/d t44i@(K@$ h/Wƍ4H "&Huu/A_ Q1 x^~/? P @E4t>T O$ʠ B hP SC@ A S '-68]7@N N u ( (   QP@ffwJGD9"XlD9ӿ36))5BH@0ySRdA7&֟ɽ(;0L@?8#Wv/8-ݺdY`kQ6|. !J:pj1t0h(4Oi0$zHa|HD 6? Wr0KrCqrz?u$2B&P%N9 eA#)Z԰BoG7GZt`> %t((PGOOHVjm!P7`HD22ȱ\|\ u #"`f?>{$j=N{ C?bz-+δDbPzl 0D"&*WំrwTSe !C"? ww Y4 CLhY$ D1 F  @4$ 4$I?nFQf>H| bٳD`Q1z~̀"#~`I B?Ѷ#$h QӧN:f  H $V< A A; `5  0sTC4}`&&OំpgH"j3` ~ xCH3|NE0! uZ* xGD$$ 94( /L& h?1 @b\&!=8!øecXĀR"2ȠE0$h(J1?;h @HH#@@ D#?LFPL }0y Hրh$ I?oc PbsE!Ll0h0@5 ك0fM_12I0N('c%QyDZ3 @ f`  AϒKl`8#@PP_H)BAABS׿?N< 6~_}@%a&#TP h44[ 2@@GN"  rBX GGX"6v`&KH̐X @HHϿ Pb(1A 1Tw@c+P1ghL8B@!<b :iހX @@ K'a0H$ , $ OM?N&Up2sc@w apP@44iӦL @LB 5 B"'H1`8mMLV{p'8(1A Pb2D gm>@R{444ַN:t_`, abŗGB<5P%0?apm;@qڟ@ x׀-`V#}(`H 2'L  @((x~@ } @!|0N`٘N~PPPh"3P.4ă9wl'u ** QP@ffwʯ~4UCdb@s6 NYoHFs'" @@.@C0ECdqu=Mm.'FA(%CAڀ^:^^|nL7`,}hxA12T2ι2;h I?u,ehG `"@rB` H"jA6_@0D-P*. f8F(X \ /62Wv06D5x@ O',T  $dd"+@(4@3@y8lw<i314xz b(hQI}`v f135kn˩6кSW`$  g4Z~L2! CqSؔDD ',2@2:etY,K%  A3 ffl/qj!q8Wpq~R  ( QK'a0H$ P@ @H$$I$jbp  D@ A% :dI>@;0fL_^1&$dU 3Hg 9^`8@CPg [0!O!$$Q@` 2dd[N3>|r1 1o8jf!/Ȓ{"8 Ab  $@$ HHc>/@t Xs2"(FDh) @: dCc&L^r󗜽yh b0PDS aW$F R0t-^#p$`D $M҈(P AABRzߟL@?@P(((QGHhѧB 4?DʦH@@ PPP> GGK ,# ) A ?O0P)NA{EEސ:d FL3}^r󗜼/9un@( fxZ?DŽŎ upAh pQy'I ! QH_ヂ"$@oN:t@@P(((tzzm?N)`3PHs?4@(@E)a0>`G  b#1}!ؙ  PeGIR3q}_r󗜼/9wz~x@h hx3ܿ H1 Ć$a9a  `J VDB h h444ioϏ:tӦ`dO 99!b]Ǫ@}n5!/H&C   yybŋ ~H @HHcX  c0^ @1KGN^@d !ɖY_^r󗘸Z@1`qT"t@0fgW1:Ip P@@ V#'G^@8 M1s" '0(  R~:`qD\((Q^<   uFDx  PPPqT z:t@d A s, zpGE@d `ddɗ}^r󗜼/9y˯p<*5aq x~&<&<&4q>:tӧNCǃ`6l66l0f 1 P.C`|@( R'a H$P `X ,<#0&0 S ʷM&1V`CHiih0u'1P= yA !^+1T@ O (l X   @P ,t=@Eش@X "4@h A*A`6[  !!  QP@ffwʲ}$R:2 vy7cOlt/-v`P%a%@yyf_nv.a\?BAfFxK?Aed ?"PM{6Y2嶥!F3$@h,#KO+͔J 980}XI  9F,Zx! aĘX\5 q3qe`_/%gMVB >mrQߨ>XlAU*CG̈}G\" ?!@sx $#Aa+g0y{Fd0fPG@v;`3y7]Mt. 33&KOɟўf r1cl"B0d2 d g].K%d@N@f3 16='2`v Af333gK{/EėLK%ZB`xHgƓ;/ ȵx 8X1&DB,2 /QAH2`:@2k~||tyq@bb]:Lǜ{ FS4)6;-   ~Xb'  !cN``u (+KBg( C: !&Y_ OrO3A@uPƀw;fTQ @ APVC/bLlx!p9 O?A qKID @P () (z=:z0> (PQ1E>k6j t~?f<!HPPP}@'@ $:YLѠ:J@/C$H*B.PsGJb@l dd}_r󗜼/9un@a8u5ag~&<&<&4q*@ D  |@h 4ӧN8`~"a`l66mpz 03dBNǐ @( ABa0H$ X XXeL 0L&&&H ?,qʨK+V`Hk@@Dp80B|G@)(A@(}c@E@5 @ *<: .~蜦P 6 6(I6(wQP@\ffw\_  ¯,G6΅7t2j % (hR')#/@t $`n\`lMć(&& EC!'`tCJ~I 56_2jK@zF$;Я$DC q) E"^"F5Q i90D =xC5((!`$kE Vf@u Q+LZw` < O@QS %pIQlYETH"PJWzt}y?>b?Xt$$=K"Y;D% 'F0ҀcCB !AC) "L H * _HIh}$I x ?@t5h6`>4LɎ7Ppuzsue)nM )'w$D( <1# ; h{'k w?2L$I%QXB ebGQUqF"Pffff<" pQ5ǀRbt<sXf'}`Iz'^|A%X+@BeTPrft;G7@k@1' 8ـ|IaCm*g(Dș5 L  b12)0p S¸ъJjS6[CS1}<@Zw(iXy}U ԍ+Lb 7 @\ ai (-$׀R7&o`Ҭ(<5Lwe)iB}0 "*S@h RJFҡāJ=CCA#GJGO'\GGG1`DiO€!D記,G,XB %g `3'A)lUE/uxHL>o0^0 /aȀ(P,BIB1b %s ߲`$į )Ȁ28X#Q鰉?$U T`1FUТj݂((PV}5.ob;WeArFB?+e@ DHd!`*+(#p_<\ @ ?$l%Z7Hȇ@\o EI>h{EAZ @!R,Y4)Mv@[!wD!)/BpjFDrԯ;.kƊV:EpJ Ozd8&-]H: lpn ( }2BTKi< ^+S^@ #8Ą P),Ę3 & k~B`I)1c 3Ɍf]."$GP*)+!Cpd 8[xACB:B_,AgU!p!!`(߯ՌC?㼁.@@BEHCS(n ) Vg& A^L-h. $ & Y߰Dg|+.Q}>U\H~!' Ȣ65HCD? :p:|YfAPY5| X4r~ב)Ǐ  MlPA@   eQP@8Jffw}  g5d4!yj _h(-ѰPROk^ o@_Pb$OtpB"E=?wz00q0G5`h'( )ߞIS g00%؃@/† EaT\6Fku9  5o?u`+1b GѦ!X[FRLla„L8~_ĥedąE (>,5gXw7rf/>0O?/@r+\ 950בh  +$T% wHEXD@a563*A6G䃪`Dn>`p*Ѝ! ШP=D KM6 ,:X͋Sā82]m$ pT]*@P 佂DzJ&)!r?M@w̾F r^7D@0e ,W@B/Iy[" Zɘ mD!NHiz](H &@P)xE  _ۣ8cl8z7p 4 +H EQJ~@Ar!v./Rb1A$B} `Rc@ų$3_h *a!@ AD.Z4>@UJ 0}ERb@cܢh=;5K_TPr>4l4)"].A]L2elצ2Iq0'̶#/9P=XHP]wa7x *m縓p^;@Q RB%( ? JH*eDJv Sl$clim0|?TRUp&0РsT`qyBmO)HF?h?Sy 9`qS7BWOՁV + @[w5)`={/Y34 QAd-dmo#4JF X h.BZ8{opؿhSʱ[$A( @KD?tˇ\h$fnKQF  RRuEEh2y,0*DUz(@e HhEKD>_] $X4j"a. ۧPј k^H@mǩJG Ĥ)~ 7A`5H"G!Zi 4Q |uz V+o. !R~apF5Y NgG'X1x HX$SWӂD^%XJօ^+' c|L0(;oώH YC?@$IAJ> KWQLJ$ CtJ3_OHj`&(h*.U08Nh" 7 iQb,(>F0@>$3ϰB?z2P2uR mL@ aDbޑ`AOZp`D & 4W|FP@R16;^__O&o3"B萏+Ee*fPt>O@4LGK|A=.M9v%982fz옖Gvf< ))NC3!_Չ΀u( ~jOH8UhY~Lbb.P,JPS$* " IvhI?5CtdADPlGc>3T~|fa D+0 pgbti x䬐'$8(Aڬ崤QAq[Ey|Ϟ0059U vmBuOMBD(b2PP%40kEj}ƀ[dž쒐98 XEh(@D|~+'74I9͓#@XXd4I$ a44EzV&6WoPH'(e$ &) 8֬@iIJqXiRW >F*)6@4$%*(EQ1ov6|x@ᡁJa2ϗ\D0(Zl RR9)1 PO믟IO"܀!GHKòN#|)_N{Tx]jϙXiZ !qmǝ*u)P8CJ-X, #,H4l)*#)PZ Q )EPR)9 LЀ@N$䮍)Dݐ(FHS F2Oyh&엸VPrBN(rjCW$xjcE3X8`:k(2 AT.2£h@i# T-SHE9FF䅐 І)6T 9N $ThR<@CBȤ& H  @*ԏˈ +#?."' xPb#a;de91KGV\DJUnRܹNuЏSM⽰+]93(16ηxʤ*Ig U"@ . &!b^0J:AEJ.;NL3ұɋ۞R AgwԵhh "= 7bjêyb҈ռ϶nqSbwDYS@8   0 *6@<( $ƫEThbPAP]!n$h $8өTibe `Şuh,"A IBp-q {a1ؘ}  &-,j?d:jZSP(A8(!@y2 =:t.MZ@'E=l6hR TH%ICNFa^_)D3$k[MiQцT(fႠVpW9>Oc!r !7s K"11H AaNAO/6V cL p 0N0@x #hAUXA*<9(0AZ<2~[B?H?!~CéCˆЄP * #xM!A댉`< b!@K!:6*+p3C1g#pV/OM2}JlCzW8~x3H)L1xƔQ ZhO4[ *oԂ!$J,"qiH?Jˇ"p1J$ I)XZ UށHY b ɂ`%t9_JGd(e?MVɁT20Bc_Nq87@R#nPȣHf PM,m߇1@ 8~l@! ̄PY@F2qh= R  VV̯~!eO/3e2ReR9oB$2H2=5!BFIHXG1U / d|Ji @(6c<}l@ӻNCd$,@#c@)cP)+B@P@8|t+%X`Lz CDPh()N h~SE%P ~ %$ $eE :Y(VhRoLSOrOx!,z̢OEO{>$AHGB Q@$eP Nj(p"A-@|,ƄX(E%&#DI,H,D`C>AA<,˚Di<";=4c-^X|lр"X/ɿM9f 1 dE@?ۈ _ ?썀0$` m ۈ@.W-,!:P ) \`Ap /`NFeC%ա)Oh:䟕ٙcStuܐ`Y (.O,`c{@J D!oB09d,Hpj_BXM812%?XU!tn:_ 5 2!ސr/XO(}?Ǫ%O1`FCg<cY/UO|psCC+_ dCq_ XrܰQ3BtвHX\?G#&t @Vnh\9?/eVڊxI# ĭP+p1\ rG j&#C8B? Ƥ04p\.=@z ZZ3 )\ ݑNA+@PAtXAP:`,6t3C4HBЪ;@N;D.EA&@!L-@A5xv&ތ2 m@z5te ASӬ g?IP 2@WIMuzxLHP f~|D|X [tbņ)<04aUdy"/oPcqh|' DA” p``wྞZOq4`d@$<l,*hT U}gC H  ۢ!(zgB$0SX,< ((?HхHCs`4i*:h  //.X ʃ~͠PGL*LY?3/9Zޘ `0!8T(jx*P7Nh G@_>C<@%k0 !B@4Ҁm\vB m]xI h="jM@TN6 ?GCwrexHb#3hCցM HYH% 姅$tjRv45GD2łz ߣGB@oR HHʗc:RIJ`64Bj{D:(F4J5 _B pE?(z,*Kw0 i$<`-Q(C,{Q%OVhDQ'q iUeB*w8`Th.%Jp0Œ P!4>$KCL%K9% /Su(+@(ĉ,Ǥu]f_R!00!)kB1"s}~U$%SG`fEp]T! 2QPD i]! ( st·bax  (XUQxFdX&'@8ڎ8W0?Qz8im6߀`~3+*k@}1@ꖀ-YU 0\@O- aNMVVO?q0!C3n8dvHPB@/gWkŢ.V0BfT/!) )%M! -J +!NM8r˿[A*`!B3x ?JKpX勡AY0%9(2 P(_댗ITA` h` za/<>̲Q@qF !8[5M BQ| b|t|D\` )B!0Pz@* hZtRA*A\|. rJ3Hրd*aP2#E!@m+p`PN%E逃9, J݅$#MPD`-z0ZlWC iP[dNq,۾$Ć]rp)(PGM/{$/GkeZ940ǰPrhyBX)$R  53/Ƭ+܃+\+j@lRv˨` cb#E^~/BB A=@MCzTRBL" Rz&Q4hhMʀ@B4ԭ  jSF[0tڀhLIMq9AV| WP R_ c$c./G: Pa|!gƬ/A`!0u@-x 4GG% T( 2To2J$&(AL #B0%eIVGabSh"\9)@W JQ5LD#NĈ)AN $D4ªb^RZONB?%/$dQ!`1#MQB8KI1!KdB:$@ WG qix B $F] C@ b2\B,:A@"DHX0`:ub@ ;"`/KlyŮGAP9Qp##HдQO@jϿ 煀?PLd(¨oy'c( z@x_ 1GRX:הCm4!t}P%^ ^b飐@T]($H?XMxiQze kq5&4 Ax ?(0#*eFz V$ @z TA@{͠ZPڕUMbTi&] c 7JD"v._3PQX|LbP^ ! (CD4E?É]>i` '(Q y!@H (/*(KcT1~JUАVG5?ho-kVH& *=EWb zBPP(A@}Tb6{ϟ<T s!e vLB!AdSv= >!AWoI75 H] }~3ėpH |_y^~ Z-F\',v`~-Dzjjjj=A" i R  'B5 AR h/ @WahY!҄ä!GMZ)P D7.*tkP/dT[TtMWo@x@(}{L PP S".@חBUb؁fMh.<~Lm@!+2vXϞ@Pb9 [4My5anDЪZ/ (&J@,AVy(f~@Y*GNbqP &(eCt!(AJP  vJt$ hi]V"\\vciA4cA(}{/m$+(@:@$IA`}OE#+rHl_HEr]}q0dL젣C78@16<_PN@؛=0̋Z 7o`1r0 !X$h& eIJi |r#(4 H 2"G@\ 1anpOЏ<2 ebTA(:)4@Mb3@?D [" >,Fɘ9 @3 i*iD@Yji A]D 3`]KHR-5BBPiX)e8У7X*㙠J 2-t Ԭw#G YVO]J @<@AH<((?b֚mZE@[ĐďE T GeHH A1'Pm IE5.IMGZUxkPGF9+ د/x fuNfA*rjp1C/x/?;)(+=JC/Ь\Xw҄B/BADo2^$ w?#֣(!1CRrĄ"ECI iUQugu,XE⎠ˆYuU(LP4zE6t&wPt0 dA h3(^cд~>uiIBu{#9@Aiod ? 戧20@F_I0d@ O=y;&ɨ$@]"0E[6}Pr6RcV 1-O0 dh!P*vQv<ݚnv" ~\^ 8g/_StH(Dh5*`Jمjm+H"S@,eGC/A WMaST|_A a ]acf1]hDSu˯JpKx {ˉP助sԉ~Dt%D!$'ZNC҇ǂ~O;C~᳙Ġ&_; YFJ{anJo]ì' `0)d@>O |JIJ4I @ F%@B,&4Dgpy?F g W:_3W$Xr5[E +Kg f"#ȉ7btDG|;$( IBX &e5X4@6CUGqJRXaD$SD!SCc*F-:$`hЊZOF&FU΀fV/ϥ@j e-4BD+h (C?/!/Y :f |2]wPM]bu r^0sPW@h b„PHQ+Bhcs?fu~ %Y=[ crD4Q}4 npե6a0%BH80Ptp?+}pTxJpOc̿L"_ <dV #ڐAh$"A Thpł !m VbBhD pcb pAM8h7`fU TOhD9LjC3rhQzqܐڟ5L ,dR3|+fJw^Q n%c/ ޠ0 ,!,?|g09FWό*Z屧MOx 8)Fx̽M@P!(CdCd@1RC _HE P  p@v+4 ,eR WM:$i! t{_S2X.]6B $NP9NhC RCI%b!P PQh$J+P>ڽ~q?$S| ! aIF'2R$+<()@:hhd z@Q*hЇG; rJ/R+):گ/f`&E:`Vpj9 !Cޝ7ȯż̄ĀTnM3 ꋭ8|jT!$ݤ'H7-@R RX P1 XK4>a0 " A%o R}j+ aI t7)5U ir"O b!)9zU6zX !DgPni  I2qH"X?l@gAAVD%f1 `+VRg }j(%@j=4`cc4K %Ɓ :_QG0ߡ{ -yoAgPE?c@a a+T-< b d@x6/ЃA`һPa c)`DHH@<# TB@ |G2ETj;w_2ug@2b3H(%?e?JDBI :y ?(A;5&8D?9.8ApHք| "btjS…K@ $ rB8B 9 })p$Z(@ALAICh ECtTtTtTt![B?I :AR:0LPmΑ_ c/|@/ _P<顿~O~ Q;p1< A< U7<hDzt9ȁqIH)8WhOSCf<HmC+y(/ Ukm5P0&GWh3,QlT"?倕h_}aD.`34A$/PQh @r b_G%p +y_XIG %toٸx*5vjB@pD`h 8(ωM?TZpTopL^ޒߔB䓄3 {&/ wwBiDy |بmPbyϜ$ q YcE~Rz~ |B" d ¡'AH^\@xEZU"(TB6X/ACTpu8(Fht0| |FTw|Yji_.TTB?Z< <`,x/l\!T_qدQdNRTFkY!yJQj,!NUb?H4t"e.eW}޷&D S.?HL3`(\ dAr! LbA‰j @Jd}Q# 䔬u0PR;K;kZ@G)/JK&ULyAiᇅXH1:"*Ct h1$@ tT (XaHRS4D` `aF~R@a? 4@pha$Q j(`@A, &P di(p]@H)X6=K yêqQ 8z ~0a<45$+ d02 mr hEd?ǀv W]`*n>|.~׌Vp_'jqx p\~~>>E}Ogغ>**Д:2ʡ![z!F`AP$}C O!-$*?_Ŕ:44z G+ȍ `>ĮX@@<@Äkd:Qo< *C-7!ܠ !E__?|/(fB1_?s ? yH Z494$wG;Gq| !("R X"u@@HrgT1&ԓx@^{#RSNp[n4"=(輁$聴R a(Kr>%HJ> ')tkϵr!وp>KTv` D2cn  V"Te/P@C 6p"( *+WX & N j9_r@c r1]f( Aim=ʌ0KZMsI#)2X0F$а_00+h hZQ(J9h[łX!~h! ڱah6 Db+4ǻC:c[BD V~_@c@Z0)uc\RA#1K[XAQnc PJЁ Wl0#i἖,'+Y[T(a8(v Ѧ2!BIW%@f Ld+t3 *GB)H?>$ʬ| 0bB$W80h.쯂T<TA /,T W 40: pX0) ` !Aih D@QH8Mf=䌳t@HyPe!Uj)E҃Ok-,!yGQ):bpUW).GM#!ˬ Q8 @`P03E Q@i '?^цo6h 'i m .NM.-@qA`V~U$ AnkcYq0Pf ҆;@32F4RQ0HG݆%RCnxbqHEGYhK' F4d.AʄlX)I_eU?Kެ($N‘WdkuSv[խҖ) `nH ps\J(@B^V LW ;+$Z4kуqBs-1g<<DJPP?mPo@$@_BɁFBB +gFi,4:q1 'QUPnkvG q<=A6_`~^^|~#ENR=FbBL!; uo֗F՞",p P P"J"*ޛ@nF29X%:t#D^D^^A tBQ ,yy QE LЄA=L `A`["9@4Eh.У@Yh["3T"2Ƶ1!j ,$ - T)JP@ǫ ~&AJn4D/yI59L=Qi,6 ])AG]k\v&ZKHŬZi:a@0bq̕ Y@D~m,񲰇d#:4f \&nb֢ Lfs yo` >Y*$a@*q@u/tcBseTM\⭞<,$,z5 L)H$PO'οGu*S2ԣwҍ$!!!3F*ADrXʑA8 j}Ea\1o%w%^I+4H+ )D1P X#TP ŢtRE Ԉy5_䍵C`~Q*!*Z!E,@/%(@ 0q$#a,5P)!HB4ZcR9 zU 0$Z0IB"0hPqA  ^H^x| DNA(D ag$GhB4-A-D%Agdb/\|Wgl uJPft0w]$$ <$"$Scc\=E9T Zr?EGtVF*Z'}ldbm/9)xX) h|3c,i^E8q0w/%qHnr  8HA%8tHH : $Jey 5ܑ:$r%&0 \5" %)J@+4 `#4   ]2PU?PP@@u@A)H?K""/Вߐcc )P! YZky$T\ZsAHZ{9BRU~A J%}U-!A!E$[$|e 8 ؃QXT,s^TDUI1y3U 4dxRio` ^(@v Dq(fV(z0z3AKJ "UPlw͂diTAƖux g ! ؞DJ)^bĈ;,A **]#Qwf-BOa;C?-D#H8f i tp[1 cA(t@lĔ}0x]_E qS:q0Lʂ|](VjDjbSg+_0ѩ]U G_FyPX"7> <АC# ' -H T2Lw +j']6~L1h2Pm Iy$"ĉu(+Ӈ 7GV"eGP$VPނS?~r*2M07Jw|€.P/1 pSxlR~G`2Q ?4 NDG+ĸtX|Mj.4Pb iJ5D$?BKoRg)oU?ub~~ȓLQ=p+ '`9Z5NJ5`TAJ=P+d+g5*%r"p?-H$3¨eAQJpx萐j`ğ((AvhJW7t c*2 z yF"HU][.E1 h@A;& Γ'#^{C#GFp ZJEl0 !r!`|/ A.8!8?"ъD C6[H ET? M_JT !HQRNHhDZP!AB(*TV4b !A*UEE]%^_Y0b!Siv5H|yPyHeb㧤ˏN & ]j+@]4#Ü -X<P`xg *W8$8T"#4wR0M 3,HcD\4QiUtY)h%SH%O &A޸2M!˃T+׃KB*eT@zFu@4$JUQXR @ p6ǟhXhPT)2$V!&$M(H}:DS?ćSHG IC|P,`#tEy@?NzSU`A?D) 䑰`?;aܖ,HB c"5xMKP[J'P$o˧X/cq@>XWCCdC"c } MHSĠ"jm h Ȭ ?xI- ??qƏ%^b -w/P o|$z\4bhc7gפ`8]=PW{)!& MFV_P &T= ?Ӗ+ g![R8j֓Pb< U` yx T@bp +};%pP$A o"f.lQd`9 8_o\po+}4Ną Z0Jk |b2o:@ _A~zăX>oWc)b eq`7 |pF81}}pv/$]ؚFr`ў.(a-,ԱO]3.3JfT3P+@ e0(T`bAP-;'zT.P>( 'IV#t<"%84(UPd/"B hR'DM Ly8p ((@ B{hG00<HeS}`2]ޔzG:ێ#}Lց첆=O90cP` ~~nn`xB=^ @,Eڀy pM TbU "Q2>7@Q!=HO"QJ]h%@r>A.o0:E`GEi='0߰sIsAFĂ $THA# lB~BRsU.O\?#BlSo!E\n0ʨ$-ä>)K3 4߃ĉ(D@R~ J@d6._%j(ĄOcHV5b]& CztPA@/?.HrZ. =(SF%E pEԀSB  A0& +? ?TЄ} ~|ABj0(D``ChH>'wv* 腗=pQW0 4a5,k&@-%̒ z]\! !u!u C~f0 R|XHg8gyQf\1 74A(! Q9R͏)( !Hm?MB֏j(, )H00^pg!&MQU(3A@A "fY]L!@@C P-]Vc4ajhmb Pz |€~@~r3 A+_A0 c"'m60m?\ PVAZ5hH1Ԩ1H4EHnXyDubL 2"7} !VzEb.e?<`(4?'T` 0h l 戟x/J/P(1@gHQ~{ A} @?&%&RT@qyA0@Y ($=a$D&w\m7a @Vo`?2P%䟞 Z Z:hZ!P+RDP!(RvY{d!#|v@,|q׉Gm $-ᓚ(1 daZNP:%ZX0iX< ~"PBӶx0[߂ݤy`kԿL@xpĢ G؆)X(d}lI(Vn$Hc6^ H0BP3poդq@y7!Hxڜt#?M>ChQ FF#?pXR njUoKǔ *DyF2Ut9q Q-4vA!"IqN`'U($(-VT!j%lkXx҃ sI)PGQH:šj X($TeIƁPwI( t|+VPHѡPF$#l'&R<@3 dX"uH4E~*ZM ǧ0ǖJ>@f\+U"|Q(GT'&Čt]Ո6WRSQ%4B CclQvGJ#sF\)#&՗jb$P)pL$JFRZnsN`Q?*sM>J.(@5:ER;H1TG# 3̊C(aHŌY;x-eUwC)+,H@Q4H H(>MW% jR4? ~ .$-5 Z֋a8V8Db$eVH~--5bd"l9 6D+T~[s3$Wb(d<Z1Yta.#capL7Ph0$'ؤ:8<~U3U R̢Ygh !9Yn5ͷҫ,fRI:rYbd7L3Ùd1@>IH&TKkp+X^B4ǒyr AHf RKJ$ /pF LBXdBC! aAtf#3k@1{B1W% i J*J A%4E0,Ƭ ZX_n\Dd9I Ҽ=FM#V!VǞ(j>n< l@t$ 0f4Ӝ-DGA0(2wJGXmEm?G+V?VKlfN ͢#W^RHQګc6N ;8c hB޶59Q.3U:!KSfHb,wsdQ`7HT  BAG9UN k$84 4eyN9NH2:I`HX u4`0*Rh ρH JFn2 `*1CP%E&K)8J@GAzAP! QP\r B)Œ1$Xr޴;L(# PRJ(LI!p$A#`Y  4Zu\"Q(`v,J v %,Db#řGдO:we]D6gJ`.jB]d0Rh3y٥aPp/B Gp% @bE oQ@M 02 sWq:3aD$0xhhJEHҴ)fO¨cD)HA(-,&ދ٭W  .КIG53D~LDu@?hL(Q4]HdA8=I@\/z 4PF8E'[% %BFN)^X,d0YB!B䔎!D%" yPVa;k F#PHXdR%Ad ]npztZ(q߅d[P%pC W! DZeߢ^\`+:-pZ =b (AH R?`xxr( jli-WI"O=H@' AB*t+5(@b<Qlf) *@IL:~VvmDLu ]r[Ksi!?A%ՈWE )Z8PI@T hpǔw(A`/p7|<& Hbc^p?Q&ŀwZ@L%+@9F>V)@BB+tZu,< vS bA !NLihr0̕JXL"p'd}p/PB ^FNERq?N!0|}nҠ)S%UMF BK$h\ J~-S53Tt-(bH=V0<2.I ZY `FHݠ@PhHѠc8Ɨ ;nH%:+(qP\1aOc>j1  8!~m,b?X4AX.P qw>d NFHk“֗:F@B( *@A"!0|2 ]kCDX#Z$S)\u)\vᐛ "]%]AP@" NJbMXe0H@]=6V{G k&xMK<iw;@ ňG@ xBXZi飬Z@Ahk96eЏSp`X JȤ-ՑuT^Cp(EbGÞ3jj] aUuQUϓYPJ?*z_ td eՐPzqAe} *Q\. 20(߫ "TKv  *J ($ӏ#JG XLAt`Q $d@dP$]Y{b*+S R"AU % |A4 FPUCPz#(#H85JtԆEr 1Y 5#Hh$t6q @9 D`j 56AF <Gȇ&hh2)=^XA&6wnb I@fɲ 7cɆ:>Rʪ]PA.H4G@$SP ^G4<0Jt>ե Ehu0)KG#uw =^@iÕ Js4f'PR(&3CjG(@m Hb@h $&.u߲:w[q*Ii p{(%sIK(X%)+N"L8)A0u4KbO<%}7D5kM.Ti|zhhP[$AW$dzFW@ @/ u9huDLI%m9&C2(>PE$B- @IA'AA88Z G X5w[NlrH8^]-hMbYlx,8ԡ將~Xh|0-]u)N0 8i ʳ/1@w2J~FKBp"Ad_>? #ց i?0d#VD[QL ̟cbD@bk|] 0$Hm+D%d p\d2DP z?X(H(WđLE`4$=^0XE; $(ק\Wp($!%4 ^Aatu iB> qhy Wp9J.1djє0?ç<1H+2c̟l* )_he9L{QBGP J~z DVP" G$C /o*'fF EHʂ5:{'s~~ DbQ020`?p{?? @h" n>`.˨\pH 6ew \J` Ӻ< .H~e67Wm V_y  lGlXb P/!@L 7l]G؏<@'uS4|$V(wH`݁ZGiK4 ; AMnaӜBiA _>!LP ԁU"c [A Hp hX+I`N *Zj@`!$RHE*|n!!!!!AP |u!Du3GС䢄PNԚA!QG)T K/@`!8~@aA!##$ҧOX%|!BO-aB> Cn)i]AoF5+: E dYK]A۠3=yD@??@vHTBQ d(@̍A)`'P#'H";~ (B 0#˒@6 Q@/P (0# MqtW`v4201$-Dhe RK"  :j5 ʿ a:T@#x4 hBz`Y96T@Bh#{"taY{Q.Ol$}XVT3`@?/qbp 4.Aۈ@e8)"" !t]Oq}O\}O]>q]>t2!cQΏt>ϫZKGj-LIPU(atT,Bp^0PzRJ?m|#'ÿ#삌_t(nף*(7@L0* K 'ж`d5qgP1b q_(S9: 9+?}X\B&ք(w뮁 vz@E5/4_@^p 7,I3lf% X@"2cZ bC%^gL% *}J@r jϧ01^0`Ele K BB C - CPl=GSC!aJ| `=QК97H N>7F0UP0pQ P rXa(Bf^֪ bŌ!2ZbE-$QTUVbO$VP%/Le촐zPɪ)PIhrF@S? F.$@éCU(G8TU_TِTbk.GIY.ӄՔ.F!1<0]7w bx9K5GfbrPvXYD=}j1z8YwKgjV0 $S]ACJ kup(cB3hh+zH /P#Uw20!$BneDhTA6hL" x+"f q{m $)r#EB<0@?S13D5`Tyas g1g--j!``Ҡ]:cP_?HIC?&B%֛}X"ZAÔ@Gt Dxi]1/p`1XIa@ E Hf=6@lB>qh`$0V|4HD:  (` 5A; ?!$PT y)[ (J6MP UHv5q`AhiPIހR ! + ieىQWe(P*ga\'&@d@MÜKCU-TՑX_=@?]V&0Ć `[Nď#" 5_XQD(5 (!A RuBsbXD"@ѣNj;4 RP]L)jZfX@@.[s^'_[`ar1kӶUj `#A !!$ $kGU*; XPaKAQ@Q E[Dfi_A 4Qy).3G`Z=E>刯 یTC5M G ZfMF:b 61bz~^jZMNUdTn KL\ LBзOF+w|?  %8 Hcw"8=a,DiABtl#p0?*I"H$EGD]^ I@Z11|b*e  tIQX aqf5B+xiLʨB$ae[P(!E;L<h J.P d(I*n$#!=Vf F:(k>F^Yk/2G0JQ;6 px(qu1WvېLg }CHEPa h ^"e1Uˡ `< V rhJapdu F 8uL HQ n|0† XhELY((@E#^,){YIdlf#6DJu%O!v'0us($qI7Z+(,)t.5`eQIDRg`-YjGN1)e $B @b-p{c~XZ>]5h:(4hŅ>mV {ya/(B%uU91EAL} 8#mPAy JߒJ6k*c i'NrqPd870NP @R 'z @Qj>b)%j UUCA)ЂP|_#P\̡a_,(HUxR  b7CC){h|,DݬL29{2'j٤GhVqϙ1X:$DǞO&χhO5r J[ֶJՁdWZC Ԡ(A_5`M5euI) Av_d)nuĀId]ӝ!J־X Q? j3M^ZXa(׎FB|K(jE Eo@B gI(m855^`IEz $hR D(V@kP S[Al-N!AKWఀֱP Z:U$kG1t0HH(-AHG w9="R0"$ i|%/b̐yeڒLOYP.t+"@JeuԪt a9Zk@B(^!TS>cg ֧xotՈ3 d` Ad,]! `,J>zv $Ah$XP] )EUƑ^qJ)H$ j RZ(, 8Neb(`UJAX 5iAU02\-AW&!LA ܫ*2=lf ,; \r0@A-pИr( / \$E@DD* Wd0@_rO/H{&?6{Z]Yb_D6i`uzWBFs8QAkg&c@uŰ:\k|pd.p@,s& %8Pk8P^qk ƻL"jOI)G+e'RDdd %pEw#`\K w WЊZwr+jQ*(-HU\QF9; @e 8@5A4P4Ca~аΩS/!>!qq02F'GN["26* URv?odp/n @H?S| N+}֐PS HPb?\Ő`(0?V|Ak˧O]zhHs r=  `"zT"**@`F "B@9PPRhR&H4q&+P ;!p8 OB3@ZX#E{uN :DB&R؟ٍKWסiE>IxZA음8 ;%+-Œ PcN50_cΗF $> 5J@R\H"$#Ae L7xC Jrd+DZwWц;n`Ù@1qSeIcIz)pfD Ї3i(ipR5^?%C)>5fȓY'q"k[zu% +5dVUBXu(U!qQ-P. };#w )D]f3h1צ $,Bi. jJ`)+ #<]ՠ,PIz(R DJVP"3@YY8)Ƽ),4@&sGY^9Ha #SwfuB+VqP#xB&Df0ʘA !t]O]>t.ϒ>}"*>]HK$l6uh4CjZ@B ac6Sh"""h==dBޠi_+HxDCED!PC¤,m@Q*dY ӧXSp)Iv?P e0)@ .0t`!(hU@ "π0 CopЂ a8)#ـ"Z@Hx?6l rR (X@XM|c>$@SP{BP^h-!D 1T4`S؄C˩=ѻ! H˄m;6  SCc !cj?Lz@ Z+ ʰ$_␼~/| R) *[6_f(?F47$@_GBh= 2Ct#GrAbl /pH xڋ1g?@{@h' 1A> =1-K3f̤= fGʨaN3bȤZ R1  ug2*8fi@"AUDP%(YuYeRiCY %b8Jj'3bV+Fi`hh1O&@xޓ``&U_d(cZ]2[lGh ,IBH*'?C%P[L_Cp~,­siD U)"-P-PE\Q4,D5~AtIq󡨄@QH(jRdEPXB> O␀I@h&y"D$ A$MDHk!1(Y];W ?gC" P]u]NeS@H 4@ 0@VA-bE)ARM"d 0XMt&*I eIlݓm MF?誂Yt>5nLR=;~ ?HC|hC@)eCCrzלPl)Aek2DZXT#CXM4Ҫ3:  sWPs[6@-䚇+D H(Q%$V RB>c R-GBDH[hd$Y,  Jʰ"=FŊR`F@sj0SAa1JVsVN~Rl"^CBT/&+jmx‹5Xd bYJgpzy6N`QeLrI#k`9J9ZG14"<5h fELb%we09S0 Kz=$;D~hϏ" RB|Z>?up/ H!=XF0Z#`|T +ZIXvhJ&gJV*%ҏBS|0vQSGs+95!9S5򺔝 ZD+ȇ+BBfs4QF *BBjD(@% %~`A(k'LHK!F4u_ )--)HaX:jRl-YcB*(ᒞZc5+ Aqazoढao,X8Eהc>Zpj5qS?]AEECLB>IKeg7N_ RXiV#) qx0B!yn5ct!1BVRu aT^ R?TMPi@1@D: ,];Ci٨'qIw+ Mُ&08y,܄ӅB(UJfDQ @P!ThQw&hrkn7?q@d0l 'c]PDx ʑ"Z+K" Q?@*D d^[ ],2$S"%|<=5,4<p.AbA3PJ'G ]ˆ]AQA@Ԍj?46uJ5Q͊RDbfT.@'iu7rzX;FJ=$ ;&Z}g5)KcE',D)g: ,FLpǍMV 9ݱ*u>I!QRa@ pǏe2Rh}.OȊ0`QF(8H8 :@D$HhY( ZRZRA`6I4 <"D5T.EJ 46hQ xbxl@ itx@UruJėI4Uy//렀Sl=,ƾjj xAZ!)h HiBAbGf!xH}A Ti$,.D6|lAra  "$ ! Q BE)@P) -%JoPcZȻNE;-r2u@G+5֪GOdcC;BD1`uB0%[R!1ILE1""0B[ uw]R8Ph7?XQ(@mr2rtVH XCsA :D^ @]zl ͇L46c$5D, &gypf@0z=F[ MEEg-EMtRܰI2FI6D<_  \xJW;²hBj3L5aaez+XPyԁH5V?o 7 4*?QbWm(TQ(XkwX8&ϠQ,ZIa(AQBĖ#A(D"*ډFȅєEIXor"a_<"XZLjLD=5ϥ$<`hP& Td@" ACj *Mh<̫8&3d)P)lDZ #H@!^R^704J)C( xzC`R# !CdFB>J8og!tS9,`P `/MXB@KA@ᓦ*H4?Z&sfmkGgH Vd\NuHd78c 3׌ Vprq0zT$CiPZ@ƚ%^kDXl.hFS09c&y ,$ h9= D8 yX7*$%sAAO{ ?7R0 7y%/ s2x,R2p pႊ,q*@Asbl/)Ļ*0ZA@ʊXg] AfX`"e"6-TqHnc6%1PV5aHѱ37Mȧ'ar9(pHD؍g`[Su \9~h*"-DHOX"7;^s]#*BcLut}$'Z糡UȰ]Pxq#!Z9H fSuVIӎ4*`~ P|< 1@3.(a$. !Q H\ؠB@#!;#8Ve RJ;'A@LW!i$.;`XFBkT́ A@P  h ݁THh`qPz Hh* J]_ i: Z%BJq X%L @PhFDH 25ˑ4 S)n|W}%#" 0DO F*BXgkc )eΞaYT~(4=C6Ҥ 6aa &ia @݅P@"ADS;3gq#lYY>9e"ClTY^T'~R`Sl+GqDԄ0#9Lu! }lwS:(UF-9SΑ"!JX ́NJ(0rd:Az|@vH)@=>DhTT jAZ $Ib4$R(ERP쁖!/ Џ] &A.pZ8@j\%h(QH B OKBJ]`rתsiȹnhbY+k#-T[Hn -oR sX%N0cps/pA[:.CΦ) 5A4By/tT#R"#H i [}UGFZ =HD d`L6Zx@uѱK{BB[b/" Hi?D6)GEDZu"-/d %73mXjs&' B2158ʺObi A0DAZ HM@3 MˆO& 'I-M|P]((. -QyP~ʐ{duo)W(]y-:\ S @{]:h8ŚaPo6X&^C DqJ @QK?0FE5÷Yda +[\B4/d_[C "^:(-lie,gB !^aJ^}SZ !K A! j{U0^2J<>6) HJ 5'T QE`*uaBCWQ/ُ^LjT F5!;E{թۦ8eZ-( Aa8- /I\֔$-IRBDc8Ԁ X D -F0(N-ߧ, H% q󐬵/C@GR螺[#&V<ȰN(iq)^$D~FZs7pm{֊iAPS_ϢJ=sv08lԩVW=;[@+j!҇5y-?"C6=pj)ȟ,A`'D^ (@d' > @4*Et:H G$ ) tX(Y@>PA 㭪#P+!c#!YlA; EQ" V9" S DiXV ]-9Y'v9Ҷy @.??y,giBN/a!v6ykv_Yt+J!AsX>緷D_KЙ= ;6((Js7QP8('h'*BT;@ >Oi/`d(A[H&@jT p8}Q"FV.ATphѸGȢA=Z(Q%%o`*BjU(hg=ri]jJE-鄿MCK6f :Җ"鯮L}'_$+KR"D3HkUE ))"0Ml!׃2%5h >ʝ @ R|˫]_RWк>'*C*"aі~ OdDd PX Ӳ0(p\ȁcS!TC$C >(l@٠_Qf|?PM/I:dS@l&X7<@1 *$DF Cy񃼐)H# SN0mg4B U a4ڵH !;Y!e ext9J+ a$ia@ SV:"Ҵq, ?,kCp w|*8|}AWHGaXB2P 0.8wd≮ Æd`7 "+0=@Wڼ*x t]O]>t\|.w "bKPA!#}0LxAV E. h{} &J*֯;$- *C -/Bi$-ԑG^C5 ]BHJh}yWW7g'  "!@_|"㲝<$Bc8`[Є @d$V(   x^~/?yp( >^`+O~$tz ԯuw$p^hd 5J5kCckM }c@n!`A(+2@q%8%,9*:r1  x85ƈj吃Ԍꈈ ʼ!@ :uPH8E(Ѡ#J hs$j J@U #I.!S,@U:E F(RُsBU J)A%jdV 0kDiAhpտAJ8tE y)(Xr6Bq o+I( 2T=R3\6eP~yqzFBҗ(a@VS[ e G yT*-,ʢq0Ck @xz(Ty=7Kq(żqrDNJ<8?,XT HNg,A_$%))x|;ɢUuņ/ ,~_Lqe9NJ/6`]]&a2uyw&SPVp:?:#Cx0)7kS&3%L;ȚJjVK %~ F%.(D3 D2MFX {뀑fM`BP@|xrkF!J\Aף DKaD " Pk+_)ZIkf=DHY((ҀgB}0Sx4"$[!Jd`͚XHɨ?RX1erL܆>[8O$s =%PuN;Z!|IW"JD Q & Ei#1ŨA}85ƽ2}OB 0[BQ55/6%*#+b?[oKNvܒe̘LXEDJJ9fV$iKPCPq^̸]F1Ԏ&H26bIc"&v?nh]< 3U"S !LKF`W 8 YE!v(3|=!nSWX:8QӘb=* \_-! K.$#򀑹i N/$ LUP^AG e*7uI\UH `d GY?nY6 _"O Sr7-4$8r@}7<++zOoq=RAJ)2qj0#Nh|%DOjkl_릔)D Nh mBg׸ on" +ڮ't5$rBU2a"% %D%M8BH.(B( c"΄iD1GX;V29 YǰK FS6l%(`Z*@R h$n dP(%AG}Z["΍++>1<ZS l2ȨXj5Be D"I2P*g`?ҦwԥyiK9F;hӵφdưʀ 151WQԹG XO(M!9s,6g-Ṁi#=u 8PZ=vw 4S+PZd ARp{bEb@yAO0 f- .Vk_;BP⩤L&%1Cb╥zA 'dr"dBD&5, dykQU4!XG跞%` )ڮ?${ʲ GDT5{Y]q4UIyBt?- 'Pei9ͤ=,0/!D =-SC@sLƧO8xE)5N gUeRvRJ&Y BkUvL%X6i2[*c@vœEhRD k2 JV( Y vXw7 rXkEνgw(Z@^-9NT`y$7%@ƽ징H:vGg6{x.b6А1E+'s݉ڴg3(HP2 }"F*O΃}-~'YMŤ@YI&捵/"7nMb{ojq*.ouO`H'm !kx^)u`b HDf>hȑ qjÎ`4i (z,^F QGp< 1(DaRs(B 1tRC(&i곔f<,R.Ҏ%(J2Q)8 тb@U@!DHt4\q]FVhӎ$aCF"3VWbR +-Pp+(d rbƙE`DJ.XhxX)|&(Cy#tCv VṐ WhB,b+bW^EԐyG#T# 9V>% ""7P B!H?_g7y֯m)ZZ\bToW?G>kRDt 9? `KxD!-Bsk;4c 8<2AFޅҡ+%Z\kE#G*́w4;$BuC1.v]iBX,$NJ) yesy\NRzQ3# F^_;=M!9ET7_{8B 5('-G?ٹXb`B\ HP@J008$@"D(FxAձ ()ёAM0$A3dVgX èbhM#U =.jO"d,:lCKuF3KGByLd@Ѽ;՚AhXc;LT\)JW z_ ! xBjDEdP`]l P"jsh,1)R3hr?/T&/)jΪïj'!#Y% RYNEE kLr)$(> LJ0i 0XC\Œc q:+IpAi԰.+"C r9 a -J)@:Ji+_Ԥ4. lb}T~n"+  U);lZʩCB# HD=%|yi5L[BnYw%>Ք+(;JuJǨ,STa)l3աt\^&|J9^/Z8uE,<ߘ9Qf`rk^8#&cG1cƤ`x`"a P-J%`,CRkY'l.cN5!#b$%XY%01 ?_ud-B@zd rCSA.zDOjQX[% =?ޟ9"Y`a_`YQ XLW_aGO@1J+!Mڦ@gC !/ cKSX1~lx 2^f<%7(|~#rXMI0$+bGĠ${C$H {M$: <-v Bp \RP-aNPeFyZ#T-29N(Dž'C((axtI@8C *eL8\_LG%͆ A4`M@$Ght e=4, PmTjP@,py( RcE2x,@t!X7 (JJRF%[t0A K~Ψ0onH}P$`)VF<(TYڇG Şrb?{ < ڥKQ##$`R'8M\jAfP jCF~9CD m)iR/C ?fSh0r^<8$q#Z-[F""&?H~cP: 9*C)܏ޅp:aXGV9MX19ҟ!;pOSeX 4D 1!RkS9*UDԇGOw-g(~4pΫ6YЄHB(b:%G40+fC R Bb,HH!I=??w AS|7++QQ\Sa&0/lf([jKpJ%A֋2]"8pKvCA4P JvЩP4q(c p R EH)((D&DX:KD`hR.]A@Mt=m!Vn4P D T"q*%S4 '$I1 X0+VfR40Ph(B32?/#Dgc G_兣#y"E`C5vjb< S)Tj$RM)+YG0B!huе|$jhB}.L"Z@*@AhWil $غ@-I >RX: ',| {ǔaĤ}cp?XD7[. |1`BDRoi@8+D9E) )UI3$02DcZitEFkAd% @$s$+av!ND&!@S F$(x;6 KPR)@hM,ku[_1߼@ƶ0 ?s K؂F>#HJ}#4 At <`F,`?`EÈ"( p04ЛQ*;L" vL,XƂfX<0A66! xT7Hb7~/_[,(20% HWȊ8/b"x"tUQT@a$tˡ⇩ *+ZGcL0GMQPcp&)32Bt xQ z- # //M}r"y<@B)D@F5$ZE@jMGV\VIΟ?ۆIEU,`$ X-4 hQAv@\Y  a(REWZk8c+g$s[γ]GkHt|_dY,KgM %H4 +%ԏ4 ŔUvsZfI!QeE9sآI@Eh)Vћ*$@B$HB @d0%E.@mEQdĶۼ$(q(EEoj @B+Fl' 6vC8kA֨*Pb -E( G ڽl k[ӧNR`/@Y*?#3@P 8B11H)<BXT%"bKk(?~qa@D@BSbMIXٖ-l0cXր:L~od& F= SJKQMo1X̠4 TCh 1G磩b JWB(6PqA5_Tr"IE%in_ky#Q EB? ;nD4+˸1RT;DRJU@{*1&=,D!Dyybŋ| }JS BQ;@ R F|xA @@dܷHeJ3ID&<VgQ"'Aoy\!lF!ʊ$b]Ӿ4hXF0k@UE)X dRs 8Q5$BQoCc(I:@g"$DӑArI$u@%(P"fXIHKU1v< ,aHiD3Xb (PB (PBH (]`U#:*(,k FRQDbX (/>!KRq:cN @CӒa O q ~6/z'%D"E2GA0LFdNǗвKyh 8in.QDD>Ѹp3fP$9X  rhEV؂ W0;1&VdJ50U~,X(@i^g43H=0NL2R 6xx=(CHam@/4=4M:݀9P) 0pK\|抚xM4.SXL"DCCIAhh,EG,jUBV-"aQhkQ8!PІQ~@Pݗ^t~@| '!&N Eg0PLO8Ǐ4Rԧ#4H4eK f`$0!9xkJ*-rb%bV UBQ[bx #-"T*!(If'`.;Ta^~QÆ.W$q0#1%/3@MO=JW2s=J^Re+)tT |'k`lD@fN`ِR96]B~$%+Io]UHOq^a*af7"ƌ.Ax#QxGۉPlH TBVd4amC-pٔ9$QS)LDTx4Bm*1F360")*S($AΤeLLnNyLhC+v/LπD$HN N"yReL`H$ dH8`j\pU3G%@1fHÚf(nhglQ1mE;ĿADX0hFP(*Li' yybCɈt2U,h $•](gZsj!WV$0yyb.B!bu !$9ӎO&*rg9 :4/,XC (U-IL]d)UG2LuZ 1\3 F 0^MA(dRF\C`JB*2~K.GƬd$MwJqǀ"D$h+KYHTL dND0 k"T!^BIZg9xT MSI$M5ؠ(RA)2\;4hG*\$yk5fK8Nt )DaF 5X+:@[oxZJJ$1)x("d;>K@>}}}Wi,KRj.}hPʴ?CA (ZT H `$R J!Eaak*<r-WKV W,`+T8.JG5]ZtR. +p iF(fzпJG{` ?pppE*& H7EӧS8.M$IxC"*"B (߈W,`Wźv#5▇BuJ# J5`%8l&f }ItD$B DBPl#eKAH,2a&* 2^-yxYn#UO2yЬD# HN/?0i4P +B"DM9_`iNV*u&Krr±¾4(@6R N UW@k~*FrBeѬWJ%Ē8- 2{H&IҌ'y!!+1P,?,D9āT)bB!@ $$b5f0#^z8#ɖ}  Ãh&!W"Y(P#Ϲ;7̟}IC'E SrA>($ qdJ*DTN ԓ&8A2(ωY \rsQoGqFV3A|NHCq % 5 I/,XC(Yr<R-h%A\k^RӕQ#g9f5T+j1"&|2bHyiq<^Xb1B BHq W@(- B!)Hו7!]U)IjE?  `t#N,ML%Bdhqi^ƞ40(%HR_T!ge7gbO{~Q ][ KkXGmY, XA&dl;d@0hWEdPAgb P:#>ÇT@HR0  ,PJH(z!TJrBe ҈fb vC1Y_XbUVIb1CT@!A(S3Z$E&O h@IJWM)&2gZ~&_EmCȭ> H z) 㦴-qO8P$V;9Ȝ f&t qFlֵۃLBCʤ3b؝HժiB1Lt)HqJA ]0fP)ֽ\KgM~6N)RE8tp8o Z|JT:Z!./iWߚ6Ԕ2(' NN@jRBl6ѓ L(H%$ WV$?'V^T ֙z)xTMy**txS!#dRp+(-2?|Ϲ>HG"1d&@)p SFZsUlVTi+߳Z |fFv+ԓyXO*ENJ9-D0lEHɴJ9ӬAX  ,@R@EAǔ_#K95Ǘ % MjcU8a:;@@9 p7 x~)Eށ  " !PU Z|$Rym!jIt@HJr-]zF@ *D C KOh%B%!]V0}$      y!y!8H (c!(6!QP@ !ffwʨ\ :Gc W,"Lq‡}͘@)rv@"#rBnX# һ=R 0#@GWČ|"Aflw݌](&ˌ,0< AH' }ضť-!I HRBd"@? x% J'Q-"RǤyN@X8"`6#ȌQ)gZnߨ 'շ`ހ<bHH)MlZbӖ(1A Pa/BL# BEACB *A9#+an)JqL_3`E8p u? ;RbSWb 1)9?ѯCs?9@ Vh4%+]c<7* @_~WԳÌʹSj 2)TR! /|#؁)ڭ Kӎ Nָܲ F0EM} %$q.B &{I%)Bkh&@l8q @([ b.~ -p3sAgh,õjɾ60:āw&4(Wd6  '`!ߥ ~RS2]_e lؙfqfAL5"d.0lP!;|`(4Av6d2}~i."I UL^(1&4~$PldqD$ ^Xb (PBPg %@ "z@!C=e/,. ( QUc00r|ہB9 } 4(@ BbĠ@0GHE.a0(HҀ`!_Nɀ?$r?ƸH$ FnP,& 8SXzPUE:S" @G6:y$b};\Od S$04 .DğLQxg](uҫ8M|Q| F| r9Ss GRه\ 9At16!-'N-ZuKBM%zb5=OenPJwdn@$, ##)6P1x``%= A6z>> 8]) d%ĈH O DDc1cŀ@/PS A C8%!bI9B-b+G~H<<b<*9dUHKx'0?HΟ< c0L@<{E:tӃN,Yaybҝ`;wN|%-C#VOZax= $744T l%ή 1OkC\R~t?VEB4$KV5Ba:<~(P+{MT_'I/ 5ƔǨl1y@q/| +`@-l7@`30f14)M HRB$(R'& $q#A 2%-^p(rHF F^d@CAD:Pq)q##?@ N? *T4hB)JU*JZ *B\+/P  0`K $@$HZ #(1$J@"@hF:8Ҭ,dɜ"G!> Ҍ&@r@=^:Og>Jg%Q@"pd'N 82pd  (^> >@BUY+ @^Xb (P(t Tu]u R:5#R8@ @^X|rH_aF`yyߍ5F6qD0e!m44Qs 0BÏpgh$Hq$< >DAlQ?el082E:P %@@@/ =HB#YB1cŀ:Jb_~s((QE*sXp (x!G3╬i]1 $0'$"Ea&pm1Ճ檼Ahc{ '|00@0"AE@>qk`)lZ`>Z(&"?@ ,KoPj}IEQ) S@̇6@L`Ro8P:0iJJҘęZh@@=`3 d~ |Ц4)!I HRB ,~$ G A"[NP BtJ d;ZB2(0 [а XH'؀9o6 )\_ $nnocc Pb(1A Pa DD$$J1.UB " -`$1@Af D0FtUE_\gt?Kflp JU[U2bC8x@ѕ쁀*ɛ+Lg՚#sqx@iʠ5Y?e@ CM@snJ/dW8rrrT4iP΂)JRJ- X1Z*mh$`i0*_307O w9ȌLh} ha c_dI&wpg/1{w(,dɜfaɃ0SCTp )XYU9@ "Y'Fhg+Wu3R K$oaHW2)-lV "fFR`: OPGN4ǦUlz)ߴC@3ޖz}@:ehJU1c1`vъBzjFrs h?@G 3<  u#)G ΛNSnucCUi:];̀ ` ( <qZR3 aOЦ$)!I HRBP'p'8NOc(1A Pb6l`++aXVW9BS)0) R)JRK@E0a !C|o2ɖLddtYg,L@B>7(l F;f~(PK`qZR3 aOЦ$)!I HRBP'p'8NOc(1A Pb6l`++aXVW9BS)0) R)JRK@E0a !C|o2ɖLddtYg,L@B>7(l F;f~(PK`qZR3 aOЦ$)!I HRBP'p'8NOc(1A Pb6l`++aXVW9BS)0) R)JRK@E0a !C|o2ɖLddtYg,L@B>7(l F;f~(PK`qZR3 aOЦ$)!I HRBP'p'8NOc(1A Pb6l`++aXVW9BS)0) R)JRK@E0a !C|o2ɖLddtYg,L@B>7(l F;f~(PK`qZR3 aOЦ$)!I HRBP'p'8NOc(1A Pb6l`++aXVW9BS)0) R)JRK@E0a !C|o2ɖLddtYg,L@B>7(l F;f~(PK`qZR3 aOЦ$)!I HRBP'p'8NOc(1A Pb6l`++aXVW9BS)0) R)JRK@E0a !C|o2ɖLddtYg,L@B>7(l F;f~(PK`q ZR3 aOЦ$)!I HRBP'p'8NOc(1A Pb6l`++aXVW9BS)0) R)JRK@E0a !C|o2ɖLddtYg,L@B>7(l F;f~(PK`q ZR3 aOЦ$)!I HRBP'p'8NOc(1A Pb6l`++aXVW9BS)0) R)JRK@E0a !C|o2ɖLddtYg,L@B>7(l F;f~(PK`ʬ `\3 aOЦ%)1iLZ `'p'8NOc(1A NbbC>'>^ 0s+ b·9ik0)S bOiiiDɝ)JRU*lB<ct@M>'2ɚLd` Űb8Q)$T8@q` L@B>7(l F;f~(PiC#\B?D of;M}>t@].A | '8RA0FB+FJg9r#Ȍg"1H07 `F#o"k`g)IK2TR42Y U@ ~b^r Ą  ; w20b@ x`\.> q\| ud=G=^a,((FL+:%:Dt(]agf(? D@-l$#H`p^/?y^~(  ut?G?_₅  tt 4 ttА8@zd@z@8Ȕ  6 6( 6(wQP@\ffw\_  ¯,G6΅7t2j % (hR')#/@t $`n\`lMć(&& EC!'`tCJ~I 56_2jK@zF$;Я$DC q) E"^"F5Q i90D =xC5((!`$kE Vf@u Q+LZw` < O@QS %pIQlYETH"PJWzt}y?>b?Xt$$=K"Y;D% 'F0ҀcCB !AC) "L H * _HIh}$I x ?@t5h6`>4LɎ7Ppuzsue)nM )'w$D( <1# ; h{'k w?2L$I%QXB ebGQUqF"Pffff<" pQ5ǀRbt<sXf'}`Iz'^|A%X+@BeTPrft;G7@k@1' 8ـ|IaCm*g(Dș5 L  b12)0p S¸ъJjS6[CS1}<@Zw(iXy}U ԍ+Lb 7 @\ ai (-$׀R7&o`Ҭ(<5Lwe)iB}0 "*S@h RJFҡāJ=CCA#GJGO'\GGG1`DiO€!D記,G,XB %g `3'A)lUE/uxHL>o0^0 /aȀ(P,BIB1b %s ߲`$į )Ȁ28X#Q鰉?$U T`1FUТj݂((PV}5.ob;WeArFB?+e@ DHd!`*+(#p_<\ @ ?$l%Z7Hȇ@\o EI>h{EAZ @!R,Y4)Mv@[!wD!)/BpjFDrԯ;.kƊV:EpJ Ozd8&-]H: lpn ( }2BTKi< ^+S^@ #8Ą P),Ę3 & k~B`I)1c 3Ɍf]."$GP*)+!Cpd 8[xACB:B_,AgU!p!!`(߯ՌC?㼁.@@BEHCS(n ) Vg& A^L-h. $ & Y߰Dg|+.Q}>U\H~!' Ȣ65HCD? :p:|YfAPY5| X4r~ב)Ǐ  MlPA@  09 09 y!y!8H (c!!(6!QP@ !ffwʨ\ :Gc W,"Lq‡}͘@)rv@"#rBnX# һ=R 0#@GWČ|"Aflw݌](&ˌ,0< AH' }ضť-!I HRBd"@? x% J'Q-"RǤyN@X8"`6#ȌQ)gZnߨ 'շ`ހ<bHH)MlZbӖ(1A Pa/BL# BEACB *A9#+an)JqL_3`E8p u? ;RbSWb 1)9?ѯCs?9@ Vh4%+]c<7* @_~WԳÌʹSj 2)TR! /|#؁)ڭ Kӎ Nָܲ F0EM} %$q.B &{I%)Bkh&@l8q @([ b.~ -p3sAgh,õjɾ60:āw&4(Wd6  '`!ߥ ~RS2]_e lؙfqfAL5"d.0lP!;|`(4Av6d2}~i."I UL^(1&4~$PldqD$ ^Xb (PBPg %@ "z@!C=e/,. ( QUc00r|ہB9 } 4(@ BbĠ@0GHE.a0(HҀ`!_Nɀ?$r?ƸH$ FnP,& 8SXzPUE:S" @G6:y$b};\Od S$04 .DğLQxg](uҫ8M|Q| F| r9Ss GRه\ 9At16!-'N-ZuKBM%zb5=OenPJwdn@$, ##)6P1x``%= A6z>> 8]) d%ĈH O DDc1cŀ@/PS A C8%!bI9B-b+G~H<<b<*9dUHKx'0?HΟ< c0L@<{E:tӃN,Yaybҝ`;wN|%-C#VOZax= $744T l%ή 1OkC\R~t?VEB4$KV5Ba:<~(P+{MT_'I/ 5ƔǨl1y@q/| +`@-l7@`30f14)M HRB$(R'& $q#A 2%-^p(rHF F^d@CAD:Pq)q##?@ N? *T4hB)JU*JZ *B\+/P  0`K $@$HZ #(1$J@"@hF:8Ҭ,dɜ"G!> Ҍ&@r@=^:Og>Jg%Q@"pd'N 82pd  (^> >@BUY+ @^Xb (P(t Tu]u R:5#R8@ @^X|rH_aF`yyߍ5F6qD0e!m44Qs 0BÏpgh$Hq$< >DAlQ?el082E:P %@@@/ =HB#YB1cŀ:Jb_~s((QE*sXp (x!G3╬i]1 $0'$"Ea&pm1Ճ檼Ahc{ '|00@0"AE@>qk`)lZ`>Z(&"?@ ,KoPj}IEQ) S@̇6@L`Ro8P:0iJJҘęZh@@=`3 d~ |Ц4)!I HRB ,~$ G A"[NP BtJ d;ZB2(0 [а XH'؀9o6 )\_ $nnocc Pb(1A Pa DD$$J1.UB " -`$1@Af D0FtUE_\gt?Kflp JU[U2bC8x@ѕ쁀*ɛ+Lg՚#sqx@iʠ5Y?e@ CM@snJ/dW8rrrT4iP΂)JRJ- X1Z*mh$`i0*_307O w9ȌLh} ha c_dI&wpg/1{w(,dɜfaɃ0SCTp )XYU9@ "Y'Fhg+Wu3R K$oaHW2)-lV "fFR`: OPGN4ǦUlz)ߴC@3ޖz}@:ehJU1c1`vъBzjFrs h?@G 3<  u#)G ΛNSnucCUi:];̀ ` ( <qZR3 aOЦ$)!I HRBP'p'8NOc(1A Pb6l`++aXVW9BS)0) R)JRK@E0a !C|o2ɖLddtYg,L@B>7(l F;f~(PK`qZR3 aOЦ$)!I HRBP'p'8NOc(1A Pb6l`++aXVW9BS)0) R)JRK@E0a !C|o2ɖLddtYg,L@B>7(l F;f~(PK`qZR3 aOЦ$)!I HRBP'p'8NOc(1A Pb6l`++aXVW9BS)0) R)JRK@E0a !C|o2ɖLddtYg,L@B>7(l F;f~(PK`qZR3 aOЦ$)!I HRBP'p'8NOc(1A Pb6l`++aXVW9BS)0) R)JRK@E0a !C|o2ɖLddtYg,L@B>7(l F;f~(PK`qZR3 aOЦ$)!I HRBP'p'8NOc(1A Pb6l`++aXVW9BS)0) R)JRK@E0a !C|o2ɖLddtYg,L@B>7(l F;f~(PK`qZR3 aOЦ$)!I HRBP'p'8NOc(1A Pb6l`++aXVW9BS)0) R)JRK@E0a !C|o2ɖLddtYg,L@B>7(l F;f~(PK`q ZR3 aOЦ$)!I HRBP'p'8NOc(1A Pb6l`++aXVW9BS)0) R)JRK@E0a !C|o2ɖLddtYg,L@B>7(l F;f~(PK`q ZR3 aOЦ$)!I HRBP'p'8NOc(1A Pb6l`++aXVW9BS)0) R)JRK@E0a !C|o2ɖLddtYg,L@B>7(l F;f~(PK`ʬ `\3 aOЦ%)1iLZ `'p'8NOc(1A NbbC>'>^ 0s+ b·9ik0)S bOiiiDɝ)JRU*lB<ct@M>'2ɚLd` Űb8Q)$T8@q` L@B>7(l F;f~(PiC#\B?D of;M}>t@].A | '8RA0FB+FJg9r#Ȍg"1H07 `F#o"k`g)IK2TR42Y U@ ~b^r Ą  ; w20b@ x`\.> q\| ud=G=^a,((FL+:%:Dt(]agf(? D@-l$#H`p^/?y^~(  ut?G?_₅  tt 4 ttА8@zd@z@8Ȕ09 6 6("6(wQP@\ffw\_  ¯,G6΅7t2j % (hR')#/@t $`n\`lMć(&& EC!'`tCJ~I 56_2jK@zF$;Я$DC q) E"^"F5Q i90D =xC5((!`$kE Vf@u Q+LZw` < O@QS %pIQlYETH"PJWzt}y?>b?Xt$$=K"Y;D% 'F0ҀcCB !AC) "L H * _HIh}$I x ?@t5h6`>4LɎ7Ppuzsue)nM )'w$D( <1# ; h{'k w?2L$I%QXB ebGQUqF"Pffff<" pQ5ǀRbt<sXf'}`Iz'^|A%X+@BeTPrft;G7@k@1' 8ـ|IaCm*g(Dș5 L  b12)0p S¸ъJjS6[CS1}<@Zw(iXy}U ԍ+Lb 7 @\ ai (-$׀R7&o`Ҭ(<5Lwe)iB}0 "*S@h RJFҡāJ=CCA#GJGO'\GGG1`DiO€!D記,G,XB %g `3'A)lUE/uxHL>o0^0 /aȀ(P,BIB1b %s ߲`$į )Ȁ28X#Q鰉?$U T`1FUТj݂((PV}5.ob;WeArFB?+e@ DHd!`*+(#p_<\ @ ?$l%Z7Hȇ@\o EI>h{EAZ @!R,Y4)Mv@[!wD!)/BpjFDrԯ;.kƊV:EpJ Ozd8&-]H: lpn ( }2BTKi< ^+S^@ #8Ą P),Ę3 & k~B`I)1c 3Ɍf]."$GP*)+!Cpd 8[xACB:B_,AgU!p!!`(߯ՌC?㼁.@@BEHCS(n ) Vg& A^L-h. $ & Y߰Dg|+.Q}>U\H~!' Ȣ65HCD? :p:|YfAPY5| X4r~ב)Ǐ  MlPA@09 @` @` 6 6(#6(wQP@\ffw\_  ¯,G6΅7t2j % (hR')#/@t $`n\`lMć(&& EC!'`tCJ~I 56_2jK@zF$;Я$DC q) E"^"F5Q i90D =xC5((!`$kE Vf@u Q+LZw` < O@QS %pIQlYETH"PJWzt}y?>b?Xt$$=K"Y;D% 'F0ҀcCB !AC) "L H * _HIh}$I x ?@t5h6`>4LɎ7Ppuzsue)nM )'w$D( <1# ; h{'k w?2L$I%QXB ebGQUqF"Pffff<" pQ5ǀRbt<sXf'}`Iz'^|A%X+@BeTPrft;G7@k@1' 8ـ|IaCm*g(Dș5 L  b12)0p S¸ъJjS6[CS1}<@Zw(iXy}U ԍ+Lb 7 @\ ai (-$׀R7&o`Ҭ(<5Lwe)iB}0 "*S@h RJFҡāJ=CCA#GJGO'\GGG1`DiO€!D記,G,XB %g `3'A)lUE/uxHL>o0^0 /aȀ(P,BIB1b %s ߲`$į )Ȁ28X#Q鰉?$U T`1FUТj݂((PV}5.ob;WeArFB?+e@ DHd!`*+(#p_<\ @ ?$l%Z7Hȇ@\o EI>h{EAZ @!R,Y4)Mv@[!wD!)/BpjFDrԯ;.kƊV:EpJ Ozd8&-]H: lpn ( }2BTKi< ^+S^@ #8Ą P),Ę3 & k~B`I)1c 3Ɍf]."$GP*)+!Cpd 8[xACB:B_,AgU!p!!`(߯ՌC?㼁.@@BEHCS(n ) Vg& A^L-h. $ & Y߰Dg|+.Q}>U\H~!' Ȣ65HCD? :p:|YfAPY5| X4r~ב)Ǐ  MlPA@P y!y!8H (c!$I(6!QP@ !ffwʨ\ :Gc W,"Lq‡}͘@)rv@"#rBnX# һ=R 0#@GWČ|"Aflw݌](&ˌ,0< AH' }ضť-!I HRBd"@? x% J'Q-"RǤyN@X8"`6#ȌQ)gZnߨ 'շ`ހ<bHH)MlZbӖ(1A Pa/BL# BEACB *A9#+an)JqL_3`E8p u? ;RbSWb 1)9?ѯCs?9@ Vh4%+]c<7* @_~WԳÌʹSj 2)TR! /|#؁)ڭ Kӎ Nָܲ F0EM} %$q.B &{I%)Bkh&@l8q @([ b.~ -p3sAgh,õjɾ60:āw&4(Wd6  '`!ߥ ~RS2]_e lؙfqfAL5"d.0lP!;|`(4Av6d2}~i."I UL^(1&4~$PldqD$ ^Xb (PBPg %@ "z@!C=e/,. ( QUc00r|ہB9 } 4(@ BbĠ@0GHE.a0(HҀ`!_Nɀ?$r?ƸH$ FnP,& 8SXzPUE:S" @G6:y$b};\Od S$04 .DğLQxg](uҫ8M|Q| F| r9Ss GRه\ 9At16!-'N-ZuKBM%zb5=OenPJwdn@$, ##)6P1x``%= A6z>> 8]) d%ĈH O DDc1cŀ@/PS A C8%!bI9B-b+G~H<<b<*9dUHKx'0?HΟ< c0L@<{E:tӃN,Yaybҝ`;wN|%-C#VOZax= $744T l%ή 1OkC\R~t?VEB4$KV5Ba:<~(P+{MT_'I/ 5ƔǨl1y@q/| +`@-l7@`30f14)M HRB$(R'& $q#A 2%-^p(rHF F^d@CAD:Pq)q##?@ N? *T4hB)JU*JZ *B\+/P  0`K $@$HZ #(1$J@"@hF:8Ҭ,dɜ"G!> Ҍ&@r@=^:Og>Jg%Q@"pd'N 82pd  (^> >@BUY+ @^Xb (P(t Tu]u R:5#R8@ @^X|rH_aF`yyߍ5F6qD0e!m44Qs 0BÏpgh$Hq$< >DAlQ?el082E:P %@@@/ =HB#YB1cŀ:Jb_~s((QE*sXp (x!G3╬i]1 $0'$"Ea&pm1Ճ檼Ahc{ '|00@0"AE@>qk`)lZ`>Z(&"?@ ,KoPj}IEQ) S@̇6@L`Ro8P:0iJJҘęZh@@=`3 d~ |Ц4)!I HRB ,~$ G A"[NP BtJ d;ZB2(0 [а XH'؀9o6 )\_ $nnocc Pb(1A Pa DD$$J1.UB " -`$1@Af D0FtUE_\gt?Kflp JU[U2bC8x@ѕ쁀*ɛ+Lg՚#sqx@iʠ5Y?e@ CM@snJ/dW8rrrT4iP΂)JRJ- X1Z*mh$`i0*_307O w9ȌLh} ha c_dI&wpg/1{w(,dɜfaɃ0SCTp )XYU9@ "Y'Fhg+Wu3R K$oaHW2)-lV "fFR`: OPGN4ǦUlz)ߴC@3ޖz}@:ehJU1c1`vъBzjFrs h?@G 3<  u#)G ΛNSnucCUi:];̀ ` ( <qZR3 aOЦ$)!I HRBP'p'8NOc(1A Pb6l`++aXVW9BS)0) R)JRK@E0a !C|o2ɖLddtYg,L@B>7(l F;f~(PK`qZR3 aOЦ$)!I HRBP'p'8NOc(1A Pb6l`++aXVW9BS)0) R)JRK@E0a !C|o2ɖLddtYg,L@B>7(l F;f~(PK`qZR3 aOЦ$)!I HRBP'p'8NOc(1A Pb6l`++aXVW9BS)0) R)JRK@E0a !C|o2ɖLddtYg,L@B>7(l F;f~(PK`qZR3 aOЦ$)!I HRBP'p'8NOc(1A Pb6l`++aXVW9BS)0) R)JRK@E0a !C|o2ɖLddtYg,L@B>7(l F;f~(PK`qZR3 aOЦ$)!I HRBP'p'8NOc(1A Pb6l`++aXVW9BS)0) R)JRK@E0a !C|o2ɖLddtYg,L@B>7(l F;f~(PK`qZR3 aOЦ$)!I HRBP'p'8NOc(1A Pb6l`++aXVW9BS)0) R)JRK@E0a !C|o2ɖLddtYg,L@B>7(l F;f~(PK`q ZR3 aOЦ$)!I HRBP'p'8NOc(1A Pb6l`++aXVW9BS)0) R)JRK@E0a !C|o2ɖLddtYg,L@B>7(l F;f~(PK`q ZR3 aOЦ$)!I HRBP'p'8NOc(1A Pb6l`++aXVW9BS)0) R)JRK@E0a !C|o2ɖLddtYg,L@B>7(l F;f~(PK`ʬ `\3 aOЦ%)1iLZ `'p'8NOc(1A NbbC>'>^ 0s+ b·9ik0)S bOiiiDɝ)JRU*lB<ct@M>'2ɚLd` Űb8Q)$T8@q` L@B>7(l F;f~(PiC#\B?D of;M}>t@].A | '8RA0FB+FJg9r#Ȍg"1H07 `F#o"k`g)IK2TR42Y U@ ~b^r Ą  ; w20b@ x`\.> q\| ud=G=^a,((FL+:%:Dt(]agf(? D@-l$#H`p^/?y^~(  ut?G?_₅  tt 4 ttА8@zd@z@8ȔP XU XU%XUQP@ffw: өl}yc|g < 0(!_dWg Xl=XmS#Za0F!bzCܴ:"VR _#Rn ݤ fRBk$(Q B ?Hf@CE6Kf i8~AB( = LJ8%U;8hTPAlFcȀr]YBDT ,,#Pl+ tޑ&Y&,0IH !~c*& P Z_ "8 N ED{ PPB1$w-/vrC0P11N"(\؅)T jxIa$YP6y"1  k~ ðߡ_JmyNz7)-24G$(MȵCUAG~PH5@Fe0 a ڈf fH(KxƢhW@s6Qa?魹+λZ~aKrƋPE%bOiB2ʅLPԼFvJ>#]o*bEТKW%]:(QhAxPj$RP2 R+E)z,FX # ߎ~%@ X `'1k/  E78u(l`acJBj9!p`96H2+F|3DAB_zL?zvX[pya 8@Mu@)h^,;b8a@qa@t!€wct~X+^נ hc^i(:d#&Z C0z@P,|=U,9I 4#@J`cl@GF( J$<#O-LΒBʄd".NJd@sy0s'|"!/ev]131`L bo fhŤ@i%CR &: @Dt z 4|z,-BZ(?# nQFh4:Hh~`6}Y~_$jl/T!D\@Z(QMfQEyLL%F'?BBJh^ PTzxLj|.tpTSFVD D Ỵ0YWa3zP f&6hjj̠ ZP@ 8h\%"|L @BTI=T3RO.w !!B`OߴwN #șR L"0&J̈́WIR`pGk/?(}XXk L[=\TE\,!aq`IG b`}.vhO]'.IE}">tHO]'.IErJ(H!!$C$C$CH8H8H( p"@Y &n,f6gְšſ4t36`:`I ͨ\"f,FC3h#`xd R]]BGк>.t} ]BGк>.[Hs`$s`K )6Acd6Acd6@D^dgTa\Ԧj5P#A*gBXm|K c,я *Y?5*gjT@/_?|/_??@@{ rg rg r 7s }1} pt -=r]=rD=rD2f͛%5)39<;C9vR>;8p wd. <A PTĥ?%%1м `HddZ`c.(P>b9F3asZ=P2V_%~JWRe+)YJVR`@B"DL[(.a~cN.YoXa =`APXf:?+^ACf$YC& Cȑ/c0fJƎ#v(,"I5F1LxLxLh1cD `0 E# STdEeȇ@@=a pcŃ 0c NI A]h``_0!AO.kkQϗ`7cG2apӜWF8F@0QљNZh ,oHPh(t)0l@@ __ǹ*V/X PT222eKdY,K%6%<J!ӭXP( @h$}?+٤+ a)*  `J'X,_K^{.e̹e" `C+@2`!OV|G᜝8"E1*20D":#IJ3Z # 3+|4hC_ u8PitXDVD`"-44U7_jXj~rdsY c a0H$ A  B @!&e8B%A`!1F ]A$ C"LUX=WD)T \U136f̑R*Ea!<ˉ+W4$h/_ *8kK{.I$Ȇh.tHbw}T6vE}">t_X ?Pe e2*0m$@1~ %9+!%"E8G2 ~( _SSm)-$0P@W~(dNa4EA*©eB?9 2LC<BLAm t} ]B ddd>.FH6͈Sd9O33@o/U" PTܢ@u92ZBW 80  L+ _u( AB';@{ il3WX@UpyWP݀Wgf,_Ъ%*HpH@P P P XU XU&XUQP@ffw: өl}yc|g < 0(!_dWg Xl=XmS#Za0F!bzCܴ:"VR _#Rn ݤ fRBk$(Q B ?Hf@CE6Kf i8~AB( = LJ8%U;8hTPAlFcȀr]YBDT ,,#Pl+ tޑ&Y&,0IH !~c*& P Z_ "8 N ED{ PPB1$w-/vrC0P11N"(\؅)T jxIa$YP6y"1  k~ ðߡ_JmyNz7)-24G$(MȵCUAG~PH5@Fe0 a ڈf fH(KxƢhW@s6Qa?魹+λZ~aKrƋPE%bOiB2ʅLPԼFvJ>#]o*bEТKW%]:(QhAxPj$RP2 R+E)z,FX # ߎ~%@ X `'1k/  E78u(l`acJBj9!p`96H2+F|3DAB_zL?zvX[pya 8@Mu@)h^,;b8a@qa@t!€wct~X+^נ hc^i(:d#&Z C0z@P,|=U,9I 4#@J`cl@GF( J$<#O-LΒBʄd".NJd@sy0s'|"!/ev]131`L bo fhŤ@i%CR &: @Dt z 4|z,-BZ(?# nQFh4:Hh~`6}Y~_$jl/T!D\@Z(QMfQEyLL%F'?BBJh^ PTzxLj|.tpTSFVD D Ỵ0YWa3zP f&6hjj̠ ZP@ 8h\%"|L @BTI=T3RO.w !!B`OߴwN #șR L"0&J̈́WIR`pGk/?(}XXk L[=\TE\,!aq`IG b`}.vhO]'.IE}">tHO]'.IErJ(H!!$C$C$CH8H8H( p"@Y &n,f6gְšſ4t36`:`I ͨ\"f,FC3h#`xd R]]BGк>.t} ]BGк>.[Hs`$s`K )6Acd6Acd6@D^dgTa\Ԧj5P#A*gBXm|K c,я *Y?5*gjT@/_?|/_??@@{ rg rg r 7s }1} pt -=r]=rD=rD2f͛%5)39<;C9vR>;8p wd. <A PTĥ?%%1м `HddZ`c.(P>b9F3asZ=P2V_%~JWRe+)YJVR`@B"DL[(.a~cN.YoXa =`APXf:?+^ACf$YC& Cȑ/c0fJƎ#v(,"I5F1LxLxLh1cD `0 E# STdEeȇ@@=a pcŃ 0c NI A]h``_0!AO.kkQϗ`7cG2apӜWF8F@0QљNZh ,oHPh(t)0l@@ __ǹ*V/X PT222eKdY,K%6%<J!ӭXP( @h$}?+٤+ a)*  `J'X,_K^{.e̹e" `C+@2`!OV|G᜝8"E1*20D":#IJ3Z # 3+|4hC_ u8PitXDVD`"-44U7_jXj~rdsY c a0H$ A  B @!&e8B%A`!1F ]A$ C"LUX=WD)T \U136f̑R*Ea!<ˉ+W4$h/_ *8kK{.I$Ȇh.tHbw}T6vE}">t_X ?Pe e2*0m$@1~ %9+!%"E8G2 ~( _SSm)-$0P@W~(dNa4EA*©eB?9 2LC<BLAm t} ]B ddd>.FH6͈Sd9O33@o/U" PTܢ@u92ZBW 80  L+ _u( AB';@{ il3WX@UpyWP݀Wgf,_Ъ%*HpH@P P ` y!y!8H (c!'(6!QP@ !ffwʨ\ :Gc W,"Lq‡}͘@)rv@"#rBnX# һ=R 0#@GWČ|"Aflw݌](&ˌ,0< AH' }ضť-!I HRBd"@? x% J'Q-"RǤyN@X8"`6#ȌQ)gZnߨ 'շ`ހ<bHH)MlZbӖ(1A Pa/BL# BEACB *A9#+an)JqL_3`E8p u? ;RbSWb 1)9?ѯCs?9@ Vh4%+]c<7* @_~WԳÌʹSj 2)TR! /|#؁)ڭ Kӎ Nָܲ F0EM} %$q.B &{I%)Bkh&@l8q @([ b.~ -p3sAgh,õjɾ60:āw&4(Wd6  '`!ߥ ~RS2]_e lؙfqfAL5"d.0lP!;|`(4Av6d2}~i."I UL^(1&4~$PldqD$ ^Xb (PBPg %@ "z@!C=e/,. ( QUc00r|ہB9 } 4(@ BbĠ@0GHE.a0(HҀ`!_Nɀ?$r?ƸH$ FnP,& 8SXzPUE:S" @G6:y$b};\Od S$04 .DğLQxg](uҫ8M|Q| F| r9Ss GRه\ 9At16!-'N-ZuKBM%zb5=OenPJwdn@$, ##)6P1x``%= A6z>> 8]) d%ĈH O DDc1cŀ@/PS A C8%!bI9B-b+G~H<<b<*9dUHKx'0?HΟ< c0L@<{E:tӃN,Yaybҝ`;wN|%-C#VOZax= $744T l%ή 1OkC\R~t?VEB4$KV5Ba:<~(P+{MT_'I/ 5ƔǨl1y@q/| +`@-l7@`30f14)M HRB$(R'& $q#A 2%-^p(rHF F^d@CAD:Pq)q##?@ N? *T4hB)JU*JZ *B\+/P  0`K $@$HZ #(1$J@"@hF:8Ҭ,dɜ"G!> Ҍ&@r@=^:Og>Jg%Q@"pd'N 82pd  (^> >@BUY+ @^Xb (P(t Tu]u R:5#R8@ @^X|rH_aF`yyߍ5F6qD0e!m44Qs 0BÏpgh$Hq$< >DAlQ?el082E:P %@@@/ =HB#YB1cŀ:Jb_~s((QE*sXp (x!G3╬i]1 $0'$"Ea&pm1Ճ檼Ahc{ '|00@0"AE@>qk`)lZ`>Z(&"?@ ,KoPj}IEQ) S@̇6@L`Ro8P:0iJJҘęZh@@=`3 d~ |Ц4)!I HRB ,~$ G A"[NP BtJ d;ZB2(0 [а XH'؀9o6 )\_ $nnocc Pb(1A Pa DD$$J1.UB " -`$1@Af D0FtUE_\gt?Kflp JU[U2bC8x@ѕ쁀*ɛ+Lg՚#sqx@iʠ5Y?e@ CM@snJ/dW8rrrT4iP΂)JRJ- X1Z*mh$`i0*_307O w9ȌLh} ha c_dI&wpg/1{w(,dɜfaɃ0SCTp )XYU9@ "Y'Fhg+Wu3R K$oaHW2)-lV "fFR`: OPGN4ǦUlz)ߴC@3ޖz}@:ehJU1c1`vъBzjFrs h?@G 3<  u#)G ΛNSnucCUi:];̀ ` ( <qZR3 aOЦ$)!I HRBP'p'8NOc(1A Pb6l`++aXVW9BS)0) R)JRK@E0a !C|o2ɖLddtYg,L@B>7(l F;f~(PK`qZR3 aOЦ$)!I HRBP'p'8NOc(1A Pb6l`++aXVW9BS)0) R)JRK@E0a !C|o2ɖLddtYg,L@B>7(l F;f~(PK`qZR3 aOЦ$)!I HRBP'p'8NOc(1A Pb6l`++aXVW9BS)0) R)JRK@E0a !C|o2ɖLddtYg,L@B>7(l F;f~(PK`qZR3 aOЦ$)!I HRBP'p'8NOc(1A Pb6l`++aXVW9BS)0) R)JRK@E0a !C|o2ɖLddtYg,L@B>7(l F;f~(PK`qZR3 aOЦ$)!I HRBP'p'8NOc(1A Pb6l`++aXVW9BS)0) R)JRK@E0a !C|o2ɖLddtYg,L@B>7(l F;f~(PK`qZR3 aOЦ$)!I HRBP'p'8NOc(1A Pb6l`++aXVW9BS)0) R)JRK@E0a !C|o2ɖLddtYg,L@B>7(l F;f~(PK`q ZR3 aOЦ$)!I HRBP'p'8NOc(1A Pb6l`++aXVW9BS)0) R)JRK@E0a !C|o2ɖLddtYg,L@B>7(l F;f~(PK`q ZR3 aOЦ$)!I HRBP'p'8NOc(1A Pb6l`++aXVW9BS)0) R)JRK@E0a !C|o2ɖLddtYg,L@B>7(l F;f~(PK`ʬ `\3 aOЦ%)1iLZ `'p'8NOc(1A NbbC>'>^ 0s+ b·9ik0)S bOiiiDɝ)JRU*lB<ct@M>'2ɚLd` Űb8Q)$T8@q` L@B>7(l F;f~(PiC#\B?D of;M}>t@].A | '8RA0FB+FJg9r#Ȍg"1H07 `F#o"k`g)IK2TR42Y U@ ~b^r Ą  ; w20b@ x`\.> q\| ud=G=^a,((FL+:%:Dt(]agf(? D@-l$#H`p^/?y^~(  ut?G?_₅  tt 4 ttА8@zd@z@8Ȕ` 6 6((6(wQP@\ffw\_  ¯,G6΅7t2j % (hR')#/@t $`n\`lMć(&& EC!'`tCJ~I 56_2jK@zF$;Я$DC q) E"^"F5Q i90D =xC5((!`$kE Vf@u Q+LZw` < O@QS %pIQlYETH"PJWzt}y?>b?Xt$$=K"Y;D% 'F0ҀcCB !AC) "L H * _HIh}$I x ?@t5h6`>4LɎ7Ppuzsue)nM )'w$D( <1# ; h{'k w?2L$I%QXB ebGQUqF"Pffff<" pQ5ǀRbt<sXf'}`Iz'^|A%X+@BeTPrft;G7@k@1' 8ـ|IaCm*g(Dș5 L  b12)0p S¸ъJjS6[CS1}<@Zw(iXy}U ԍ+Lb 7 @\ ai (-$׀R7&o`Ҭ(<5Lwe)iB}0 "*S@h RJFҡāJ=CCA#GJGO'\GGG1`DiO€!D記,G,XB %g `3'A)lUE/uxHL>o0^0 /aȀ(P,BIB1b %s ߲`$į )Ȁ28X#Q鰉?$U T`1FUТj݂((PV}5.ob;WeArFB?+e@ DHd!`*+(#p_<\ @ ?$l%Z7Hȇ@\o EI>h{EAZ @!R,Y4)Mv@[!wD!)/BpjFDrԯ;.kƊV:EpJ Ozd8&-]H: lpn ( }2BTKi< ^+S^@ #8Ą P),Ę3 & k~B`I)1c 3Ɍf]."$GP*)+!Cpd 8[xACB:B_,AgU!p!!`(߯ՌC?㼁.@@BEHCS(n ) Vg& A^L-h. $ & Y߰Dg|+.Q}>U\H~!' Ȣ65HCD? :p:|YfAPY5| X4r~ב)Ǐ  MlPA@J :: $)QP@`ffwc(Q@!@) 6X C!Ă"PB`V@0Hf*8N`' ,D4d4ēADK"brR BA`K`!8 !P )CUHQ  PL\d, @DE% k "  PaB(*1J𜾖Jo "`N h  @(@bB&Pq*W   @$  #?g%`!,D+$&P@Q_0P" d hz $#P(F",1IUO a@hJ$A0(RBcd@! <0b!JZ aP"H)(ZRQ@,@, J( a "`@{&" S@A@P%Ce^G*,Wp PA @@$W `T",o%@PDJJIE~ͦ@H  % PDpP1(F*"0Hq`m #H/ #\QA$:@ F""WA @$  <0XY @А E b"P)! @( NV`0 O @ʍ 1(!L@ -F/℉Gi hPZT?UizJhVH y38%b AGH&9@Ijd?kOPA,/|e"lXkLA H\âK.A(,RDr4h dQ4OCn_h>!e/'mdEf5Lн ?!1r iL1&@+E8H`mk!EyV|`EAd3Ea@HA.pCIVê >P]ԃLb8@tAdH%H$J %1ꮸG Ss D~" W5d H$WM"WQbԜXAGyX. VP(@bd  `zGzqi8@j@Ȃ %LF1\((ں-l\td @Psc 9LK >\w@hBmkx@d4DC! F,ᑨ@uGq"HŜ.I9'9Vs)X)KV{ YԬB-VJR^Z)b$`ykF#Qs'f*8iTQY+31/@ B$ (t-2,&r)T=~d s(B5u "XF@@ &,h-9n ;N/FC0! n|I6Pmb X~䓻׬<06,P]Z4yFĖQ>/1z&(?7qkj!A\! u>,x} ]?@ p怠>B#8g?Nn;5PF*j24 E!F  S砒(dI-HpZf Oˑ@R %"I|@Wzvv'aYEA%9)Cj@u:[@Pό%^ rcXLHWa"DJ# s 1 # Za0\2yGмLҤa(94$_~D!`@AA1 (ml0NG.V"r 9|@    J٠8E w`sir%(bO  h-t!@PТPAIB_D^~9{5&H_), l(P(@EJ_(x^?@)ЀL/" S:Ӻ ЙVz?P <<@|^B.B">DB _">D9P9@F2w)E`<S,:xLSry  RDD61Ο/dd| p'P(Q He*TWy?lL  `@fAHPpa@JA$ @M#@r&#H 8 a \0pP!EP~XMP  R   DP)(&P6j  0%94RNWU8P< # ł"$,S? P & t#" @b A$)YW;M$H @$0A` H@B $Bee "HA 0p㘂W섀AhB`xYAa`@@K ? ~ ZlC@dKNSLIA #{Vkr#<$ E DRR &HSHGJ .CT @C5+&g@ dNt7>Dax`(Z#X0K rr9=jCpEj)qw6`hAAY~ ,~>?%#&F Ye_B0"ojok5܅XJ,.KGG k@XtUqUh"uu6e t}[Ox N!h3? *~kAv  0 7#AbLdj Z.P F*P$N,"IY*rU&||\`GQh$ [?E+cJޗZ` AHDbBKbu"l 2 !r D(? "p@AC+}DⰈ:?5 7Q.% 7@y. -22P`.t"L1_egFP9䮁,hȢc0O:5%GhX QΦҠ9OĐ[tysDl";,{נEp($P *" bIAQ>ԅ0K$0ʲ'pP*&UU[T}ꭁKxkY)/K V@0 COW_,d@P,Z=p%BA.n7i0aM6&R߰ e H D] 2)`r"QԆAUЄƂEhf+2XmFJ qG" ڗB'# ¿`(ϊhAG9!fZSOlT`x 1x7/A(l}>Sj<"J(u4yrjhw 8 0@4Ax&TM(1bD$PI?*(Y0@? 2;I{C!_ H~5 p KC 2lĿ;FO\!*pۼ!a!a@ +tfG0XҸQ b `(|piQ\$reA}LO7A yiz+}GxV.Dv!N> TY||"U Rm *3D%BF>%|7 Cjt4SX !]`&B[(mƠJ 4QK*0X&9k@8K`A T!ջ/ GU!.,T}oM j@FM&C-{BYH)4-'Ł"4R2jARCል$*E4@Go@"mD#?& kaڂq 34Hˬ1!ZWP_@u0HEG^~/? >\ܿ@  'ET!@})( .@ktEO /U\B]-[_q.w@,*(ȆBBD ,BPƄ@;J" (rj%8z)ZHzDEH$Da!*,Xb P'P 6L>D8*5 EIA =&";8ݒQ=ܴ yy F8$)@(*&jVr_U8L#-xTZAJ5b( 5BۄDڎ\rrWVi2)z0m9 J·"`}/+8[rF|v2E|yr#@) [ Qk} { ARwfAS䚇1@lo0I.Q4#0~k@{ 'Hx{C8G'"?@O )%4l \] j1ÜFU+dIycq7 4F<ypiӀ K6{}lIw@rހjo@6q_?@>|^zjjF`!M }R1$\Y膱Q'@ AYi0CnAȲ?pM,_!%'L(/48esIQPe0.[ 8dCdCqun.D^G^>Q""""^4:@sX-3Ӥ0\GHj@AkNO(LB|/ QY -!DMqKB^i%`0XGi{(ɂq*@ C%D (4"0F)QHDL%8JA1(NE( `4{'"@$@" pT IVE D@ `ʂ 8=JWI0Ծ_IAvkyDVtp9,*QANR6ck?*]k BU5/ J (@1u7"Se1(2 ?T4T %IEqa5B5@WI`hBpziU>N((Zmi ($h<>4&$@M Eq䋔@n% @wxdrAnw"L}C[.?T@d?;y&J "{Glɍ1 tqU&h  AzBlI`҈C-%Hj`0L(D8L.""L0DHwHbK )UL!HRJA0~<@bW3 CV$QibTd r] 3HtK5 Fm=?r׵" A}k?}AP1$@PF@ .N?< ȿ =2Na7x5%8 d%`m՗-!p=H @ ^+u6WMWQBt|"tT@w 5'yep0p i>4PÙ% h&%A@DthA,A`2 b. BAJ*ʆP!@aR=% B4jjC @9+a XEa?`UѭM/ۀI:M`\6SW4MUҡj} ȽXw-@l X@bHۣLF`D!#4NViOF_*= 6`y 崑ğ(vB@(4aEკƸC 4=|x}o06bbE|G@ONa\ bTw09TGC&r5y!?W)G1~yx8A tÿ_!# ݺ #'HEgukwӊ%21ːte;_~!jA <8<`$@TT*i(Ѧ$*98SE+<}z Jj2t U">|XrC:1C.!1O( \ A* 1Oy2Qa@~li/ XTr9ZKb,/^ )kK#AZ;H)/F?,_ᄏ& kbDN‰ * 4  pG5TYpX:A8B9C(08lGh(tPiQGXU%3CiLjz|TI4`R9 xNh%v' A%n''mNM""K͢FŘTNTp_̶3#@fzHT "(mfL-9[*@EnS J79I'gyA8q $=JG`5 Py W^]C0""6lo1 <ޟ)!T!S|?[[?!YW)2V4#2fj`y!W( ^y7XƟ҄\Bsz<4$\hhBiF(?~,aٌk7a2$NnnV/*n{. קn(1ӏN h;UҤ7>a/]P" t 9 *Puʯb4"~DBG+@r頊J(X0ȸAZԤ * d@GK8f9!2iC J=J,.ѠP ps?PX( Ě-Jvm J _iQF&Tk UB8A55a)FkB [BXB!WPⲁF5_i_KU@)V/t T@tR`}X \ iA"{8G_V*Ydup:$F8T~NH e2t9N%@XCk ?Pu/3 PQH@G(bHTTt&!M@km^?^Z! N2@#NPG՚ٞ<' C CƄkhr? ds*QA1ńxk+9 $^ Pb @ER =2BU(%B?U  f@'0P0-k/ #n>!!J S< 7=(_a׀EY dbtrFZV*tPf ; *rRJ zaԪ`[8<\'@!&QG}@*u"AR_/ф+>Ki>0*M2 ?`A*PhG1A >a@(w_,#B?p?:-*!4?BU'` p  np@10㳊# +#3(B!:I? - gn0]AL5q%.LA?t, G1h+s:+`,3IjnZT T8ŕj}2)yA,%p nt c8(D3>RPDR+Ȁ!wm:oB?JTBxU$ -U H('HX/06F(@lwJ/SMP;F4%W!+_"K5HB|n0Bd4@-%ŝ@V/#C 3|.1NjY O?/Pſ1@Bda8 ( a캃eJZ #,dj0!gB9@Jb,7 @|0@44Q@0:@:&*1D 0Ui@!AkQ Ah6HGҪ׀ף69ePO0O!!-,WHՙ %)@FҋOWl|C!@,u4qC @#=R+T2/ d hψDY52Y(n "b@(0Dxz 7SE`B@}D/Hh `r*V Wؿh AZJh@+T2&h8NY F?ɴ) ]* { |?@}M=  #7gfbF^W`O*Ur1xZ o(_ʔxٛD0(N?xn@dxJA(G N~( 2PtrJiJw+8C;M5/ ^\D Zhy6*z#E R+R8>/TF`!u>I٨ @R- iShz 'LG $0!=5HY P]UE G=QL4*|Q}?&P$7@ d+6vh~ ҡV\X%hRGz|gaRGf #Pax5P->S^~ ,%,I00"'B,M%AoRR L#2C%JP:Av(` vB ꥽[,},$K$0 P$I I# @db#@@0`@8yFʅ*#%@ 0!p PPh PZ,(CL)0BU*(!a T.wvQPPЊ)G-Y ^s|tF5,ҵ"h"D *F-&Ǟ074iMH]FQ,+kKɆUAu ԼV/Ӹr < r c=TK b|_!ZČ[WXXDAg / $d:"v ;x,$Rtc HYNJ{59Ab`@g?0&Eu +=Vq؈&`aB0y-lEiDj5*XHdcm@%Lb"  h ua%P$ "!@P4:D+]Z{6VhAΉD=\bM KLʑS XBxͅ6!2ڄVbۮp,[v,OGVA=$A|Mv!$3԰% ~\ªLLA"ixM|¹wػ)ۺS..h|W0k6Y1ioD} 5?_V$w167K,ՂRQ?sOM F ,60I!.R.aԬf'2xXDJBv"YdV^7񒋿w1ů63*uI$M2oyJS: lVh(0 `9L1P %LEqXH*PDP>t,L0FXI*$ IFXX6ր*J}%4I J)BR4)*P!It$"X&X%Eٗ4@PQJzQ#3H{DV:Az 60KDT2)XGZ9Z<3c)h/mRT-]N+䫉y%Shkؓ$bv J9%XݼD!"jqcGh0`uA  $6qJYQZB5zx\0C(BJVI(Xpr &V&r3C02ܛ2'KGm=h|=C2 t3U>0 +ą$!Wz6? [ '%!܌c7_UZJ@p)h<_q@ HA(BTAJ`P ."q" @P(R41SXSBE!h $&B Q -5N :X1":1QMs0 5(i9rY+Lֽ5'uCJ˿ 5YJ%,.5tMWl0\2rVRҸq:`"@C&)-OA`HQVD\T4=m¨WՙuI 3\ʰ_,(PF‡ŗ*`hsD+]V"),4aEKFZBNPf1ÍK 92) AX@6 (" KǹBB(r|T C@,0RYgV; 9"1:3ƌU*2k3U=.[UNk H넬ⅡRErEt}*r`ٽIA`Ltry8Ckʆ/yV>bmg)Py` $Ht&!E@؂f攣V{cu4^rY8g3d:jzD!Rk@Y7"H5BI*P&Lģ@/;,E-52ME0$8$0t˖4Sʀ12IPIڹOYlHY01*]gP! Teoǣ@Ffp9$a1k/SB9)6/%A.B\|p2)RQBPz)]b-wHJ]> snI!2?5P0ትhGtV\TZ1ʔBG] qسCI!a# A(sQlrTQ N ⌭pRt Q|=g#QP1z L ԯ (Ag(BA$ECQFXHԁf QuZOViVN$XFhе$TJyC($h d)J Q(` Iya y|*'Q@$Hՠb2NO"G+ǦD$8D(|A 2}Bgr@HpPR%g0 *.*K8 VC΢'IL-B ?)JC_T$G`,EusވRArb+Abٜ#@ґ !1о:j*E,qA8@Q+"iO;ÈS (ϘqO)ka_C]QvME8Dij4WWԇ,&,)^85#*Q. 14?HE1H,DxD$"p pT( . P$u8z?ʬt Y+0-GW##(گ##4"$@R+Jj@/_h,ʿSZm#q!KE$k]KL%JaNފHF׾B#j'cH*K<" )Cg ~H& Ps ,">CLm!"I м\Eix @p`0-(/AyA QEC rÃK``a(@ `'TtG*%B|t63C! 8$,Šϥ΁&C9?Qy.=.3y (|z/Gp}@-E`BQv]QDZXI:'֑~/ʑye'Oుazō]EBON a)<\!@$X. \/?!#x^,B AiXx|d~P?(7c(\|zPoFy@  #@T8/5#"4P"(@(@! D!B F !@8n^@,J:C3ׇDQC*hS? @M(Pz!Z(O^@Y4 ^,)Ԍ^\@vF7 =L@/6dQ?gB"\A  "-PJ0GԎÇ`CA/ zi 'VP5(r,@(L XdsQ@c3`wDY aA~+p@@#E` @ "5I@*QB sFV@ Hvl N,晬F-W # 4 ddd1#Nj-&`5G'M!i*  %4'PB#)D!_爇& @ ah _0p?4 A0aK'!((AoHs搘Q%w6 K#L?\a=N94uJ@ )3APLU|$ .6(?ade 2* Fbt8@<@P5B(\U/3(})?ojTt=׌I]E\\DSA{,D[(B@T!Kf0&1?s vN jH"'etÓQxVиG@BYg53 9 Y#& 14UZ< ՠ@ hI - IB> ]y,L~0T:6m CJ0$xJ]@Xպ+g`a<n*IYBH (qܑA0 q/z5+Ɣve2`ʗ`gEA9EZҋ$5CN-@ BV4 M7(%_QE W$ P=  @2?aHgL@# "L~G(W4HNə~*#$+<V?M@@`4\B-,d/(i$iZ X@Bt``  $ D^I@< RN $tx`%@ Ҁ4n5@/VQHY]@| Ӂ*0NH DEFȀ }!b(iÕTf/hd Ac(-I`x!I Qn>!!D0D8 H¤/ ,xMP$.-X-(RtE@RdK1 :a&!* %,gDuN~r 9UɕծE_ܧ`AJʑH\9W~`W_W(]`Q^潏 |1g>Ph>" *,(Ddɓ&ij t/$DCxΎ{tl{8@\B8R>oeriD:F`<"LͰqQ-qH?i, 3a؆cEH !H)ȴ(H (Hadc8d T"1貊 T"1X1踆*Q #@"Dddd0 %!!""Ai^t@?\.(?HhDP5:1޽(u$R`Ϭ'DJ)}a,$zr:if&*+0B1tkeXB#?F@(FTJ)@EAja'#GYL?!UT6= 4<d@Dbwa s&?@?5|P`D`" Rw$r ! Zn!h h^$t%B] A^ KC"A[J3:٠Ba{ `S%h1Ά{E9Р#: gBиЩAjt  8>hh$Xdx!Zh|<<]>.JiC`LDM^&^)oen uj| oX~N( !&184b,;W#=0c{8^M )f0^ bq&~(m"Ɉirb+ 12QJTBPA* B QRHm 0%(i)쀇ݏUGڱGfsS>P[/W+W-#ZCA:9@fBET>HQ# '2mpPJ")i@7!aCGo󞧳@т]i d\V@ R]0; Zh8&H$80Z ' Q6hUYДf2" ̐P,+@`B0d"Hi UJT @Pd Ex:GyA,`K ^sii-]Sba wu'!Px82'! p,GBwIJ)Q [ɑ@P4ӆD DqwpӢvSEw{Ԍ>"y!-79u9prr" ', =@+䣳$A"ʢ 8s \bƏb`q&N3ɈxAP @b!\3J Ck@P) Q/XU`R_46EVf 2F0D8yp @&B2PtP)ChI9$BVTF34px4@T"y!jppQ  `1$kh5 dj(ŀ/TQ sH@BÜ&hs 5 sh<S44S8f(U3h>ī~2r ZPA!H 0)@ZHyV `B$NB"jR#v (!0@h(D? APP '9Hx!xEV,5F0.!@F8!Pp*` [nCD$ ()ӯ"D Wc-*(b FBA'ZYiSpATpt JD(*!PqB$z.DOD{"dmE&#N]?\)2@Ր|(ϒ'(b(,CQgL_2?HD ʠ8&\C 4jf $AĜހj>%J@6s* z92 $= X)K0XF G% qB%W))פ!(qHVJBY4)sd@E@$6)k@kiD|`7FHH t4AZzGH8@h%A  ] 2.0P!fBH)aBPY <4hk)O}XP8ro` A/QEb$GJΔ$K(HpIEt17EI($`؁ɓ/亊K`@(_h>~.J8%0LңBEwaSWB H_<'E{#,pTˈ@KUHi@vS*wfۊ#;` ^耢V)"p4b҃ˁUUY !ƀ @@Ph(&q=" l!Dq)&׿hno((! V$m ``hh&aNo)(gK̄K`(88)A:?JߣgKmW8e7LttŔ]PNeVkGq40 Bϖ&%bz^Y`U1'AE $\ko:(ք MI B{aDk++-TEe1=A 1 $賈i0*!\$`@D@K~Y"!c#PJ*u&w)B:wa(<ĺ(("[ᒐ_Ĕ)" 0-A EDPX*.#ʠ수`4(>5@Y#D⇞8etyHPp$a&R@<)_hZ H ;C xwHeH>h+: :\\ bЂ5NÆ-#/ ]d)jBlI|aGЂ>DT@,ϐT[?ang{b#ةA+ ? MED%NO`RM_,Ru30+wbCqL>+"tK74HU* D`FRPz#"yn3_q)U zJr`/0_J`+3X$?T &" Q:3/d@խ  `$@slGT BR$$ pjF (Zo$hzՠ_q Z " UGj4w$3|ܸU~=MSUtlXY Rlh'ȕ9Tv5gs%owNdbKh /*8=$OPGH0o`?|NRn~e* +k ]9fu%ҪYsH kNS'[1^s+Ve0UG X@0(:zDN@`<j5B. q~9Y: Pr@ќb ? nF91 M~""M@1 y,!APF/5 j}>}J# @-EcCڐ3t5{9p`PHh3@@p@$|vF|P x!L q $ kB$PA 4n _>C]A 6GZ%^AXaad 8hy*V( PM&J? .(=A@! o\=րS`{!urgpP+PIhPӅR-786$d? m`#&J g%ʕ\%|hAt x/ɐ_ $@$ p2ʁ  0B^>}` @DO x,4A/EЀ 08!-18hhC((!K  x`x ʧ83)@ @~H4h Ѐ  Ph(V`@4((@D"rR~}@@T )R`@$    @@ p pkA8WBb#  x(;Q"qIΚZA-)]' @DX"IlVtAUE0HTL P PhÜ@ \AКrEl^g YKu\PH#AT)Ȑy4REMC0̂wח}aSRf* *yu¬I,NkkP-# C09µq!unE2;dΆU1Ѕ0}&>l?A1^0 !P ^.9Y+0A/yI2h`cI*b9t Qg=Tpy)z>=ðp S`u$A2ttm%`,h% Uj#B4P P T@R=1D:+ZkȘOnL=}|r]Sb>R ZrULvJ#H-`VֹBӗBX"lS noǨ-S&nG;+ WnM Nf34<$IYi4J '7%S#JĻ(c(Y =bI*J %#Q!()J!̐cR^50)~RW<@*2㾱0Dk9~Ң̟x4O {ax.(0SXQJRI7^†s ]Znѝ6D`%zpgC zP*\yș` ]* R?İ0С$kD]; cX~gUuhH60V8"(F/LV Q-_zy &-N*@& ( TC*+ FVk5H8%B٥46aaRzVz'(fFJ˭Xb: -]iK) fҬ @ӂiuJ(t2P&_DRp|an(2AHF -JP`2xFh-آ)CB,y. BoȮ64R89S"I +1BPuSO L XAC 2K-)uw %/9Lf|̺jAIdTAu1 x`2`J  hc+(wLy8,bcJ-& \9*ܠS @ KIPG Aʬ`iDW"TaP h1h,Ql8zAYT5OQ {C:-R-GK4" i5JԬfGp %BB0 $z"ބt8 /qIKHh &$A%(hJ4@zND}VL4X 4k@xJɎ@I*5A:@b &P`yl)8q\L !:Plr_V!G~A[UbRH@cLR( (A  BrQ(BX$BHzic }Mq@9v~Qr!W)s<)@}I)u A #C?pF46{"*N0`s`Y9"Z sFt*LP1QS?xfℨ鑁iJ]QJS!Cy_ hʒ6xΚِVN](*ր+,nfT25 N̕*mc ݒ .@a1 i'^ %!B)X,.=0'x&68 }55oDJ2\ SU SZ !`yZMo$KQ|(刁kpdHP= QFź[R#I1(3>YU.E(ԦX!'\JP )GfBővqGQx&l)PQ4ڔufG>z9}tUi"epa5o!^8J/Zl3EEIȵzE |D9&B.`]hw@~$>,Zk^KP!FX9ʀՎDQn}$l *+KV46@5H7@4E4@/@R z]h -hOx  EU ,I X+HQт>Bp)#Hr-=0!g&# y]xb$ W$ #"tB(%ԪJ: WEPUH*J-QKJBHH)D5Dq2*&P@`?:E? fX$@ ̍ P\*hĉ .zC!`U*/T!J@?P]O+Ny2i' ?-$#O+I la@AH9@J 3rzF(P9d=Β 0*5=":]!u #>l/ wbTzH@XQa N"TLI@3D0RXbuo(U!`l*^"@` Y|Wh[XW{ ,p`p<?t01O!Zp0t%AÃM (d0ʆb(ب1G0GQV$pD$< H Az!HA=H@m@DkњЀA:!M*&*&<4b %Hi!0()OEAޅt)-P$,?]V9@ ɬ"%Y+1`TYA jVc ý ~ Q WD!H݊0JX)F G_ZF\ l ?,h0<"e]EF,l$xc< &e0pGWz89 393JOl t r w!rgK&{OW@?@?A=ByrLXNš ؀@A jUG<0e .r ((0/y?ǒ4dA ($(@"8OA@rx7Ar t$耦)v( CxMF O) 4[0@"!T,0:@GH i$%p   TfgbYo4t#q,@[3 h0(W((p @60p$琹qs !4_@0.#P) jKB aAe=$P0,ŵ"D0Ʌ(0M) Z :ȡ`,Ga醡! p$6krD@]. a?#C4$F ]e0"t`,_?8ħNN"  Q,M@_qzG-)ąT2O#%X!ن(\ey87 ^PJWM1ඎ$ t %T QT%@Р6 (  .m+HT:? &:+?W?1( 'Mp;\Zaw =nQGQͳZd(XAr0>meOpA;U8~k  )BrxGK6~lxHJ(E11@tEDIpZ9T!%I_!%P ȘQڣԡ 2 #5Wf1eD xS0`@6w_`ҕ@xV(^mHH0EM-ApuX=#SLX~сZ( /6TĴ^/u H$ Et'-,K0Mf(L%Yƕp6@8Adx/DP ڐ\B#M`sp ,_tBIm BӨmodpoQYaQ/&hJx4 2LWlHa;7(2NiAxB0 1hxABPbѵxꌥ+@fUG 8pZ 1 I`0!! AU 4N.L瀔w^V[t@Y z$ dBMBEԲsw;'}{XrnmGEahG r} !" uQEǴ-&n4O*_b-UcH(דGsBS4f0#R,ՌIʈO)EZ=X2 HAH "A :Ta\zMP GEB;@h 4iWpeoz Q5tpBȏ ĄRд%Ҡ-kF%7`xJ (c UhEHD;s`S:̅2"ؼMGs<0( %ɿZfm5(H0NU[ p6qMꀹX=##dz* ` #1D!@3F@P'Ad^~/B  K ZQBEP A@Дz_d"9t1htBN(@@ۃ PUhrR/E -5ߨ R>A(H7lBW6H߁-C< O~2> JCW0x8ܵ^zC.s3XAfh0 ?I@F)`v(ZLS>@ "\_TO& ?xI*|*_* wdXE^f˱`MT}@D5bToCAК2V"Ǵ*JI@6=p BJ&0\"ha DD Ea:Xy@.\b4P hCtx`#xFb(S pSl $cPQ1XqDRo 'sJ` y<|`,X<')e"oGJ9Ƈ P>FM (@( g@PPr-G.W]@z EQ@&U+@m db!-4"+o#DI8 %ePf_!Bl0 QO?Z? :!r9gArdO@PHP H.+% )$"" LpNp&E!@b@ b(yoBO\Ipb5!A(!k!eT4N (m aj" tpΙچ4 7@(; !T >#C%G"p0+p݊jpb"Ms"T%J cW:8YDŔO V%`H $ **a&S]BYOy+OP[OG`*> A1OSjHX O 1'7BcbM!~t1PdT ` D+d!TB$6<#}lr^Db/`eJGBp7RzP%/ 4`0Fh"8?44y$ xa`>2Wr';~V W!\r +.5vJ$,Ǘ͘8U!p!еpѡܡH-V,1k %@/,  (4EbN`PxS'W+H$LFwmhB^D?H#0ra"9l["Q]6}NmEW FD!,9do!$h&CBX ~(<J8lQDŽ$xi ?@2GhGڡrBB^(0`݀K@%#Q*?>PP0>#H _ BPB?'JP?=A[e@@Ɍ1]jA]آ%XIÉ $1__ J 4{Çaa@F@rsYz/"𨭃͡j3S A[a7'&Q0K?(G˗/XL":KЈntGj'dF9JI<W:^tOR(@Y5ha GhC^h- @¢,6 Y  ХAhg8D1{VS_L`RIIC4&P&ȠQrP@Vo}Hbt1+!,g 4j#QYd1} p,; _`7РʇD (ԟH@P_K #)%! kzif~[ACQFX)QF+A4*]}Dvq Hq$Hao@`8Y5h >oFhu$0X=$UCR! tpUQ{(Py8@\ U?}i  ԛt(b1#/ ϪtȠ=Rj(v`@2 Y` uX@N<@2E14@x:2^ZЍ V#E+F" zqq% CF.F.&*gD0]bX?( (IL ,$a1Z8"чP1"ZAQ,ߔHao Y]#ʜ(, O%AzCtڅ Kȓpr"Qq8e B4(Z1hj%F`%i(Kk3Q?Վ! xDʝca(x)%uBe A੹l%9QD o!ܸ |b 2\|l7 @ A UH!JRa ȆɆ1!n4SnʐJAEZh?0ae 4w0 ',>fZ#-Q@  @io@!yu3E)_Gӱ@pʎgd?Cg o!۲ab!O䁀DB   Pa1P! dh/A 0<tBROH+GY(PU5@GF^nnn_B\ J8Q]Rb+#q BdQпN??@OM #!~Hdn /DtE  Aky X.JLR hPH2 8pTP$BCah.P裃1ZaG-I@kO{ f)@G0@%5|HJ@Y."#H0q(brȍ !! Ѩ$"Qac$i*!@3u$POףeRBTGk:=lc\!dAʗj5w@ b4D:)U 6*ҟJke,H^A Q*qԏkMdBfuaJ42\s>A~5&/˖'1zR %HhD~6x),=c!=-߷$i}Wr >BJdcQ@Dk"n!!}iBW@M E22)JP`eL@訡)5!_pݏA,]9%Dε9gX1&ʘ:fRB;,)  !R!I@PQTV  tVy1W u$myxm$4础Ej(S@F,j\Yh +C!XNȮVr%kN? o8:B2bﮥKMdJ1F+Rtus"0@@AEj PbBF*J#Ɖ/NZ~|9w( "%BPG (ZƀE. dRpA^@ y4P^R%<)JP`l&} $(+:A o$"հAH,q/0FTP< u4b e)(s5ĸGƙ#HNͧ<1{'̩zpoEWa P+ .',wV`Asi5P&d"\J˼|eE£&s?!&XcP3` ݩ)!'H!(j4V |lG) ;ĖJF/(M=[)F GLTb}icEcC0 "K RbP>V4yDN0SWFK%b1i0p9tv AB9@*Q?(U8r!x"F@AHݒ &XON4ij4@gF"(Vanj)0̸c@aJ+ ec  AN(3/2)`Uˮ_i,'ȭ*遛0\)`1Yr;)4z};C )!$!S]\s}) w}@H|sْ8YXB!_XCOv t0B4HЪv  `&>xw! |hfp\4bH$"R,++ŶxO^x[ɨ\hj~Pa†Q?#.C\-#?4Hb )?lם8I{aToHFNrZ >8jk r4}:~ue=&>dcfJ{@Jg1-@]M@Mjh .4)@M X5ZіR.B L.&!@Le9 E}/CpCcHAE OiqBQ2y*?HI8*%1,$H  JQZK1͏g X3Fl<\sF E BUN;FGX "@00i"60q(^,>H6ؓXЌWL:[3נT 0i!dI $4CI%RbBD4>yU:L $  @d٘ P` ʲ H-*BAHtIIREP @@ @C3R Aq@%TȀBl@#$ThQ0U(!` ~8 8hnAh4Ka@!soN $ʻL0,nD$hbRD8nK` Ɵ T„ r p8ZQyٙPn@$!KQQ΄P 3Ğ@UTcz"A4HjȲkx @UPˈMwJam.PvW99@d(%{+P@9 r'$(Ġ#DR)81 u) BTHPk&[3j@L mEQI*F0 _0DR*&i'@3g1p QTCD@nAT2&4ZB(B Ɇ@ȳMX"2 ) ,cb{sIVI Ae>|X T!tO@l$`ť PhT H`|/FȣNFOóvv;;;;;;;;;;vvS:uO ~=@A A PH" Wy"@$I0x#(%(}P0V ht['zwl(4@NECJ8w"f~4b(0 /?}f~C@tANY Pj0!@t&ܠ ?]=PPQ@$5:@%BUYs1( EPw]@ꀈ<P.I*T) Td(BN tδfħ'S"(q!d@0~@<!@0E ' )K'a0H$L ؀ '!b} >`x0Q1+Z?|+2MHJ wZT 5@u $G - h! e&%Eh8QJ8Xi AW^a.YCZ:-%R Jx9w!WTА0FU, jb3!@,?ؚülM:Fg)0A:_FPS oHR1Ixu|*HC$K#`%S S ‚0kӱ#LQB'NA,`bUq>Zu䀞#)!X4Aж(=J h (hw~%DJV0|$^}  @="0CH b % D3E Ғ3X9 ?.WBXO[JYb!_zu Yqr@A|Fa_TRBWW'nC60mQ>U\C>1G7hiTk+ "Z)ptS 08b paq zĮ橘Љ~@cgs':'e콗2\q&$k$ ""iNJdswM E}4GJH"V%מEF-YںFF Qs5K15 ,UXPdti f>o2He68Y.5Т f8&*ۍ@h44Qoj5FQ̀?@HX" 8-l$k&IN]$EE^\X8BW!EOGͯ Xc&0{П.IJFDZhl D6#Kgu*pg"hNmEum#@0$r WzUf렆VG` =@$٦tUU- AwCuJ(Hi!S- (Z*h)Q j RVI|4(%Jo2SNt%U@ (.]D`UO'E䜓bLI1%ϒbLILc Q|20`1:%!dQՉ1R%?n1+x<.IQ w:LƔUx׉E|)Jro, BJR,`!Al@Pp[ dbA iV(Ђs(BD'm' &Ij3`C@P !Be]?)Cŋ R @E&C Q LЖ^! `2 |jdjM&81ɀu#TWP P@$acjzɋU ,Dɍb@B1e:FTyť* i @D/I`Ig^VJ!H 7G  `ԅi ~:#Hĵ (& ?>JhC?-,^G?Ner?DDHOһEfVm[p9c@(PI#PBFG̒VE"|\xL -A-̀?mخͧo?yCy @bbG!)Ԁp.Ftֹ#?( d|+_dv.m2$)^ M )w+ s?ZSHANhih=]PG&E!74s/1"A<@M / LUP?Ŝo(Di^IN j2nlPFL4`EBAV*1PQ)Z.i$di .sD?.z@YV P FԕKbgiw :`TҖULΆA=\ F0 $!V$[?WW2;1ii">fX\!"'Jp;X2 b*20("%'͒ ]AP( J$h%v.-(@4@`T) !0@RAiQIE1ꠢU}8䘓"f\˙s.D̹"ǀpA!B J j$Nv(b PW!R*Paj(%5Aί/p8>+O@^` ĭO, ~BO!GzX< dXh^ b! `U͋99`~i!܆O3dZ2#̞ Qɂ!I chGBUv]dF1EQ:p9Nt& nZPKB\iB:P$(EtPfABdRipj5Qj4 |@DH(6Eİ$a֠/@Q-RĠ$ɈKR@xR !$cR1KMv (LgL) C;=3 up9P=P9f24T P< P Fn`PF(A~^7 P ijkCDQ:`G%1"[oۧOn=ZyV0P `!@B#Q)$T_Pq~7oRx@SwU-7i=b`~8 xINpH(}Z@_BX ea!Z‡5ea)ap4EpP P-ZOhK??$H+)PC YQhQC07NNGASp,\ $2Pd 288`0<&'c?` 0$7TL@Zv$ʢ364bX Dh~S,ިQA:Cj9K%(Iv ]> C - A'􁢭CZ G a 3P_{:׀{-7GSaC(ĖdqSnꇒQ >: Rf6 zp@8,t;=|>ᲃ&C H\S`a Ŋ@A4nZOl°&ɻz<2$V)C'ʏ@>.X9#0%"GK>֡7Q_Q[PDLBCEQT~MO" Q$ [" tA\,n2ZoY`C( PLQD P|*e0dFAq10`IB ZW1@N@TëG q<~ ;Ljp*OD  Dz$#aɹIPn4qJÒ6lF1DJ $<@!$W(CtQӦ}N;YNvv݇m;q / (~!L e!@Dٖ>RDO`1B0FI $IM}TS%&"uȇ o)_4Y Qh j?K"H*=9&0B0D2Mk^Y M>`App0B D Jip XATuF8)&u+;,VBbT*A /ɧ'u=#ǜD OڨQDŽ""|ET?'W |P($,WT41}9Gc6}'t^I9&$ė= PEs' J4AE EXdZpP-]5+A‚"zS_~tU_P_yWGf8[$?ېFNUVpؒ)'ψ@ G!PB*M= Xt"̨FIB"I/O/r: ,<#0F"@@HDKHpTXA!qu@a0 Cp= xL$@ 1x`} LϤ$+eZ:0̠V((cRR_xP)Ad e?D@2 F7&F"R H+T6)RT_l0[PNh . h!l RhKD>=;H6 4H @(MRk@5@5R!x^_YnSۧOn={t 3'8E`a$m;" x^N'" "Ax|fYl'Gwާz@@v,B1 ?y@j aA .8a(С3HaAEOj|pƦ/lbUzC#,6nJ h!&] k`&Q < I}d"͸J(A@ Vj p r!\%Ϡ U1c@LP#1M B@ F(sųZD91Hc6 "cQ *}A]`Gr.y<WԆu)邟G|!Hz"nlF7(@d/62b1pQAm@-PE+yK:`B_0L$ A@$ 0 TЦ qUUx44 yyb ~adByy0 `b\-=Z_0@ arQ?XJ7= pbp>dFhdJ@-{_D?4 1,hH/@`FA~4ѿ ͌Yl`Ў 0 (XGl4h}c`/y~B|.B/!`rC\m{=g ACRDG(Q]N p$(E'^=eΖ>XLC (d TA 1EPPJ  ,i9N@J5D[e bZdIUą - $jW@@ CHXգB4ϨlS\LpçOA4#jR',q +QwXLG^F 8GbJxa*Ta,C$CXAb!(ȎgȆ>]&0ġF(J4yh2q@@ A Q< 2h:A4_?\|HG7oT;x =tD AP#Bx#,*1?>D$\@?(Eʡjq~ii ;R5[E%ɓ^ht9p%v9j 0&$")l CM^K<ւf(K a#}`Q KG# &q?q MRU@)}feFU<㙃z=/N@H&2CXB LZn}0+d Nе-X`y'kn`i iNmو˘d5<(0X 0BnqPDMm<Ԁ:ҙwg-eA'h|53zY GYOf Z[h‰$D"/GP Ӂݭ%u×ŋ8 T_ΒE yv\} (A@൤7Q_&%aCD&,* ϔ{G / ق:It{ <1Ų?003U;䐏WȀ/1(ruT,0,HE@EBIDЪ!e;;F|ȥx-5$C}EābU@M`S/fAǩУ4PdR ٫*rd1R\xlaGU 7`2 * n9\ҽh('vC]8 C4|<(=5,,!я8ۃǫO:ҧ&:|nNdVUկuץD&ߋxCʕ hA4t0.ҫZ&3Z(dHVhvI J9 @0jPJZ0Pq. QAWG-ZPWֹ X C(GSJj,R":BqBjG(<:dT %%u#)CteKA]V-@MCw9($6h"(AVX>jҙ!/׻mg4`gJYa}kNgz^Dy8Vh K؄9y_kol$p_?q 2G$` @8F!'Np2<` S| _YZ, ONFt@I^m>@yKr5N!ˤHAtĜesI1X[~c \8C{H@JrfB%*Wo"is&@P i ]j EZR&vOCa)Ĭ^Q[J$+! BcJA T_l43O>8\\f/A%8 @>BrvxP q[0>b&P}?9,/]PLFs@[c֫F?|,a#m12q*H5 @@@gN:`>CO t0΀ v/7@] OZ +T0*VR?KL[ T> CXӘ/pz4q$4F$ Q_";H= [y$̎[}xͧ N=`3h ,x N W38ʜ d `D(H~ Ӱ ߰8Ѡ,5iYYL@R#ZEj@ ͭ0>B@zdS Q(? !*{ +\J@8g<$U*JjН 4 bCT @:l *0.5kG I)K IڔM|"|[fWZij]dd rk/` a(wb S( $__ v3 #;wlݳ}zxZtXh F5L%?'&ߏbf 1+ 4|$`Qq>Kʽ`@Dyw<@9TPVܶ@v@u DS[P  b0 4B%9 d }[[_0 8 <jAGAHև`3_`^]Ÿ0` A0)@(c33 +d!gqZ ު`˟/`~haG EG3#oݑ-Gp©FX*Q>:Nc` 7_ !E/@%)^9J,h~&Z9}T1ÑqTPȪl>"Ap`Th D%E)vV@7dH #DCpHz! C$Q@ QBB(Hj.wf>IMRYڨ@B A/EB"FF ABɈSVw/@@ LW|zm m6Ͷw;wlݳG`΀At.iwNr`"+JB7E 9$HS@_`9»cCp0|@(  )J1cAB)P]]*R-@?_WTAGQ"I䕝 (@=\| @P((8.tiIDyA09/zDt,BfATX. 2`T!K6cl6;;wd9eq% $8 Y@a ‰H Q#%Ʊ )#% &JN:tNmBk ^` FT/!Q"B/7@ RDRC(( 0  ̆DkJ~p܌@~G$ PPE*9\X(N;08N K ۂw B Rώ 19lZ2TAR K4pJ?ILZeH1|'(P )0EizX vV%PhM,d yydH6`bn\@\L@  Tg(Nƈ  Y*1YXQP@`=ffw@lY`cL !($v ѯ>ˀ,Wf Hx-PfIc`aɍ.*@ So+-Z@>QA B 0@SWhJ9hn]c0@:1re`Q%tyu-g r w*0,Ei4#I#3 +1%ϫۡ2m |q׈窸1]y\x>3@24`&dJ00AĒ*4m d '<X+ǔHr򢯎~麀sc o;*~rc,JOV@1%(zZd #9rFv}jmMlZb"Ûbl2ts `T _@B?7;, @[((%z;:>?)&^ٱ[HrݦޫsBw?cAsVl@ЉKqN~AP&H- K,Cy BD[*OP 4gӴMKjSaUV4XSd7 OA;38ydi Axڅ.4t 6\>hΧc#,s0٤fMg4JJ-@BIr`["N是|@ъ3cH'@4M%J@T+ME(Bh$UÀX= TA F5h:@(JCh 29C(-QB9 T3 +,bsE5"@Ev&J@u}+ZZ;j9VM8QA@`C8< ']Mw䓣g. `I4"Šӱ~A"tV#\#g:ޭoUHKkr@S3QD Zdba)_A"թ+_(l|>"R4<(+j@ |"L ̀5gx3SlF )$DHsX Ύ%b@ jF )dPzEBԤyL Qި@, <"@uŹ5 R'%L$(Aq(y&(Í JjOE 7$؛g`pƣ#S%KU,tkB)Bj R_,|TT;h23dLnnd$=\E g$Z RTHxODRRQ#F @Q- !5bBCni9"4B[SqaB(>YANЇ-jrG , R_DT%T_|;ڇa}mh0XdAl^D'V.*jm]k톘%"\ $Dj}mu4(s-W(!NI(@_ausF.D+4@"Pi A$Q!`R,8YhKzvRh|+iG:b1ZVIL 7- S!ŴtiI\N}$j)Q4 @P!!AH$SX@!UR:|HVbꤊJ`@C8}SOu]dxpsci* I0ʢ apHex JUSb> R4Vh"#@% PGhij6EI 6*d3D H09gձs 5G(bQӪm񣅑J(wʐa#* $:nx^n m @lH̞R1آMʻ9JʩNZ/p Ⱥ$F Z RaZG,!9U(Bp UH2U6b!E+2.wVHHK!Խ "`cOx #f@!I("\$\A ҴP>=P -P#|$C?"ڿr %CS:5{)"jaE'gA(JHTh=Ia \VN"SZ[/!P@(@ Ddn,7I$Y.i- +rdBe@O"R)ƾXǍhuS5əPt7y :3 vڗyCؐ|C]n"ʠ)(=@I(q ')`$J‹+$5 ' t`4 (Qԉ]'ħ]4V`9R"#*ZE2o |Al *y? yvF@(OC $ # ްy΀H 4Ėt=>$ýBlP44A=B A?,zm% 1!K~^?,۴Ʈ<g !Ä!K̅C+`J?@TPf8}i7OPS?(!8 )}# @ /\f ǺD$jw &m =0 d2 (z⅔ @"3F y:!2%)@(Q( " 0I  *\>L B-$)@":}GF t ";4P'#b@gqL,=kjy!6XAIcf8.0Bpf}n ` C퀈ǺAv4)g}j2[ѳ) 9K?V`s9aH8؞ ]gŚtWG CAHl,0(1薒(FR7M/+Z/=&%5lFZ5+$\vL@˭µXi_?#UAd@xxM?(Ap>`5@fr{SÂ˞$^Dp zxR||䌋OZ$($0X8 ;^OR Ƙ ET? M_JT !HQRNHhDZPVEN?Z{:GzqPH9,I&Dc 2@ ;Zz{R_b!XDH\_帏vu,o@d 6ހr31a!TOabC$#d送!>(xjz|0:"tX҃)*0 G"i`HGDIN cK`$x1|jb+e)Bp_B>EAAR4Tq(AZH"qJ 4@)g (} (Pk(?U ce P%hQrSAL. @0AI 8 ^Z!xncߟ  ;on 4'^<B@x,*0 s!PZwԕAY-lV@Q3=T4> O ˅aIY 0QC Cp YT pUipPkKlXWi۸p>Q"5\blŒyQ0B j^2HT,A`{7ZԠ|x/)] P/ YTyu-6a$C rD$= ` !(\πA{@*(C@+JH, X+J-h(z4P}A |9I!*$xЕ'E47aN9UA)`e{ɁÙB#w1, TCbrAOP}""4_0ut%,&c@s "8hCttX $z^!MH<@:Xč06R"N(GM$@QAOM:MBw<@mAd(rH|Y!@ z"tC)Cל!ey bbIU%*10 (\ T#?- 3PǗ  <@9^BO<EmD?p`Dsb ; !yZNL  *a eFzQb1@? PX&tfР2+ F 9==p7B vJcU Pm A0&Ry0?h2$ w ># ]:GiyB*~vqO!B? {͏x#( ج fU +aOth4-gIFL?.`G W 0U PBi@Q?K"cՐ'n"Ys<"sF+|\+Wwv2?j@+IyP$5g *@#;"2Ec€#K@Wc##^K}⠎~ J'Zx s@%@ z< (^6p zBH.(Pt P@s(dɤLCH΄-Z@Q`J|#BqHMB}9w(P]N^Ǣ( XC"F'Q!PAgy-UFٹB0 nJ#K)|LԘ,_@5RuƘ+1ql\JA6g=m؉T1",Hb@Bt~NPA/!"HLL@$D8D6A T@=@h +$5Hj+A -DǓGHjj5@Q'p9G\Hb A8hZ7B MW~$SQ}p@R)!mE߷+< ˀ"E#G1 tW9 0s#@%FaKH8 qDh-"ar$(nzHPZ`_K.FD H3rdBzrl@LVdwL<H&A &"aFdQrI>Uо~`գ e ZR0PLyƒ) 3@ zDO$B$I$៝A?E#@PJ6MO!ܚmJ .  KLc ~FG b\IJ Ze?K[j1x @ \*dcv`?@h€¨ᰆss0ŀ@Q iG~1Q(h) cqcGԎ$b!~(A5Lm8@i !)ñr  t?@./@t\`Jev/!sho ­B$%ЦP*ų_`,PVӾ[)aZH4X@Z `q 7HGxPm q_61l яhF(la}ckhl7K4>EW 5!x8z4mbxM 5E+! F'#Cj!!!!0PQ  (aa/7߄aKxSc)3a~SȌS̸@ b{X#}~O@i3z@V)FR֘i!tM=:Q G1tCH``4`%O:-v Hk3O*?$@B~H44 sP)D~C"P(c`ؠ2#,0F\%(fvx݉0km*"Q?ϓim0s>U:H/\LA 2 7~f7 8L@ߐ !<^B #t  +;XQy"NXZ(4Y;<P$p<ѪVj6!1oq@" 0Rb/ |b/6} O" % p 2ȏ}BSx*(0ZS9@`B-,+e\@;zp&nZЎB0# NXjAB¨-CCRzѭ ,y Y1R TD r hHP +6)O^IUy܍@(Q,ς(*00Z h4P7(8`$.&AHL Y3ЋGa~C J& m?)˄!T"1yk"k:q)#BҤ0`p+F`BX1=&!Hej  0xyL1E*IH&2I̒DTQ0?%QPJáb= EG]>> > N+P } {ާU" IQ5"+|P7X)k$h̅CAxXK„Pq'd<ՌR|{wSܨ4tpC:TT Dտ7ʺ WS\ 3p@hoтfT ;XzaDF;Vl`0e W Ѕƞ%IY^dYhSh4T"J*XU*B(.M$(hY HXM!#AFC(hƌ~p*n(Ez.Ұ0A׮A[" %<MHH~1}`h:z8 !z$LJWR@Mn G.zZ\J@ Z=PGZIK@ HA4ABbLF_o>MS% lrwUA%1B ?r~ 1Cp^Sɉ&z2H@Aϲ}o EwNp5+QQA#XIQ-/ Hvˆ@HAp&"yihLր%7ʀT?F 44Q[ LD5tBX`S-Ԫ(HBP5>H=+0 @UD?C q+PADFF>9b |(@xXTiT~ЌL:5/:dޱ rDFN0Ę04 FRO .rK"̑"Im߆ժcTbB*$JV~M uY 'VD*2T,&CXbN 26y\"Z (S2g YwU4x,(- CE"xnEE62gA&KJ228kPa&@VR`T ӇK(,UO ԋ:8>RVf S~4*/D 41(M2_MAL3?#G8c@-iJ+-_r8Cɴ % t &4ǖ!y wU\K|%$B/#ȡp($haQ!YKrrBQ U_4 @`E eg@ d %R0X4v$$CPN=xX yc)EGhPH$2TJ$I4@ )T9"r(q  :AH4@He8 PRR@3S) Q(#E! PG, ("C x; Pϑ,@@mBzpGw@ػqK7.1,1бh "9V@0)"/`@Oe  p~jQ2CGˆhq@5(TqZ/4 J0փl?FH!C 8v3*. Zuߤ6A~RzPE_*}$;1HB7:xlgƀ 6@ci(ųĉ \ &H&2^:^8rI )pUp?/\ 'Iih0󁯨wtjPCCQ2%!!?efbR`*Ԛ""j_bʄ2 ZaS?4+L 0 c#YJ 4&A6)vQ8g'eYvF|-H8CǺ~0@t9GEJDiǠ&78F}Ҡ G `Bl#BހQGi#D#Nq J#bgjqJP 6^CB* mX;2@5@d4b$Sހӿ̉ o`Q:aQq A91$[3["َH ŤQV?0`I h8 J%~Y(&$&7}hCZUP*?h7‘ƺ! Cx$#t"y.AEX:&n$8V1#5`F⹡@m9A7+@A) ̀<id">69S`&2օƦt&PE,B)(RB^4P^TUnO5ͱ"cɳ&ҐAS:J:FnNP† Xd@ (OIY WP_QMAjTBv UJU#=p98=ގ‰ `n!hܛB] _`;cgPWQG$0@@@E*ǔe)"4RyybŋThti@]%)d#*@((80$PH )IU]\A$*Nky,@=d"N W_?S X :D HO[Ǜ>0 qp\hLbCŃhI2*y ܰ,A`$ #@Ag] *<I-x0DrK!<""+.@p!;NdT @h,JΩKyYS@8V2R?P8IPCV5fPCU]Q[|+?lN?iȧ4'8` S?݄`cvNLQ 0q EgNF\JJ G0v#IE;QLJ( pWq; #| hxBTFD 5aO˜;(bPDBMb %r* ir_s: aK.VN")Pj14B$*HQЛPJU@6J"A l[()@(*::P$@_WBQ/vłn]h;G GFV P&x̙\1?)i  HI1GQ!]JPZ@5/ABl ^OBL/!.s^p,Fj=! {9(@!"ňJ)BnRR`2KCYVP{Eh#-cڢX(9b0>-A ?N!`o~ v偯R1QBKAV%WbTR1bxQ' X#!{,DDT1#šL @]EVo!U7&\~%&r6< )1v JC JZ#w䬠 !ι!+a/y^svohB5ED]9~%Q*2̕Qk30U/P$ V b_}VR`D? W%:,aETrZ" S Ta VJ 1E$BE"  1c@0DQQ(Q&AgY@ehb JgӘBOJ0R֤BQaD (1$a84V  :$H1"A`z,GP(}BxnIb7ؕ *X1S-8Ua7 sr+QJئLh냸ҁ6"5 pE֔$ Z(Êr-C=JDcD-!]0!ij^,+s]AcjGBD&ƏP/E}** b$dr9? ~c U V#%⨧ (q#G HYL-yz_OY,#:b{MP傺ȌF@| 0KH vFԆ0#uPRVhduGQ )UC]C{4BA"ʌ4(bX>L)"]9I‡*v<HeATbTx $QJ1Ϝ+˦F+X⥋^|ʀQ|pv=*eXqk ¢^0I/ԬH8 @"4q@щ'FJo|2"JJdJ[oKH^ыnW( "."iE;_($]-RrP@eT5 24C#P Mg@]HdW ԖS\U,y+h-d~0 @5U[PA h #CQ4H@DOi`B娇{$D$-*< .Vؘ|J ?m]f>:Eo/uD+u%po1zR(qt^C,`1 SHp&~l SJ*12hIr_N?CmQ@(­#eUۺ0̞S`9נ TWV4s]8LۣKpNXXw1$ s_lq(ӮɈ#N`gN+r88‚I4ߜJq!WDR;ƔaH@W|a[TbGOš`o(,Bkp,3zeaQl H~cx$3 oUɤa ~I9g*Q w}a8`}'^*Hf@ }>P< a6"&D5. Y ňAՊ!8IUAX4="bS~Y~; FD($U#̆(AJb UJ(pM`UH'EKPAzXc ,[?s 9 STj)"b֍\0iRтC 9H,e(@2 zLퟞpL`TlE=i6*%a0d aX00*˃Cf dO#%Xpc 6M**V}_MiirAQQu01(`sCqD$r0 !Z-AL`hh@F2+R8zxu_^$C|?$ 5I2˔K#!iK2g$ CQp&B @\PTWb'ʈ (- $Gz! =` 2pc?L[z ȑ~ 0x##ɐ|x9p6@,WXt藈 To :=? H$= N PqL@K\VEh$1eF "5(A "8;HIa0(״X]vp"Az=@he/d_Cl\R8e -paO(CR ̘ s'px : W$|?S/a  ^Â)!@+0h0ʰSkEBjB? }~y|*! V" E" EBkBEr(gN!SSyKG4Fn%8d_Pj ̈ yPEr4K3hKwMI?Ѹ5'p7 [9sP]9˷ |Ȱ`W[>Q@B*@+>c ju,6x `,@2k$iOHz )U )6G0õ'Vm#|? 7/-ST.Ly! &Y!f>!,9ڕ?Šƛ(ߍ0TH5A4ap G1,w_8yh'nE,`TuIQ|0d0|Pgǀ' 1R)E HH UP &> " yNF `!$RHE*|n!!!!!Ogm!Z \UA & Gʨ$ht"J+9m>X k 1[LSO@( +P"u&$FJ[`@YL,m#  Y`1r9YpwLZ>sAk3C,2`$i  @ t)H5">VN^BDAAA1 z AH P tqf/G:tT=/~n A]rY VI !Ei D.˿B ߏ5@$S7av@I1.z9/T\p, r'qsT))MDq j"~H0{$629wf$l @+`3 ,|XK,!G1G`1siCCP.TChCJ} 45uqꖐ3Y-$ X a+y AHd $|zzgaJ Fʪ]BA'd< Hjd9A fHB"` A ɥw(@XSǢϒ+FD Dt]H$B>X( 'XO@ PD@> =C1,>g ^\ @4F%<ҘԬDFbB餰P"0P!pShJr!RƸu]X0! q @ťN?hqR? ,bK<$P `X@aL` "HZh~ŵ8x8aL | D8 \ F/  "D3Fxe$UꨔhNd (: 9it(@v@*GQR_AIeN,ד J"fx$:!R@g K|0CAA_ P` FupBWA R U0H|GHQ% +'Sۄ=G&@?6K;o&ri@ص1_xQ@\Ɵ(7SX#0l} B 0!H,8ARޟBdHYpZa‚(\ػ0 @w(?$ /f6Ux @' C< D8B\5 W,x( z&'  R@0R SQLL3l2LOz CAĥ (dR?4s֡I] EhA„3"w;ŠdqR,b0WJZ(o =i#6exFXB k4 +'D1(n~'5D$X5pGtH& [ Fb@" 918B#P/?O!styW#xcP!gUf{-0ä"$G(DLDt.Z@¯_gȋQJ#HVy D&ށ8i2bάgM' 4zBz]M& $hpe~&GALiD)xR6@} 8 H1r \$IvQm;*zC 9 0TB( @$ dc FC!XEz^:ـNG-kgL23C*M 쎏o7Ԑ\h ׿ YVu!\@`X !O;dIAYCC@U'܋ (Ae4RB42*@1PP84!ļ.Q1Vz82$R  ~%TE! -U@HZFӗu3ZBA6XM,CKR/Bh4AM_0aZBz ƨά9(:MQLVs%hЖFX}芇 t!)dCMyt A *|X7cU?*VU@nV^j(h;taU?‡ٰ! F]0^V8 6!bݤE? )H<(NfH` plB=!"?"" ܀/ILh8v JH05 - ly(BĠ` e(@`*$W`)v mMZ% ŒGSG b@.OhMO f] -*썢 $jl sGh ނ\w=]@4@`|C/ G)AL? >_X3h4C: h %L0( Q713vupTUD3j؂!kb "ǐ(k7S *[XA'5K<289;3)Wα MF.<!KZ*ҳsX $V$*Q*ViD3(2CDrh $BKA5 }<_)^ b+CЁuU!ږFj yc1%n=$U%D;ZD4!4D(eOa@bFEȔ`l& mg^!TUE#3P-~сtAypAJUNuG\? * Z2Qw0S[BPq20l\cZ%b$(B AB%"le GP9 GZd/(J!Iq*KT!^yu9+O5SS.|*;_@шU R&TA 1Zc$!ǜb0 [$Q+W $A(9JB (.*!J8 1DL8,y 4 6Q!2ȎDK􍆔(BBgI q%(X"3M!#Q `Fp@l(4+ B@h`)ԃHE HxA tl%䌡ePDc)JЌ҈H4UAlv0TVrkG[!|I@Yܤ傴iQv=.#TaDDvjMjR1@K* d!J` X(VJo!60%QL*;3d\i'dNM-UBP&*# &TFP_CaC W CU"()?6=1=\ʱFQI2lӝ&Zcϋ;Pч$HsUT~4 !(Py +4Y-?BET, yiP骴FPa3Z%(B}꾑XaJڕkl2V It~^|9$Q!O`H>3@P"AG0(A*j٦ b6A#L5 AՀdT)GTG8j!&aF@2xX@ʤ :B JT)A`ht|T $b@"X,,$|8 **,%HB S( Sa>O _* h%l*??bO1$ : #/t 5_~B C`f/FH-D#2HEX}o?lS0? (jд$b [A# FT^D_@Q:5$CB©J8]𩀬M$MAE xQÒ2G>O< ,d4 $nV;bd4G8',GNJހ@Ë ^@Oo;179v#\)$$ mGa40WPp0Qwq_ Q.\y* %VX`l> \0`#ДN^i|r_,9V?'i@21eTicF#E(wQ Ezғs33 "!UuR#?@@`~@^#l CUAR *=$M(Aj/#Gt%90@D2(JT 8cTZ4 B=˦Ut;Y!x\QW.CVnTkSc Z N@f$؀ 8,H8TPtRcX(! ŐñRdαQ<)/.W)r $/U;B"nDU (2 ,G#%R!! @+:~@0N!G51pQŒ(A" U]c`1O98}@ `yHZ5JAn8 B(V#$2 !vQ @DXDdz@DJ{)S%c)@rp)<+ʵoג Tu tVL:WtT j-1x  "b;0R0Q b(`Ӕ"z  {CEXI),R?|ULBaBF+LxgG"P`8i-(K|ٔUH_o36(}6FX D> ":Rz 'jh@iHǤPR]OEt sy$6bXb *C&5 $2Ux&tQRRrnAhRY!$p\A%AtXqv`c-5(zd,:O J hH?@* &#Aĩ-4q:!c4bJCRrzWtHV!"ԩ!{*($fA̕.RV:@ %A@QJ! dX;01 S|Xpv/З[k/.c`8qINGS,dZ2^yDɧ^j9clr@( $BD`i+B% pr @t4 o4S%beykx_q e. CG\0 D@8Pm z $  p&/[)1(H @QX/GHKD: C.-TRD! &D2(9Qa4#$4R`lLBM]$"B/ׯh!ICR.lĵ8^Uz9pqɔM Q"2,ZHʢg-ZlF^ ::nNYWI7}o`X!iZtP8.t! EP<@٠DAC(T UIH?A-Zb4<ʡCa&)vH˽nPM=Cnl-r9v0><ApD@E 0$@DRVegh X CNXDxn)f#"R .\$*axD 89ژ o>*UhYv$ 3Ì`]U0$ GNi*,R⃐W)JXPV H} :ꪔקŦ!]&h!:bB#STo7‰ n bk˚HT$3D T pQbTe GHţDL`D "!DaűL Kh`) @M4IQR HE,$PzH $q@ R 2(fáT (FhN Zu箜!r/ 6z<]hzRs ,̆DFOX`lg`2o(HC QkXkH6PdT@LB^ LGU%3K+N ^lS0U0]h(=q6@h!PѤ,(QTB$Ic@E -(@46ȝ .@ @68">a! @tX"gԛH bEA*P2IEADL+83$i @s24P8!XFfu_O]zu:zJrjP4V<<ބt_.$OG 5WX*4\WTU`h1Zf”5jCٴ3CHRyj܇u P/iDf˭qͫz Pw1eM%R/%vKfUt"r|Q h&p!s@!@4C0F!LL١爃l̼hlB!# ☂ D|'A>@o  B!X/j@5%FJ"S;%"4gdb`z)A`{),xEg`MBдV.@BhUQ,Hi@4q#5en@B/  @A?>hx-D단ҏ'FUA!K0r$'RT#aWW؇d D!I@oHt̂G!pK8A-b"MDGzEʿ04Sz&(L=@JVq R%^bH'hSV h (T2$@6 !Dh\*Q %aR4R0B\@JfEV!"qhĂqNх ui/@EŊ$4ՏTh{ge,dH.Gx#1R)R,G5 Iy+E5s(kb9։stw=l%K5 ի[@G6l:(h qA@FJBzQ1"pHLrCFLD:r% aHkLe$W>`6SBxGxY_R\& `)`@'QKMcAZF[y&]ɻ7)i SBjV(v-+XK[ֶJՁȯ1( fA@Pjj : >R*쿢" R5Ȼ:8B|A+x:#gQ!_˶Q(]QU/ԋ$'ΓPpj%kݣn i%h ŢZ|8 z=F[ MEEg-B9GpX@QK|kXK?i-H*4 H( HE   JBj[@4,"EXȭfQ"B4Tu7!|Th"$ F'.:~ RvPl W?}U':.ԟG˯CgѸ2uxpiٰ)@Q- pb71P! ء=c0(wGpǟ ? !"#IX)Й-5vH6.Nxk Q6bRR1x1ꕉ~EuB@C C4 WAY{_$S4` (Ռ: Wzބ [BV)gdaZc2K[ ōAk5pejҥT$hF'ձc%ȹyd%P]*!ꔨ{DžQ-P0M2 I(3r(0Wp61-y9ʻ]pE/{> aD_f.=0i=7i˓k=')~&襡v]"HJ B^iR+B9DBH'(mQvdB(JiLst)s47`,yp%1EYQE=V#5.D`(ʢ\V^K AХX9DV=^A `B<hf;{FA7 d# !bfkX!bQӰY"A$(‚X!L4j*V4@P!HA$IPb $BAdiĊw.SCXhI %h!YQc0(Qd1嫑!nÆFƄƣ@i|j$*e$F$ QceMPO$V@h~($~;xavĐ/fBGQ"g3C؛& H<C8N 8 ,@ @8Ro` 8үcHWͤ<0sV|f(4.&0h@58`IA G!u0= E (2 Aai :PZ~]5߈5^`qgZT-p5Y1Rח-SFKN/}9 >)zr `=ӁM0fw t B&!@!P`o1mPaW bq* , %LD"%lK`,ߜ@" Z@ ( %J"UsUDPoV1*™SHQ_A&ϥHc f P~8dvs1_kOislAif `N J@T҅%銟 )2n&/HRz$Șcm"z44hbd .* b*K r!Sg $#$uKʲ\Ir K⑎5ƛ`F1'^q8,(D%A`iI ST Py -@RZ/W&3 RH%@LT!M:QZ:$&(bB A@5q$I7UͼDYckQK =7 "B<D$k+"+W5ﰿW#raC?S1,4(%rg BSB;lC@e^i>&yn`23@vA\Zgr QV7@@?Br-YJ 2 } (NU@ h]6]>@0H:-MFLe- GJ@^~F@A 8d$=&N-?JLD!D`/@hqvR@8?*`5}jcH($v 5SQ E*>H@vAbp'| aABpnA%B(-j (%!@YWB P@Pm*I@["Z`}L ''l@4P|EIvRPp#DIg95R4 0(.U==E8J?P~9 4Kǥ]3 a!$:śzJ_$nC ӰB rd=J`7  FADA`aF#BZ#,kt*Ki|@k.qFh% CZ$upi\m4 bAG}F$t @6L5|!-ڿ#5撃w^I}jR!.TWdrna8K)*6X/ ĢGDXTb#d@B NXS q"zBaQ8zɤ(@)Hyā2!036 d+A@]9!H":cV݃U]s4+ 1 ǐ-8Ât@Ll)o?!QNL]cW q0)q4yyr n4%N*俯o@Mm =4;ZlQK-k[Y fZGhqb0C@$ 2(ș> /t0 K 0`I*`gKiTE t0y8BE9*8CL4:IXH@Ҍ  " zH3Jh}ر8sTFJ_* m[YHAHAeAD!HN@Щ h̀ W:+F)H`;UG221@JR1JKkm7Pf|.t́5 |M Жztp9@h&4(F}F(V@SA4N.&4SRIƃ$GB tH!A%B4,JRmX@V,X*0:@4f T BBzQ -@d@UAdn"BR@ZD6LQ@DjD*DJ@X= O"CcI2`5P\AOAy35P &-(J:@ JC*`$xP'Z7?PA@͟S@PYAD(˽6@;D6(OA Hjȁ @$@LZ 9HH;XFg y!2 L FH0Kv0)/ .(15T5G X{0?60 A;,bA .G| j'@ &j ©:@ (6}OhH @ q *K]Hӽd2_H#XU$whۑr 6 W@qVtX0G$DEAJ;bZD(B JF0  Tp %k݄W I2FnQ\AG D4k=!d|CuC#Aq8AkI(;9$&Ld،Nu#Rb~HYW"+&@W3D$$A.4 V" l1 q;jq V&39#fF$+{T8Ŋ R1/)yÊBT"TR8; W=rZ2GXb(5kWaiDVF$*;ƊƊV.*p!GPp&>¡(@ҘHbG(.o4(0"}cF!Р;L|),H! NKxd CyS@\ǠJgP CA$.-t"߯$e6 be#a*2IZnKfTDqȦxjÆ^-Y.% )IhGD"X*8G bXE!*btwVMc̱|X.$av" ;Ic^[䱚2: U%d J$cAi,Y*UX#n?-ң8E(QM7:_ؚ*Ğc4\qt̕XZ8\#F 3(Ni-ax Q+FPEֆ1t4N/K &vc? 2Q\쉄2@T!djFH p yvA`"S+ȆR}JNzBH0@ h䂃A vfb4x~Fq 2z4U '0!ȡ.%ƒ+ABժ@\h# ,?{˓7%g)HKf#H1,#mׅ4FC!Y- f߆I&"eC1@@a 1ɐ!baC5X3h}xFd# scp\AR#@ zUO w]܄j?\4v'9A2&/ѢE& f9]r#ʻ m $rZ5"m (a(b dPx<#Y:y#IU*c ") Q4k hr44 QH,ye4\/ @LV`(,Q M!\BdJPPAխKr 8w@HRCHc% Ak1ubpa`Nc5Ueu;JgV&hΚBHt$B)PMqG*00QJ(H1(@iDAB)K򎘬V(2WKraZCiU4B+*Ie br%$l3 2D) .v] lU h e4k4Y@0,A厂_@HSJP5̾]ӤE`B "UJ1kM  jhREDXTQ1BcZ$PBϐk9czR4ϐSjYXH,I!2#S88DF K0%A+BFJ\y`$CbA &P@xT-/]BI%5 #4#TH,ADDTє.jo٢P&J`(qYp6L"t|}aPdt#J  ERU"uqRc;\Pŋ1-^tcJP*4Pfj F9բQC(ҖV0Frg^~GhTBH ;GWhE 1` ](I (] o}DۄĢ$Wz>RD7#X8"O9hf7܇7R$bQ _ (8`()xP F Py(!1@hZB+X  )]""Sv+A(^?׮"y\$yy $|#&""B1mtݖB ji.1kJ.H'Lϛ0D@8#lA UB)qT@x @!PРGnXd:1?(q]S8Caok Z+jc!b@rE@e&-R*M :H4&v0DH@7!\n tPjtE#XHŪ:ӻ;v|wrDtj|6烋5ԫreDNS@lL褪  E? PЫRh,1@M)2B@4Ji %&FQlv)Q M6x ֘o'<#ջ搢:\%+E6%-QD~g r;Tb9ʫaAqO#1*Un%;K"U& 2P4^nXɁQ`  E & i6E:+/,tt:: BE7/HxgpBsjyqYܘL;mVÔCL(@91G@?KVmntt  m 5S3SP`Kju Ÿ@ H J}h* GHC/.F 4{(,IHKɩa^C^֕ϖ+G+ B W_B 1F(ٝbyW D c=]M0a9"+N N,EFY9iHR?g 2| *ФUu#'`r`<D<@5BAp/@b\[ d7usxt-nPsh`6ߧ]>A􅨜 H" 2b""Ł2e$Ġm-UK)1DQR3a5-jDHWngZnj!V#p#D)C/:_VҦeǓq1* (B28C AdtH^UPeRq+LAtd) FS-XZ<9.4Z'0Mӫ 0 Ab(*S jƎ@EaU$@ ꔡRoS`t"PJ2@(: CSIHvE 1A,Kv5 -Av-U\ *hUuu< q%(AC(-CСar1BgC1A(>@ACEqӒa qrAJͧ]Z8Sġ(`:t  @ hĜLAp!uZ$_0HPpd(%/jR@sqS1$D+HvFh1MMV(@8\QnƊW9QG:?X0  @ D>3G308A䴯E|P((%AR朣x&7 9rqST%G]*K$;zQ$ nA"EQR, QP6@kAq'py"!ŽA! ]:&l,.@CJzT<&DJ(P@(t%!!p~% 4B~H5C(a@VS[ _ BAIUF |s`eNY(,AYܢ˜NTR? lC+1R  ,BΕb! ej[ZՂHB({MC^ hv.VeAT'ٓts]S3KDfjX  ( rׯ_UI"D կ ,xoP{lqMd7|i@rgI"܎~׫*wkB:1hXij3: ?<UTœ @J-(A LZ&U!m-5+hwZCB1f w|/H\b;H. )Pp qCI%#Jc!ZR%E*tB_8p(ICLda@6KR4bX2JB:P+MV:HVJ` $@BsHZ05W7R% GVxis8!,G$$]=.1"`>I  i,i,AXKF ԉI``j@h4AHYbaVaJ<̑F@$_4@qopq4+IΨN{qBĂ 05pM7LW3~FsF(HľqXQ#ԴC9%qꊬaňl!gJBVKT1F}LqР x>:!#_XZH!_5@#?7@̓ [lexޠ]@Bh(e-/U8ԌORI( (Z:"7UbAZ@ 5@i]q#+ !nk9NCoCU0A`DŽEs+&D*:Ox31tVWB (WHPXhQY+C.pHK#߀,15_k:,%~_ 2N% VqBlT[r jB\ ZT!POK-mAWxHe"!Py EdơG4 L\R@ ?6P<h/LFMT r $=]vmʿӂ`<6O,A$A X@b4B%|S3D; g86 E PIj J>#CWI+ 1S@.a(,?d>U~OѼk40 (07)XH!*^@z&L!K7(^PfꁠR[8T)cD+3,$Q)!ֿȐK*:EHA!C*Q* nsbLr*AT&_ 2@nNrbBK%0_̫zz",=-*sq3<2S™"ÁӨiWk2i >oPmG ;C ?{ P`PFל, 5.M\ȝI-؋E[ϊ 5Oa  ʣ,\PÄ(H]B  _$@FBvF,qmH ,w@N(B1PI]Pvv!} :A$D݁(@ J`q(- H X J@q*2JUS%LT xdg!B AA I!: !^H\9wP˒-?1H;GѣbG6"/y !u(x(\W K_pqBwgR@jewAƔ,N,%U;@fѐ(EE(a`F\ hfD(OC/a}~hy¥K*3:2bQ L8CՒKGi+ G B]/hg")N)!h+[HdAaV- LH AĖ |1B:_rU[p-(xdZ`d~Rd|AHJ,cO(4 _i<K2{|&!KG_BsЩRKP,Hur bLA pд0Y-$ =@=pPQ\jZX2? 9 1 R'O@QJx2%7[uJAftqDE5'PL%kU"{w N\(hgvXjhBe$4~<0!o rQ OQYn $zHpRd $yr)% B J:B>T399gPCVЂ-  K|K`Lh@P0VY9k# If@ @R+ r^HfW\),NPv+ "c F;F|tɜP. 53šasT$dE$bk`Cr!PA aJ|%KVzT9+#E+A]h6U)p8b;H;lHNB+Ph dbgeⴄ]|F!}81dA0> /B贚9ljPay@-ez$ IFZҢzd[ 3sT$ʷdU,QM]XJEV<OH,"L^i@5V$8<4TdR(( Mq^H(JDA(y 7hA@A UJ Pb  PH Ti(*2$[UV !_.+D/h+4Q5.w ='_Zr/<"#gF<\iUs1+HM9Acя==lñ(MVPgjV)p}bs|@>  (k[KGy'E&J)d`[I-PgEIxJd,JCG/kkߝME*3U5 }/ OP^V((6L4!@r:THaEPhm 4cBZEe0ĭ(=PCA@:_MA0h5ttւ+RQ+ڵTpGxT|N C DACAxP6~*ј"|XpEx8R'!c9Ad"wDڰooojʆI#h@a)zy" ("dG$y^#ULzjJ2oB 3#M 0ބQ. AA;JHf!zag*TM!grHHT>zN$B8A*荬 "!TPE%$4}(@#Nl +K}JDɹ]_ 09O °"`Dr V{":W†do )>zDO@v]= Z]i", UN)hqY"!/bbM1LQ܁-1 "2&R"05BA^(\R Bݿ{e7 v(fRd)>$ WzHM+fR"0,5)gEY`DIEOX㲌< 80R zN>q%q i,?G c_ e7e_Q\xU3D";׮P .t)!STsrD%Bc(aiAn$% rBP p"1aI:5/)XƣP,U]j,JnӤYQ}/R H9F<!,"\1 ҍkh 0*< khx`S1DM jП/< "!o Q3$ Ogg#H- G 8WL JJD&Է򎽂gJ 2RWQX``)G"b+m춈E &48@d`L:GQLmj[\~0YǑm@p)J"wئ̺ǐ1ȄbJ:yjgPPVգEwI-(J}4+ʝNLRHD%)E/s  *ϳj5*d] hDd1, %w".pW $Jj0 @i тF" ƯҚ)'dy Ў?LT!~:$hJB4bЎ@j*sadV0*DR刅Hb`t^}X'@gExwwt45w*@I52T0#.(Ѧ` GJ="r-.&EC~FjJ@ 1ZP9bRC#R0͋HWDӒbbƚ:4)V QQZ(]t)5i7!Tbxtlx T.jrPǓ[, (g&[$2PҌхDsdhhU?ɐ8*q>Fux]x% \##p.MMO Q*܇deA"Sn)\Y̼26%Ghf =\щCO+(#̐NÙQ)>iV(Un|A6RMbhn>[^*,!&bW4 1^8#za1B 3`pV-* `\s}B9dfL#1xZ ga !'(O"46"m|/@:JAA7Jd'b!^Z@0R$@Xg  -YY ~ZEiV<4 5 'UZH!Bi*y0kkCʇXe5wHȌf.,|+ơ+|-2P̋&%H"Kk2pfkp 17wZ @` ):D% XRDְ(JM)Lf38fxgN8+JD%(ybDc¶BҪjMP ),$e0S`%А&m-7$<{jz9-bY-YR0is7˘+ h50YZ?Y"T-~ _:_7#fb  IxG"K(' !`e(E'JFOv Nf}CE $PKQPjzщa $ $bD8qkG?(@@MYx&`c0 ߨ9wC'yIp֠+K L? F4 BY Y $_2H rp?‚zC@#8@@D @9N” '`c@P -XAd$vUAj~F$!nw.r, Hw:L#_Yf!;f!(h$$ QphPe)"4V !&}ɂJ.rZI0'j*JR m+G!֊ R(\>QLiE܀HI.  L 5bq Q*̌~))$S ~h= _&@(wdX0T1H R Y@cD@M'+J @]@TM:P`tPaH2DIeQNPЊWʱ^<Q`S[JWPX#j$-~ q&D(a$q li0 b #ǰ EkVP:zHaGP 1P{YlwhEW4 = AܐJ@CE_Lb q M4 r`MSJ7,@ C4P 44k GRX,1^  b H$% TŌݫ6~'嬒X U,'UJp> EB4#acc$Pm PA*ІMj!BH[\BZ#hz mD%CE rSs Hge0+H~b=_ޑkqY TU;<`_zD9$QAOJX"NPyAp*DG͈[F+`D/Mz1m}fAD p[KU _%1EKgKL$ytJbhZcO) ;HǠc~'.YI;B0ΎVp*+ZtɪqDEtѢ;@c @]HZ+,jPP7L("PhG&;$,tz` !Q:IvxIy@j09U R R h%A R Ph BFH6 3B4C֎,6 Qj(j3IumkF\O*Lb.B>*wuHYMJU?i )Ef$2L$j1 dcH\ $KxYi9 HɦfS ?ՠh)Ҕ;+  ӫSBDLQ>DO" \qH 7D Ăj]9wvBh}B`B.F>E FWț $)JdQ ?ԥ@<8T7WԿ'Z݉̚Jdk%2IjL"H۬ES@y:@`(yEJH_S0P*KP 8t" -+Y\AOAQY'GqZl6_[P,[,zm !Rf `@ r ʦy@,HXE"$ &ӁŔ$. ddY J$GƠ b=l |  ,kXFS0̌3cTjc;1W#F%hH"C.(q!00Ae40ILJ$XKJq#L):HOUβ- Pa&!z8jcHbHΘ Odsg㌔Tw&,(IOw`4KreH5 zi:JGF(2HV QZu? Bp@ʡ ]0A&~ )&;G/T1 :P(Lf{&L2s¥ҏ ,&uEtB|jѦHi1N5P1$5gh3##$}=@MR]x]V PCKxGP![nvh/,FD"]g{:!G 2PKby !CJ 41Y0!T *1`+*g$` ,<$D?wo<(Q@ G 0dm2i b0c uڠ'Ggh 3U F  @4ED1Xiԯ I,4Y͐E_44ZI?А*,1 R,XDҥnl<:lW <( !d$P'4Ag~eZ^ʣ[,i1$Ua%B5ADo:O< &xV.N9HA]N`l6 ~`jnx_ n=[S/hTR`&j))RP% X/~(q6_B@ hbzu*$ Hb ]XL"3@Abή*|fؓ@.Q;T@ϰ `!_`p64Q^tjd (LP0'l"SkG%{ U @?Y`H ( ,0  APe }~ d,J* q8k֊b&-24Ap`q)i@6qvJ2\SA BzYQ "B#ajCtajCtBԆ RD-Hm!!*@wA_B:_nL<-Ps,t~KVY:THQ@4@nj鳠~>? ʀ#4Bi> c]? vR?ҝH'tˤvC1Vs2c?G%e, r\ÀI,D@@aP`U hAZ3B2Jv 7#!_<0JYox`ࠠ ,dC/^"\^ ,!nC0(AƎ[g`$ %@hHOr19 AO~F@8`Ü,Q ^`Ţh )}8J $ QiQ#A_E~ Q$ P%GC %! _zH )j} 4\-7|j)_O31~]4 ?ӳE(4~NwMGlKcDY NaVuߧhHLEs`(Dt JQ/.4kӅ$A~c>_,$kP!Qr 1ZzF,oG`6w @ Hd H$^1 *=!D0E'HDrICw"n*c[qB?oV K/$P[JH/݌a=ʀ傅0`#s $EK  Be?VۀP,Pc0F~C0 R"(x#Cn"&b%$T %=?2$($[Pb I XhP>8+0=!!C J= }em+ +ϰwG"W@%RkeF˘΅ :bӄPSix)%GװE`p(q:C@rl?@/{pAB]($ٌ:.HP,3dxHه`Fi`%FqBI05p8r,HGDpZ3+#ѠS" jNG_L+O*1 7䣋-\("=`& ^ ]p0^% t!3v@e/ij!d@QSJ!Za0ڌA54`Mo 6F#I.K  L*.HJTONL ^6@r? FV4 P!QPGD}|.4_pz~B(BJ(E3|W'g2?0 G8_B쓜4B?|@:!' 3ViH e"Yv%DUHkvG^H+@( k_f"*A<P&,a!An &xjAk" Jgv$BC֩&ݣ֑2Ȳ 9<, 9oHQ/bhLFrrp{pW;F O@ 6MH98w ?' Wm!Bt0? dA*^\*q-Mq#7pP}!LUfbim?1%#T_i<R Ѱ4 P֐@ @dSk(,8%HȢ@zѡF.,$aK yB@PUt4RF#`jT2 +` #)P(& !^yP|Hx BRz&}ӧU$Hրh01M6Z/ZGꀖg6q48Bk?E}D5S @E)26B|1Zމ:~T)%JH=/A^:Uj԰OzY"?}p:{ "tr~3A #t1X"zQVCH<S<- YD0L~uXrui EbN/jHmOI0((`$ H PmA O[AX, i53/E@,FDY0O)ɍ K.Q!B !!JaS)߂b lAFԔ@ /f A0$K|fEbҟ, I {'A A rvF g@ HUǑMH т ˍw8`vE^FȐ1/i(:j 18`$LQՅPQ+(EbaN&S(GXE=ɍh\vEY s<|@}4XUyHGCnyT%q$w4I@A24QĦ6TZ t %ڀ- ;eurh=rP)ɠa I JJ!BAh"?͂t|BbYVhtR4Jd!X|- &Mm@ eQ !X-B<i*>A(?!K%O dԼZ@d:߇]sx@a ᱉E3 | c@soS$Ul1Wa(6a @dx)6*I<g!'Za4o VJW=Fk}Xl($ADJN#`ELaotJY7@1lHDp y3z e(k_'gʇaY&(\(+LkQ!Ƴ0J(BD 00Z!N TywLubW-\u\9[Me(Y1TF֦.V0LN9BykO(ATH#AjoN) v $ Od`_uFQJ:u qHOYyQi肝^]`S2TbGR@Tt޵8xC,D8JDF>HQ'?i0^8O.(!Bj0էrg)W#t9P30LY>HMQM=EO6z$4P%WY(i!1k.0h6Lr$Ve3W𡮰c.1jm$bɀl8p }!rgFQ`$agQeM5K}#« B е+ ŏ!Uu,LBN`в P"h"A !8n!JZ mv(䡑̹fF砶x7iHW$!F#lhLkH[Z%DBHBWGXV?e,Eb> b KNLEǕ,;I#Q@J++fs+ΌƦ@-ЎNV%%:$LㅊPv~j1T*bU\Tf))qKa=@ /o(p#( qcb@701]7)c\8@RB-<! _ P ¡yZ>|= xS3BPfi0h PH`Pb-` $FxHT`j42!xd^:/ *:@TTXt]Nq K*ȡ(Q$2,FPX@Ih @V L!E@;F P&@6< V<:x3-@P\"Aˀjɝ@"qd,S4B@kTmP->SEiʯk^R 5$"#kSdB4팸"CzAŪQ-x*%9P( lAH d] ܠE/7E ~.%; T!@rBd\iE)^B )A e0mV^NJiU? )~ `4HbA$c)H3kw P+S@u1w h$@ PDl7VxErBԏ/hnA@ { ߒ4}/ ]xOq!Di@8B %  D@1K($1^AJgg)ߠ [ A@[ `Ly/ #D xt+ӣ1&+Xb(;Av+E+U{0(pu`(`<+&Br fph$8:Fhr4p3@DЀPܦڎZAJ=Fhp#z ЧKl3?RK2(x&"& K9h6NMPhE $}P(JRIq*f:(PH1D{rP1J +S" PZ ^kNB E# TaƫB(e1LD?D1We|ZI@\ᒡꑟBܠ *ˌH`(C򊉂S@bÕh[(M, 5|u҂=1f_1wR+@/uh O9(,&z3;^"hY)QF#G|+!k p@DUe2c ANRQ MK Ii1Q I0&WJg"&գT  'V)*,!A=?4@-܈`_Ԫ!yȂufAoX$l-J,+c>w&zQK@(tCb!OIGQ( `2 sHSt' `sׄ`aG&Ң~GUӚl?Nk0MXjM24)G Heˬ wVdPNGш\.Yc\r:LF i,'~ j9ƳEe%li($ p( qj E'Ql2R\Ik{ejCJNjY$?P|w!? 4Ru6>C)GnFh"(L䑥DT0s8 }YFI)/.3S3b" X (1#E ,BA1p& =c;eN Ú8˖|Q|0p}/N1UtCw{ .B{&b56Q{0y 5 `A%5ΐ%)DHA#r2>۠ DkUA{-h.ցX{ׇ &r U D :BcA(fx.Ri+M]`ygXuI5-s?H9D"b%YȠ  K9@ji(AM%2,W#֜4Ult|#?E<9?E]>S@+By-l Bk_RD+zcB> r8}x3oIH]<=CKh pbX<%*BLt1KCCm>=HDo'~\M$ P ޮKwsڰSH+ &M(ZY tK^YvDхR) /"]( wC 6ؖ9۵;dʆvs3 2"!bDŽ2@SaBt J$IR:Dڱpe"£!!x)G4sf B+"Tgd2+H RM?Ő(B?`hp+" 8~1"g<ɠand3҅Thx8y1d>&~ba 0G̖ <(L#Bt[y0W[|^J̟ZC\Y#INO"PV^x&"!,$=i?3-s>CCqTxRI'qq**Q"hP`ŤsbH o^FaLS-~b d>Oz!X )$[T#%bzf2Y4& }̹4>&EKDOtCYCJ_(caL %9H жW9x ; 'lO'gǁQ(& kr}aI0j5eB Q &2С $E{PuU,`up[\RV!E!MdoZ"=2Q auJv´GE13ȣ [?̵Rz3ȤNizE=٭d*~NHKuWW Fb+4 I22BC: BS0:-OL9\!-4`bj)e#Kke]HIc$]|*+u,l7%J%1%pOSĬ%#ۼj[BzbZnJT0@  HrF! scȚbXJ\ yX}Vej8Yd*? ]esn.&wePTSp;}!n[pAkkQ&*_"A; ]B!,j3$DcI(RolS@4N1C.FIP {P z0 hSK3CE!Cơ?:?ai5<@ XnɊ !k4 *rFRJ @4Qū:¡RJ(꠲y%ED$dǘiJQΰ8i*2 IhPxQJ$ +J8(QGDFA 9T5 IQE'!Z)H,%;@P4;谦`kBr<)r%AQu1 ?la҂"!aIJGZt֓C^gf.`ٜ˝ VYx?-$%dT$?iDb8 =3 ȃ!à K% \0 tw11b!r|(:CRd'$C'} ɰQVNnY$pP2qȷ*$D]Io( E]`Swh_՘huaO:v`Är B} [ !!jY٧;Qᔚb3E-*_D܉AEPt@yE3 `$vJVeQH_U⶛?»R%]wh %/.,P1I[ %R%Q*r5ВZ瞿_>)u[DԱyvE"{0DG8#D!b?,fR ֙?\vsu͜v0ʏ$D "MY#P/-IE8VAS2v%*3)S!5.G1FZ)!Z{OFy' IQ0'f՚%@0B F+*a 25#(ZJ-J24H$͂)@ BiFqe&J{}0,tׅ0MhP  )hJycPojbUň Fm1l};%+K"ZfcA('hiEIf,"--a$!OQCBn'H[=u"ŲE)Yd{4Io@{o| 26 Z旄fS$Z ˢUM24ތW`.Kq)68i2 `, PB  A,h?usXnU8C$wCiƎPyIVӨR)|pG[敓FO{Lc#%Kq&%A:,DZ!"/c( nm SW|pzisjT*jQ7f)AcYA!踖U;Ul\>2JQ`AzZO(yp>>;1+'k7$Hs< -O\ :$㕮t{㌼QVIn L EJ5l( BD, XK1#TXBQBSUHQga,ո f|&8:ejԊ ÙJ8Q!@2@x[E"R@m$JBѥUgPKQ$`v*Χ#"TU0`AMj\9D!VsbxΊK, K֌ *0a EZtQ⃋p;ST J3ȏ!PX`%ҩ,` ?6?9,&X$B?c1h#bPG=O!iXE$ =ƿAJܞ8.S)(QԎ0x(d2#}<-jŪTMbp'c“! 0XԼ:P餠!ap c./&#'V/D ^mzb!\)e/oN)RC8tpȂ8S ɉ@o'(L`]oE`*Rc@HZ+p5J)bH$H %E]|d@ؘ%cz a օ"x)da^}Dw3ȋd!sN&n͙`m*殷2pW_DI8 Y6癈pxJ,M/3qKN'a~ǫ2!6 (`9# 6_!">r-‹Q Zڅ"35ɤX&1{g))̣"}6)o> =gP-g i#` xeI5 zG* )QqOKGC3eɗedڐC $$lj  5.:(-==)s`s棡 (|ײrp +rgQ;IR[ffF(f?j"yMryhּtM;.L{͑Hc =*Q$RP9|I, b\v+s6 =,;Fw{NCf.*#1m#s&ֹIM& ՚ 0) #CJɡ<J*R5:@b!6z `Y.,4l)D1E,җP. h U X5fP+E!JBU%D!f$D!8ATW!jC$ fp!F<^!UAf<b)*T/iQhc'B_FWE|%{KrzPd+^u֎H;Lֆ"EZF#aXf_]tLU1h! ^":N/WsrFLHbLVtP0:* tTCBQs2ϊBƏ_VJ$!UJT& +> ZdڒDϘp>ZR q 5!mLbʨ, ??cELbJ ,4&WB P:eL9Hf`a1'Tf ـ" q,R8ȕKԓ$ %Hg$ZLS6mR'2JN$b SuA#iPx3R!C!;XBAV= Vz ٠PCf`$Ha*5SG Kp (} e|>@q!r<8 8ONe!5t,FU$RS$MO+5EJ !Q$8$@B2HD ) H0{8[cCRHPe5c,y@B B:Mi 3ծұ/Ys xZp9qG2u5Yv-_`E/v%` @ RQDY8 7&ʻ Pj<J*IYzJT=* H*`:ƠzHya*`UEiuLAeq9' *dtxA# z9Xxe|[,^4\Ӣ+TG @2v!)0vu3F5[ 3 1"cWR)C%D1Q^"b,NDB(̀!$étjA CeΆdH3Ll 9##LEbrC)mp< TxEp%n 60*(%xnPF^e!N:HSSU"su2w 6~D{\JA .b/+#cCsA6c[ȅl M2o;) 4%iaCh"3%l;K hq`|b$88BuOlC xaèt=*! O*kC$!P &(!$ 1u' <[[V IsZIηAFs @zj $cFJ*]J Y6e.]^K <@0M~AJR+k ֑RDZaVB-Z;-zBNĚqi3Jx?($Bv^<#hRȑCVKA+` BKȖ "B/b4xvqhMUV )B]@*Lҁ ЉHB"4dEy v @%HH%]8=Axj RqU ^_G^@(o\#QHHbRZ^JEiłU0%B1q' AC DR0 HAY_"|#x$5u!f<fXlAgXb D~^򪸓(0¿N+tme›.o d J_I|<So`hQ\K|l0@QH !*WJ@ I@w`!puuu>N" H;`DLr2b P:xifaIaFqZH!IW E  Q䅖N>""Jd5@| :*/> [%g` h|e26H%H" ! |dB(`GB:_HSғAc,hiha[0Aޥ3 j{IKx@G "Xу` ؼd"Ù%/Fޘ+Pyv@ `)G(,ʄ҂Wu3y v?R>:4/:sM&E/G$@Q89*򤯊yA:BR)iPB<w>`A,J $0<&HB#A;@@2@@C/1Y'IS (y`%AFUIb`L.:|;8Hh)6i Q%UB窉R)8k.|t֛P`pbDluCk] ,Pq% !Nmѡytz @[-#Xhb~T 9T <Ձ'Ѣji0UB EҎ= Jz "`؂DށűD,[i@X!yŃ/.,(AC(jIAׇ`ԣBD,Hij&ZUU/XLO 9/p ɉaPkL!3R91 v;1\XE,\,X;Ò@pƊ' 9Ble5QA F1^>r!`Ụ FcI@BXkS!BE"QDr3Ɯ ӥ0YW !΢:3d9 2!%2+͇JU*@.DH!%2Ū#"|/@$  YW:vǙxQ$-8d඄Z[V KA5Bѐ4F0KSya1g%{yYO^xOf 9!vWIq'#ʂI .*,HP$B#AI{{aiamDC4կ_ 2Rx.$~8W! T]#Rg@I,!W bK@hFIE*d(AA2+7qdP3uĴ-qi N|&~:I"ZkH΀?u0PБr7 0Lt#@t`"#%!*$4zJ:j,Xuf)ñ !5f1j#IJ$h`Y$HuS R%@ɴ!Ԇ; `f/` 6 DUC02mL%X'i dT!bdL3ꎚGiADR*.MI T `ZؖIq@ {LHe[E "Jj(鎄e?Ɋopt 4ED`c@<إ@qiwʛq bHK0?T䦖LC`Ve:!H^^ u=1aI(QK2-w0wPH $‰`)R<W42@Du8YtGṑKE PpRŒ*sZCWF)}}&N`R? OUNOUv@H]$#-Rw mnw_L0rPn`quÜ?DF N$ C9(er;b4aݩˀ",H$C _b вF HB? H1Qe>1oOT/l  a0 Jp[\Z): l`+F<`)xJ<@2~`4ETbG`X]xwLВE?},KF3h,4 @ tJPЬJnQr[㒄 TW3"ɜz,Q-xZ aآBH-,h@H>ÔC{xcDW0 Xq$@Ďzr~A| B8Z60x0k`Od@G_΀0v r?ʑ!D#M1@ 8V?U>jG~bpPjDHX҂rt-N>@)=>WP%QE/FgFX 7XQdQG̜# ߋHTJ1 $# pHp·*aւi "DI*?7YYrX+@)D)I<ch#+06?,ӥ.C|DQ(3  U>׷+J)# ɼoW0|/KgN#|Qx)mEJ$nXcg&0 N5נ za5~5>5ßdkyPٲ$ Bp "= MV R5]AS܀e-QXi@MUҕJ(tZ`ii:EFӫNKԀXiKFbkTQ zpDd`@hO 7 >0 mPIa%H?T@zb`/05@, %_$|yBAgыG/81!srqRMPF=ӌa@hV"J-#|CH?+?@YAؠJґ _xᙃE6a-)!BD@e..,%@cާ MB(\ u\boE(x d9U bAƒ 2CJ!҈iD4-XWPIڳBE 2 gBvT>Q""]@B` paŐr!HJ#@[`cL~ADATB0$3![hԑH 1"u0`O=NA* t} J hS Ϩ 3 +xCNPe+E"T;MjT"ؠT|X *0BV(! h y+p= a RHe!:!AńVH +`DhPB*dҧ(MlZ%U䜒髤$cB2&HBH)$ L|U"Ml*lb`h(@Ő,JD)Ϗf,4TAjLHOjH)eň@CCBd (Cx&b`F~MP^AL#J@]%?J?BxI'ա $ -/&h+wLrDf o6eDJ&L? p07́3@ L)5 7ǂ;'a~NxD`!(.ғe骵Wo A@Rt߇`gPbd"4b) ,R ?V]U9 rF^F $@P [f&iVP8n͂(TIG"#B e)q& 8- A24[܀e,.++A51AM_[ۮu@#OlGa.R3M\ a0fV0&@Μ(A&5<sl&t@_)xI 9<,_>M.:: I@&4+C ,xi]4Н  hev!dx|8Qͅ`*02C( ::t>/Ҁ:!T Ȩ. Pi7 Qi0"tL4Q@$b(PQ44/ @ & 8cHAtІLO0O4 ε[`0/Z&R?h! qR$QLKY kPt}r VOc <O"ІXP(!S2Z8|#`HH`3Au5`U7:\""4d;HaX, E!J#|> Py@,r^0C4غPCp&~Pl)Y8zZZAU/ 4XB^ZGh*_(d+<`^$CyB!P& @lACAXnZ] *20Q$C )>E?R%7ҐF"UGJGZP ;/`ODo5&o˿bfDɄüw$_-11c@sЀh̟CC4Q4tDdqk0řH/-J&~dߴGgD?-$F"@15ZFz;J,(*ihkII $  h*hZ.iOP! $M^dd ZA rAJCDP:c? DD4Q$qeb=hf~ B\_5!* Nƕ QFVj#Lq.b*S,keBVjLĠ,~X%r1@J]cA' 5gV00ha X фAUP  @z@PT AUt@gn ė PKbH5Nh\P0/P 1eBmxxŌ!疞K1t**;Ÿf][? q S}w@4\^^^"0 ~G"XY YwM裓  yD%Bk/pl\yPf#$5k2@`N]Q":i)Tq.E~)h)P`2_ h I )ESSDt^BtZm gfFZb A~Ø|AEYP RJS$+ShH$FJ*D6D9X H2%J*T$t5HH",\ԠQGT-PK&s ,.@$"BfHFh %`?vCyCa `9H*i<_/t 쀲m4W~ 4H4i!Bۿ PSLzͽpsb@w K_2bT0֯e Yu@ PrЂ'=ATI `| 5 L%< 1$99$2%[ DLxJК0?"A9Dx@I'ࡀ'E DI K  $C =0_~q耞7 @-EVw` PPheh]oC BB#U4iQxM5mϋ^mH`=@=ba˕.} (QIV*uO%,Aw$𐡈 jA^ } \y^03D(P /+j4x,P\"P_}$AzE$Z@ ?IhicqCFcO3(" DP++oqϙ_g`$3D0f?M`UtK_ 8g0ץ42_}% YQ`R38$ 9eA ʡyA//) ];Т GVZv2EװRZ8RIqV9F 8B;9>3/'Ӈ8ŏ㔄Nf!lӺ*4PNXB4CqXrԨV<u8$A B,Gh`DD (*0d`>:tӆ G)MB  _<:YBk?{> $@% /6b)}uА@h1!I :+naS _T Aŋ(J C~S( QK& ' RA@xHS,9Yѩ.0~IEHOE| , Q2٠HMH)ӿ i(r\g=RAQ-Ezc&kC؅cPWG5QiU3水. dv~ ;.EĘ"jh@@D#j,HIK}QO5(\)Y,3 @Y ?cèfC_ \T_jOM 0P pРƈ@)+F1@*G>Ïڼ< @ hWDXҵ$sP"5~p6:S9ŗ2=U@P0y`Rrt}D&vxfb9. DBl/#X]ȢL* Mj9cM @(:5 B K Q(EV0hBC$)k^Z%"K~*pz]+0JKz׆Oa` %!"~/tM$E+׊ƀ ? v[NL%KTԨ`@n B#,X9xe1ve TńT&F!Ak$}oG0a", iO V AiP̂ _K `ʐi! A1! PBta &$(J-s`E4I'G g BV@PAiN FI) A/-;!)) X),VAD)UϔGQ82 (qdH$ gUaT U\}y@ܑV(HhK 0jy_?"xDa#HF1e+)YJ8P@3@B 0!b0DE ]:b?STS!dSRјSn"LU&+? *Sƅ45+CLFɡs%͘E/Dp2*&଑ #|s)S}^ P0$,<B> c,b]/ z@, A@0f4`Y-hRs G#@ P-Hjl 9BF{%)%e| lDeE&J*(thK,&I,0!J,"PḚ4)F5Tb y&ARXéD j҈f21bŒ(PB (PB$P$EĪUG2r1Պ++ i/+YE byJ9:r"^"J<`a*Ra8j3` #A!#J{dpR,'m.^NKn#T)*JSU/kX kP& Pòfg>4FR5 ([!dXI?1>B%yd#R,B~zb2~C)7cpȲ%ȨW0ufzxLrOS#$BPǍQRyP4K%mxٍ|']WIA%~Z`0S H$sCq(4)!TkDA )"`BW)הtD"Aę`1Myb@E+'U(j3A/!̘!^Z\y%",X PBF(Pc *BCĝkBLP Hc.}F91'&.Ll0sqL9_qE)BRH3^@򀎆J"x)J=6K'NOa(̀B"Hev0lㅒMs  `H0" @e!f 18z%Ad <˽U( @]yA-$@P(PT1XIQ-q,K1ybh*Q%jp EYX$h$RRX- ۓV (#ʉ{VÂ5 !DH[13/PKB3`^H8jb0BU!kFSJqg˥7PJCW^BT(,hZB?OdF7IWca_ IC"`b{ WRQ(T-2`VAi 䤗UD9b89*BU*:/^E"Y %EU\ ra>$$lxNbUo>F"qը.K`a0"U%cG<#V FI O%(hĀ >_K`_W>!4'e&1|d9J1jkH-ڳ̙Q%YFH%y%bJ @$" (!#z:aM ZC$[$^c*N QRk `P #&ȹC)@'!`L?ˆ@8 )~8 )e0@> .H@S&Ypx$CJSr89\6 HJ SFs1j#TVPJƱXBPŋ% r@I&U:k\(²x(C9>8.r4|yr,(Y,Uu{W# S SAE͙m+@&QUa p0 d{d$2gzZjqF>(\+QIQi@$`2-DH")u$L@"RGaK&8]cP$%T  (1Q?. q$T"`Z-ˬCpL-JH ʬAtҠ Vc+Z+p(1+v;A WO'A)DU`frdc5+DQ 0 =A(B18b238)IAm!:mbfr,R&(C¤b'hJ[!C5 IF 2a*RN × 1BwI#$W鏒+FEZ*D^1B5A Ԯd+8HN2qd' 0a %@"$K9^#JX ӎQ6dd B)Hm=e۰CO!t^*uM;L2e0^@`#*?P[+ Ӏ"U 3 0DC11WY\ekmHA HBE990hBzrG dJDqB6eFQ+#?=I_\O(" P`@ XjʊE%]e< I:k+ $(  fpnMD-2$ BR%LSGQHƮQ#UPZX)b_,EKa՚f(GYC"4 U%Qŋ!(PB A@Hh-(Ƥ̡YC*y9 `} 4TξwZa [1Y(CQF< >äiBA HV4!8ۋ0eUS~a("xB```̒8[E mRp`01VZ”T j q P*!T>иE*UP $2*H b ȠQ&XӦ1bGP,A$4)(Xב( \ߧ'Bᦘ)ĺdߧEY֚9l@! ʛ$ba%(X S d! (r= DrNAQZU!@I B- ! FW`J0 %B P(-W>Z[_ MPRiNb 0GR|D6=)rap cDŽ GPR-Dyx-U\V̄(b(%2ΆNĒ+Nl#HJ)8'/|4*J]G*X}D: ܬđ@efe}-_YL B 4(&d0H9LDc(4t4vPfdC K?vxVHm5_LO( L @ >C2 : '@MU Ž6q±LH$R `t($ca%A$RT` B<gPqTL+$hò yjE V.%0c1ϐCAUXŋ(PB % 2@(hIBT#Ɉ j 4`M\hR(T圿1LrVܪR1R[Ovtg B P@@QU\Rt 4Ef pℿ)N IlPq9?j9&Suu"!H ٣f. `9zkd01" O@@ F FQh2M0.)CTy4Xx jB JvF5(84$ ##@A@QL8VLZtwXt.!A iZ鋯"KZ5v J&;TgNb@ABngMZ% Go@`&CT`PlU;karx+A%HRJM@!PPiQ٬AN=Y 5MY~PHȭU3Jr5Yldaf#Nd?vt'g9+̼6)YjP# < 3Qm @E %B g{Xq'dUһx!;y[]lz$*8v Yo nqP`<'N u d܄~k1  8;N :"pѡAΟ"4$L y04 {PxVpB@ ( @MX YA h"婓ℂPxk#,D%"-h ?$ J$6[qƟ" Lc3D{x&6dHO+ #'*T p_8_B E$DGBJ`c^PSR"qÅC$B_^2N x… Da: a@dSLjr%M>ʡ JU) Ań0Yjɖ$PbPz h%j(IG\=CH6c0Aha, D#4"(1V1Ud]pY,K%l'd#HGXBD1bp:E"N$ӑ) Id_|'EQ"80СBPM`]\c8nOct'ܿħAH- 0 a2#f]eBP9-\O ys R4@Qȃ REI2TmRIj8d_@@@ @#]e TRr1BCt!j@g @3("T$I>AcA2H!C:u_¢D+,H/ !*#-*qd FUe+ dtY%dv2pvBLB8` ?+8'}.}[:!P0P 0(P@ A(TT[3ӋCE9^JQFyyUhB'+ !BVaoTpH(8H"9KNK#ALa@$ )UA4谅Ad )CPHh.dyU02P)Q $ =YF-q¥? 'iZ>cmM6c8)ϐXQ+}5%(UE,5(6fŊD FcB5cQFJI!y#Cy;/ B  D d~׷agXM# jZC&H=vM @  )adAj@_Pr #{cH h@惮QRADc o BjEH4$* E*`@PV|Z1b * ) A&@&C.k{? H,pDP6"tiDx ( (JJ840ˆDy.fs2PAR߮ѥoEB(X+?/A'G 0hʠ V HJ'@T!a4(x?l(r VI&Q6i 9 ̋ 8FE 64,Ak ѭE(% M~@ 1x6k0 mAaL7,1"`g G!SZFl u=\` ".MpByC g8?>8ϒrLI0&t]E2 !&`%A)KrgPPk< K%\f" :?LKLo4AV J2I+0) F!" ب AF?e׸e3"G3Ɋ@$/q$D$0^ ?%'= >B9HW!%!kp}C9*5@,F3YFB / ,T@+!X*V!\I4|)j/G(H00@ `# p !JHO Z=$)+1h`n`!$YpdtR~xM- !-r>'`:2P qh,FQ= :j8;0{||gj+ɒX8Auc" `:@= mҗn)4cTZaa00*,A J @7@@x @J Rivsh* G:q2b(Y|x̀` 4G5B(tgFa_J  ,DÙx4<*jC1j&`*rqx}@$j[5  AY??T6~OuJz0 ?D'P#;ٲ -BH ?ڦZ@ &HaI Oz*.1]Tk\x 0ʭtMKa.<ؠ!pXBBE5}F )Q3hx:難: DNA֎ 5KUG 3{1qj?xZ0eEptS2d#drX=) P rF#\aXB. T`nˉ1&$Ę"LI1&$Ĕ/>Q,FoX p0 O@CF] p !#8ar'R$$$XUkWO-HD~ 2e] ("!W zO{ܾ+)Y /@h%(=dА' HLR@h#S| J e/W< %"3j@ H"9U\%zCjo0 y( P(QXvj +N;[6N ALb&i.YȎXf1@Ih$ Bp J!j:f"mTTBEQP @` 2CB)B$"L~X`A&>A|6(P T=?dCKN,p_@RB_xYh 6d2Qh'B] @ Ѥxy/8Hj81V?y T )B0B0 #}ʐl#X8QZ^izgL(B}pHmгUޙB J8A^_ /Wr.@P,DC89Q ؘG nS' ? -F/℉Gi hPZT?UizJhVH y38%b AGH&9@Ijd?kOPA,/|e"lXkLA H\âK.A(,RDr4h dQ4OCn_h>!e/'mdEf5Lн ?!1r iL1&@+E8H`mk!EyV|`EAd3Ea@HA.pCIVê >P]ԃLb8@tAdH%H$J %1ꮸG Ss D~" W5d H$WM"WQbԜXAGyX. VP(@bd  `zGzqi8@j@Ȃ %LF1\((ں-l\td @Psc 9LK >\w@hBmkx@d4DC! F,ᑨ@uGq"HŜ.I9'9Vs)X)KV{ YԬB-VJR^Z)b$`ykF#Qs'f*8iTQY+31/@ B$ (t-2,&r)T=~d s(B5u "XF@@ &,h-9n ;N/FC0! n|I6Pmb X~䓻׬<06,P]Z4yFĖQ>/1z&(?7qkj!A\! u>,x} ]?@ p怠>B#8g?Nn;5PF*j24 E!F  S砒(dI-HpZf Oˑ@R %"I|@Wzvv'aYEA%9)Cj@u:[@Pό%^ rcXLHWa"DJ# s 1 # Za0\2yGмLҤa(94$_~D!`@AA1 (ml0NG.V"r 9|@    J٠8E w`sir%(bO  h-t!@PТPAIB_D^~9{5&H_), l(P(@EJ_(x^?@)ЀL/" S:Ӻ ЙVz?P <<@|^B.B">DB _">D9P9@F2w)E`<S,:xLSry  RDD61Ο/dd| p'P(Q He*TWy?lL  `@fAHPpa@JA$ @M#@r&#H 8 a \0pP!EP~XMP  R   DP)(&P6j  0%94RNWU8P< # ł"$,S? P & t#" @b A$)YW;M$H @$0A` H@B $Bee "HA 0p㘂W섀AhB`xYAa`@@K ? ~ ZlC@dKNSLIA #{Vkr#<$ E DRR &HSHGJ .CT @C5+&g@ dNt7>Dax`(Z#X0K rr9=jCpEj)qw6`hAAY~ ,~>?%#&F Ye_B0"ojok5܅XJ,.KGG k@XtUqUh"uu6e t}[Ox N!h3? *~kAv  0 7#AbLdj Z.P F*P$N,"IY*rU&||\`GQh$ [?E+cJޗZ` AHDbBKbu"l 2 !r D(? "p@AC+}DⰈ:?5 7Q.% 7@y. -22P`.t"L1_egFP9䮁,hȢc0O:5%GhX QΦҠ9OĐ[tysDl";,{נEp($P *" bIAQ>ԅ0K$0ʲ'pP*&UU[T}ꭁKxkY)/K V@0 COW_,d@P,Z=p%BA.n7i0aM6&R߰ e H D] 2)`r"QԆAUЄƂEhf+2XmFJ qG" ڗB'# ¿`(ϊhAG9!fZSOlT`x 1x7/A(l}>Sj<"J(u4yrjhw 8 0@4Ax&TM(1bD$PI?*(Y0@? 2;I{C!_ H~5 p KC 2lĿ;FO\!*pۼ!a!a@ +tfG0XҸQ b `(|piQ\$reA}LO7A yiz+}GxV.Dv!N> TY||"U Rm *3D%BF>%|7 Cjt4SX !]`&B[(mƠJ 4QK*0X&9k@8K`A T!ջ/ GU!.,T}oM j@FM&C-{BYH)4-'Ł"4R2jARCል$*E4@Go@"mD#?& kaڂq 34Hˬ1!ZWP_@u0HEG^~/? >\ܿ@  'ET!@})( .@ktEO /U\B]-[_q.w@,*(ȆBBD ,BPƄ@;J" (rj%8z)ZHzDEH$Da!*,Xb P'P 6L>D8*5 EIA =&";8ݒQ=ܴ yy F8$)@(*&jVr_U8L#-xTZAJ5b( 5BۄDڎ\rrWVi2)z0m9 J·"`}/+8[rF|v2E|yr#@) [ Qk} { ARwfAS䚇1@lo0I.Q4#0~k@{ 'Hx{C8G'"?@O )%4l \] j1ÜFU+dIycq7 4F<ypiӀ K6{}lIw@rހjo@6q_?@>|^zjjF`!M }R1$\Y膱Q'@ AYi0CnAȲ?pM,_!%'L(/48esIQPe0.[ 8dCdCqun.D^G^>Q""""^4:@sX-3Ӥ0\GHj@AkNO(LB|/ QY -!DMqKB^i%`0XGi{(ɂq*@ C%D (4"0F)QHDL%8JA1(NE( `4{'"@$@" pT IVE D@ `ʂ 8=JWI0Ծ_IAvkyDVtp9,*QANR6ck?*]k BU5/ J (@1u7"Se1(2 ?T4T %IEqa5B5@WI`hBpziU>N((Zmi ($h<>4&$@M Eq䋔@n% @wxdrAnw"L}C[.?T@d?;y&J "{Glɍ1 tqU&h  AzBlI`҈C-%Hj`0L(D8L.""L0DHwHbK )UL!HRJA0~<@bW3 CV$QibTd r] 3HtK5 Fm=?r׵" A}k?}AP1$@PF@ .N?< ȿ =2Na7x5%8 d%`m՗-!p=H @ ^+u6WMWQBt|"tT@w 5'yep0p i>4PÙ% h&%A@DthA,A`2 b. BAJ*ʆP!@aR=% B4jjC @9+a XEa?`UѭM/ۀI:M`\6SW4MUҡj} ȽXw-@l X@bHۣLF`D!#4NViOF_*= 6`y 崑ğ(vB@(4aEკƸC 4=|x}o06bbE|G@ONa\ bTw09TGC&r5y!?W)G1~yx8A tÿ_!# ݺ #'HEgukwӊ%21ːte;_~!jA <8<`$@TT*i(Ѧ$*98SE+<}z Jj2t U">|XrC:1C.!1O( \ A* 1Oy2Qa@~li/ XTr9ZKb,/^ )kK#AZ;H)/F?,_ᄏ& kbDN‰ * 4  pG5TYpX:A8B9C(08lGh(tPiQGXU%3CiLjz|TI4`R9 xNh%v' A%n''mNM""K͢FŘTNTp_̶3#@fzHT "(mfL-9[*@EnS J79I'gyA8q $=JG`5 Py W^]C0""6lo1 <ޟ)!T!S|?[[?!YW)2V4#2fj`y!W( ^y7XƟ҄\Bsz<4$\hhBiF(?~,aٌk7a2$NnnV/*n{. קn(1ӏN h;UҤ7>a/]P" t 9 *Puʯb4"~DBG+@r頊J(X0ȸAZԤ * d@GK8f9!2iC J=J,.ѠP ps?PX( Ě-Jvm J _iQF&Tk UB8A55a)FkB [BXB!WPⲁF5_i_KU@)V/t T@tR`}X \ iA"{8G_V*Ydup:$F8T~NH e2t9N%@XCk ?Pu/3 PQH@G(bHTTt&!M@km^?^Z! N2@#NPG՚ٞ<' C CƄkhr? ds*QA1ńxk+9 $^ Pb @ER =2BU(%B?U  f@'0P0-k/ #n>!!J S< 7=(_a׀EY dbtrFZV*tPf ; *rRJ zaԪ`[8<\'@!&QG}@*u"AR_/ф+>Ki>0*M2 ?`A*PhG1A >a@(w_,#B?p?:-*!4?BU'` p  np@10㳊# +#3(B!:I? - gn0]AL5q%.LA?t, G1h+s:+`,3IjnZT T8ŕj}2)yA,%p nt c8(D3>RPDR+Ȁ!wm:oB?JTBxU$ -U H('HX/06F(@lwJ/SMP;F4%W!+_"K5HB|n0Bd4@-%ŝ@V/#C 3|.1NjY O?/Pſ1@Bda8 ( a캃eJZ #,dj0!gB9@Jb,7 @|0@44Q@0:@:&*1D 0Ui@!AkQ Ah6HGҪ׀ף69ePO0O!!-,WHՙ %)@FҋOWl|C!@,u4qC @#=R+T2/ d hψDY52Y(n "b@(0Dxz 7SE`B@}D/Hh `r*V Wؿh AZJh@+T2&h8NY F?ɴ) ]* { |?@}M=  #7gfbF^W`O*Ur1xZ o(_ʔxٛD0(N?xn@dxJA(G N~( 2PtrJiJw+8C;M5/ ^\D Zhy6*z#E R+R8>/TF`!u>I٨ @R- iShz 'LG $0!=5HY P]UE G=QL4*|Q}?&P$7@ d+6vh~ ҡV\X%hRGz|gaRGf #Pax5P->S^~ ,%,I00"'B,M%AoRR L#2C%JP:Av(` vB ꥽[,},$K$0 P$I I# @db#@@0`@8yFʅ*#%@ 0!p PPh PZ,(CL)0BU*(!a T.wvQPPЊ)G-Y ^s|tF5,ҵ"h"D *F-&Ǟ074iMH]FQ,+kKɆUAu ԼV/Ӹr < r c=TK b|_!ZČ[WXXDAg / $d:"v ;x,$Rtc HYNJ{59Ab`@g?0&Eu +=Vq؈&`aB0y-lEiDj5*XHdcm@%Lb"  h ua%P$ "!@P4:D+]Z{6VhAΉD=\bM KLʑS XBxͅ6!2ڄVbۮp,[v,OGVA=$A|Mv!$3԰% ~\ªLLA"ixM|¹wػ)ۺS..h|W0k6Y1ioD} 5?_V$w167K,ՂRQ?sOM F ,60I!.R.aԬf'2xXDJBv"YdV^7񒋿w1ů63*uI$M2oyJS: lVh(0 `9L1P %LEqXH*PDP>t,L0FXI*$ IFXX6ր*J}%4I J)BR4)*P!It$"X&X%Eٗ4@PQJzQ#3H{DV:Az 60KDT2)XGZ9Z<3c)h/mRT-]N+䫉y%Shkؓ$bv J9%XݼD!"jqcGh0`uA  $6qJYQZB5zx\0C(BJVI(Xpr &V&r3C02ܛ2'KGm=h|=C2 t3U>0 +ą$!Wz6? [ '%!܌c7_UZJ@p)h<_q@ HA(BTAJ`P ."q" @P(R41SXSBE!h $&B Q -5N :X1":1QMs0 5(i9rY+Lֽ5'uCJ˿ 5YJ%,.5tMWl0\2rVRҸq:`"@C&)-OA`HQVD\T4=m¨WՙuI 3\ʰ_,(PF‡ŗ*`hsD+]V"),4aEKFZBNPf1ÍK 92) AX@6 (" KǹBB(r|T C@,0RYgV; 9"1:3ƌU*2k3U=.[UNk H넬ⅡRErEt}*r`ٽIA`Ltry8Ckʆ/yV>bmg)Py` $Ht&!E@؂f攣V{cu4^rY8g3d:jzD!Rk@Y7"H5BI*P&Lģ@/;,E-52ME0$8$0t˖4Sʀ12IPIڹOYlHY01*]gP! Teoǣ@Ffp9$a1k/SB9)6/%A.B\|p2)RQBPz)]b-wHJ]> snI!2?5P0ትhGtV\TZ1ʔBG] qسCI!a# A(sQlrTQ N ⌭pRt Q|=g#QP1z L ԯ (Ag(BA$ECQFXHԁf QuZOViVN$XFhе$TJyC($h d)J Q(` Iya y|*'Q@$Hՠb2NO"G+ǦD$8D(|A 2}Bgr@HpPR%g0 *.*K8 VC΢'IL-B ?)JC_T$G`,EusވRArb+Abٜ#@ґ !1о:j*E,qA8@Q+"iO;ÈS (ϘqO)ka_C]QvME8Dij4WWԇ,&,)^85#*Q. 14?HE1H,DxD$"p pT( . P$u8z?ʬt Y+0-GW##(گ##4"$@R+Jj@/_h,ʿSZm#q!KE$k]KL%JaNފHF׾B#j'cH*K<" )Cg ~H& Ps ,">CLm!"I м\Eix @p`0-(/AyA QEC rÃK``a(@ `'TtG*%B|t63C! 8$,Šϥ΁&C9?Qy.=.3y (|z/Gp}@-E`BQv]QDZXI:'֑~/ʑye'Oుazō]EBON a)<\!@$X. \/?!#x^,B AiXx|d~P?(7c(\|zPoFy@  #@T8/5#"4P"(@(@! D!B F !@8n^@,J:C3ׇDQC*hS? @M(Pz!Z(O^@Y4 ^,)Ԍ^\@vF7 =L@/6dQ?gB"\A  "-PJ0GԎÇ`CA/ zi 'VP5(r,@(L XdsQ@c3`wDY aA~+p@@#E` @ "5I@*QB sFV@ Hvl N,晬F-W # 4 ddd1#Nj-&`5G'M!i*  %4'PB#)D!_爇& @ ah _0p?4 A0aK'!((AoHs搘Q%w6 K#L?\a=N94uJ@ )3APLU|$ .6(?ade 2* Fbt8@<@P5B(\U/3(})?ojTt=׌I]E\\DSA{,D[(B@T!Kf0&1?s vN jH"'etÓQxVиG@BYg53 9 Y#& 14UZ< ՠ@ hI - IB> ]y,L~0T:6m CJ0$xJ]@Xպ+g`a<n*IYBH (qܑA0 q/z5+Ɣve2`ʗ`gEA9EZҋ$5CN-@ BV4 M7(%_QE W$ P=  @2?aHgL@# "L~G(W4HNə~*#$+<V?M@@`4\B-,d/(i$iZ X@Bt``  $ D^I@< RN $tx`%@ Ҁ4n5@/VQHY]@| Ӂ*0NH DEFȀ }!b(iÕTf/hd Ac(-I`x!I Qn>!!D0D8 H¤/ ,xMP$.-X-(RtE@RdK1 :a&!* %,gDuN~r 9UɕծE_ܧ`AJʑH\9W~`W_W(]`Q^潏 |1g>Ph>" *,(Ddɓ&ij t/$DCxΎ{tl{8@\B8R>oeriD:F`<"LͰqQ-qH?i, 3a؆cEH !H)ȴ(H (Hadc8d T"1貊 T"1X1踆*Q #@"Dddd0 %!!""Ai^t@?\.(?HhDP5:1޽(u$R`Ϭ'DJ)}a,$zr:if&*+0B1tkeXB#?F@(FTJ)@EAja'#GYL?!UT6= 4<d@Dbwa s&?@?5|P`D`" Rw$r ! Zn!h h^$t%B] A^ KC"A[J3:٠Ba{ `S%h1Ά{E9Р#: gBиЩAjt  8>hh$Xdx!Zh|<<]>.JiC`LDM^&^)oen uj| oX~N( !&184b,;W#=0c{8^M )f0^ bq&~(m"Ɉirb+ 12QJTBPA* B QRHm 0%(i)쀇ݏUGڱGfsS>P[/W+W-#ZCA:9@fBET>HQ# '2mpPJ")i@7!aCGo󞧳@т]i d\V@ R]0; Zh8&H$80Z ' Q6hUYДf2" ̐P,+@`B0d"Hi UJT @Pd Ex:GyA,`K ^sii-]Sba wu'!Px82'! p,GBwIJ)Q [ɑ@P4ӆD DqwpӢvSEw{Ԍ>"y!-79u9prr" ', =@+䣳$A"ʢ 8s \bƏb`q&N3ɈxAP @b!\3J Ck@P) Q/XU`R_46EVf 2F0D8yp @&B2PtP)ChI9$BVTF34px4@T"y!jppQ  `1$kh5 dj(ŀ/TQ sH@BÜ&hs 5 sh<S44S8f(U3h>ī~2r ZPA!H 0)@ZHyV `B$NB"jR#v (!0@h(D? APP '9Hx!xEV,5F0.!@F8!Pp*` [nCD$ ()ӯ"D Wc-*(b FBA'ZYiSpATpt JD(*!PqB$z.DOD{"dmE&#N]?\)2@Ր|(ϒ'(b(,CQgL_2?HD ʠ8&\C 4jf $AĜހj>%J@6s* z92 $= X)K0XF G% qB%W))פ!(qHVJBY4)sd@E@$6)k@kiD|`7FHH t4AZzGH8@h%A  ] 2.0P!fBH)aBPY <4hk)O}XP8ro` A/QEb$GJΔ$K(HpIEt17EI($`؁ɓ/亊K`@(_h>~.J8%0LңBEwaSWB H_<'E{#,pTˈ@KUHi@vS*wfۊ#;` ^耢V)"p4b҃ˁUUY !ƀ @@Ph(&q=" l!Dq)&׿hno((! V$m ``hh&aNo)(gK̄K`(88)A:?JߣgKmW8e7LttŔ]PNeVkGq40 Bϖ&%bz^Y`U1'AE $\ko:(ք MI B{aDk++-TEe1=A 1 $賈i0*!\$`@D@K~Y"!c#PJ*u&w)B:wa(<ĺ(("[ᒐ_Ĕ)" 0-A EDPX*.#ʠ수`4(>5@Y#D⇞8etyHPp$a&R@<)_hZ H ;C xwHeH>h+: :\\ bЂ5NÆ-#/ ]d)jBlI|aGЂ>DT@,ϐT[?ang{b#ةA+ ? MED%NO`RM_,Ru30+wbCqL>+"tK74HU* D`FRPz#"yn3_q)U zJr`/0_J`+3X$?T &" Q:3/d@խ  `$@slGT BR$$ pjF (Zo$hzՠ_q Z " UGj4w$3|ܸU~=MSUtlXY Rlh'ȕ9Tv5gs%owNdbKh /*8=$OPGH0o`?|NRn~e* +k ]9fu%ҪYsH kNS'[1^s+Ve0UG X@0(:zDN@`<j5B. q~9Y: Pr@ќb ? nF91 M~""M@1 y,!APF/5 j}>}J# @-EcCڐ3t5{9p`PHh3@@p@$|vF|P x!L q $ kB$PA 4n _>C]A 6GZ%^AXaad 8hy*V( PM&J? .(=A@! o\=րS`{!urgpP+PIhPӅR-786$d? m`#&J g%ʕ\%|hAt x/ɐ_ $@$ p2ʁ  0B^>}` @DO x,4A/EЀ 08!-18hhC((!K  x`x ʧ83)@ @~H4h Ѐ  Ph(V`@4((@D"rR~}@@T )R`@$    @@ p pkA8WBb#  x(;Q"qIΚZA-)]' @DX"IlVtAUE0HTL P PhÜ@ \AКrEl^g YKu\PH#AT)Ȑy4REMC0̂wח}aSRf* *yu¬I,NkkP-# C09µq!unE2;dΆU1Ѕ0}&>l?A1^0 !P ^.9Y+0A/yI2h`cI*b9t Qg=Tpy)z>=ðp S`u$A2ttm%`,h% Uj#B4P P T@R=1D:+ZkȘOnL=}|r]Sb>R ZrULvJ#H-`VֹBӗBX"lS noǨ-S&nG;+ WnM Nf34<$IYi4J '7%S#JĻ(c(Y =bI*J %#Q!()J!̐cR^50)~RW<@*2㾱0Dk9~Ң̟x4O {ax.(0SXQJRI7^†s ]Znѝ6D`%zpgC zP*\yș` ]* R?İ0С$kD]; cX~gUuhH60V8"(F/LV Q-_zy &-N*@& ( TC*+ FVk5H8%B٥46aaRzVz'(fFJ˭Xb: -]iK) fҬ @ӂiuJ(t2P&_DRp|an(2AHF -JP`2xFh-آ)CB,y. BoȮ64R89S"I +1BPuSO L XAC 2K-)uw %/9Lf|̺jAIdTAu1 x`2`J  hc+(wLy8,bcJ-& \9*ܠS @ KIPG Aʬ`iDW"TaP h1h,Ql8zAYT5OQ {C:-R-GK4" i5JԬfGp %BB0 $z"ބt8 /qIKHh &$A%(hJ4@zND}VL4X 4k@xJɎ@I*5A:@b &P`yl)8q\L !:Plr_V!G~A[UbRH@cLR( (A  BrQ(BX$BHzic }Mq@9v~Qr!W)s<)@}I)u A #C?pF46{"*N0`s`Y9"Z sFt*LP1QS?xfℨ鑁iJ]QJS!Cy_ hʒ6xΚِVN](*ր+,nfT25 N̕*mc ݒ .@a1 i'^ %!B)X,.=0'x&68 }55oDJ2\ SU SZ !`yZMo$KQ|(刁kpdHP= QFź[R#I1(3>YU.E(ԦX!'\JP )GfBővqGQx&l)PQ4ڔufG>z9}tUi"epa5o!^8J/Zl3EEIȵzE |D9&B.`]hw@~$>,Zk^KP!FX9ʀՎDQn}$l *+KV46@5H7@4E4@/@R z]h -hOx  EU ,I X+HQт>Bp)#Hr-=0!g&# y]xb$ W$ #"tB(%ԪJ: WEPUH*J-QKJBHH)D5Dq2*&P@`?:E? fX$@ ̍ P\*hĉ .zC!`U*/T!J@?P]O+Ny2i' ?-$#O+I la@AH9@J 3rzF(P9d=Β 0*5=":]!u #>l/ wbTzH@XQa N"TLI@3D0RXbuo(U!`l*^"@` Y|Wh[XW{ ,p`p<?t01O!Zp0t%AÃM (d0ʆb(ب1G0GQV$pD$< H Az!HA=H@m@DkњЀA:!M*&*&<4b %Hi!0()OEAޅt)-P$,?]V9@ ɬ"%Y+1`TYA jVc ý ~ Q WD!H݊0JX)F G_ZF\ l ?,h0<"e]EF,l$xc< &e0pGWz89 393JOl t r w!rgK&{OW@?@?A=ByrLXNš ؀@A jUG<0e .r ((0/y?ǒ4dA ($(@"8OA@rx7Ar t$耦)v( CxMF O) 4[0@"!T,0:@GH i$%p   TfgbYo4t#q,@[3 h0(W((p @60p$琹qs !4_@0.#P) jKB aAe=$P0,ŵ"D0Ʌ(0M) Z :ȡ`,Ga醡! p$6krD@]. a?#C4$F ]e0"t`,_?8ħNN"  Q,M@_qzG-)ąT2O#%X!ن(\ey87 ^PJWM1ඎ$ t %T QT%@Р6 (  .m+HT:? &:+?W?1( 'Mp;\Zaw =nQGQͳZd(XAr0>meOpA;U8~k  )BrxGK6~lxHJ(E11@tEDIpZ9T!%I_!%P ȘQڣԡ 2 #5Wf1eD xS0`@6w_`ҕ@xV(^mHH0EM-ApuX=#SLX~сZ( /6TĴ^/u H$ Et'-,K0Mf(L%Yƕp6@8Adx/DP ڐ\B#M`sp ,_tBIm BӨmodpoQYaQ/&hJx4 2LWlHa;7(2NiAxB0 1hxABPbѵxꌥ+@fUG 8pZ 1 I`0!! AU 4N.L瀔w^V[t@Y z$ dBMBEԲsw;'}{XrnmGEahG r} !" uQEǴ-&n4O*_b-UcH(דGsBS4f0#R,ՌIʈO)EZ=X2 HAH "A :Ta\zMP GEB;@h 4iWpeoz Q5tpBȏ ĄRд%Ҡ-kF%7`xJ (c UhEHD;s`S:̅2"ؼMGs<0( %ɿZfm5(H0NU[ p6qMꀹX=##dz* ` #1D!@3F@P'Ad^~/B  K ZQBEP A@Дz_d"9t1htBN(@@ۃ PUhrR/E -5ߨ R>A(H7lBW6H߁-C< O~2> JCW0x8ܵ^zC.s3XAfh0 ?I@F)`v(ZLS>@ "\_TO& ?xI*|*_* wdXE^f˱`MT}@D5bToCAК2V"Ǵ*JI@6=p BJ&0\"ha DD Ea:Xy@.\b4P hCtx`#xFb(S pSl $cPQ1XqDRo 'sJ` y<|`,X<')e"oGJ9Ƈ P>FM (@( g@PPr-G.W]@z EQ@&U+@m db!-4"+o#DI8 %ePf_!Bl0 QO?Z? :!r9gArdO@PHP H.+% )$"" LpNp&E!@b@ b(yoBO\Ipb5!A(!k!eT4N (m aj" tpΙچ4 7@(; !T >#C%G"p0+p݊jpb"Ms"T%J cW:8YDŔO V%`H $ **a&S]BYOy+OP[OG`*> A1OSjHX O 1'7BcbM!~t1PdT ` D+d!TB$6<#}lr^Db/`eJGBp7RzP%/ 4`0Fh"8?44y$ xa`>2Wr';~V W!\r +.5vJ$,Ǘ͘8U!p!еpѡܡH-V,1k %@/,  (4EbN`PxS'W+H$LFwmhB^D?H#0ra"9l["Q]6}NmEW FD!,9do!$h&CBX ~(<J8lQDŽ$xi ?@2GhGڡrBB^(0`݀K@%#Q*?>PP0>#H _ BPB?'JP?=A[e@@Ɍ1]jA]آ%XIÉ $1__ J 4{Çaa@F@rsYz/"𨭃͡j3S A[a7'&Q0K?(G˗/XL":KЈntGj'dF9JI<W:^tOR(@Y5ha GhC^h- @¢,6 Y  ХAhg8D1{VS_L`RIIC4&P&ȠQrP@Vo}Hbt1+!,g 4j#QYd1} p,; _`7РʇD (ԟH@P_K #)%! kzif~[ACQFX)QF+A4*]}Dvq Hq$Hao@`8Y5h >oFhu$0X=$UCR! tpUQ{(Py8@\ U?}i  ԛt(b1#/ ϪtȠ=Rj(v`@2 Y` uX@N<@2E14@x:2^ZЍ V#E+F" zqq% CF.F.&*gD0]bX?( (IL ,$a1Z8"чP1"ZAQ,ߔHao Y]#ʜ(, O%AzCtڅ Kȓpr"Qq8e B4(Z1hj%F`%i(Kk3Q?Վ! xDʝca(x)%uBe A੹l%9QD o!ܸ |b 2\|l7 @ A UH!JRa ȆɆ1!n4SnʐJAEZh?0ae 4w0 ',>fZ#-Q@  @io@!yu3E)_Gӱ@pʎgd?Cg o!۲ab!O䁀DB   Pa1P! dh/A 0<tBROH+GY(PU5@GF^nnn_B\ J8Q]Rb+#q BdQпN??@OM #!~Hdn /DtE  Aky X.JLR hPH2 8pTP$BCah.P裃1ZaG-I@kO{ f)@G0@%5|HJ@Y."#H0q(brȍ !! Ѩ$"Qac$i*!@3u$POףeRBTGk:=lc\!dAʗj5w@ b4D:)U 6*ҟJke,H^A Q*qԏkMdBfuaJ42\s>A~5&/˖'1zR %HhD~6x),=c!=-߷$i}Wr >BJdcQ@Dk"n!!}iBW@M E22)JP`eL@訡)5!_pݏA,]9%Dε9gX1&ʘ:fRB;,)  !R!I@PQTV  tVy1W u$myxm$4础Ej(S@F,j\Yh +C!XNȮVr%kN? o8:B2bﮥKMdJ1F+Rtus"0@@AEj PbBF*J#Ɖ/NZ~|9w( "%BPG (ZƀE. dRpA^@ y4P^R%<)JP`l&} $(+:A o$"հAH,q/0FTP< u4b e)(s5ĸGƙ#HNͧ<1{'̩zpoEWa P+ .',wV`Asi5P&d"\J˼|eE£&s?!&XcP3` ݩ)!'H!(j4V |lG) ;ĖJF/(M=[)F GLTb}icEcC0 "K RbP>V4yDN0SWFK%b1i0p9tv AB9@*Q?(U8r!x"F@AHݒ &XON4ij4@gF"(Vanj)0̸c@aJ+ ec  AN(3/2)`Uˮ_i,'ȭ*遛0\)`1Yr;)4z};C )!$!S]\s}) w}@H|sْ8YXB!_XCOv t0B4HЪv  `&>xw! |hfp\4bH$"R,++ŶxO^x[ɨ\hj~Pa†Q?#.C\-#?4Hb )?lם8I{aToHFNrZ >8jk r4}:~ue=&>dcfJ{@Jg1-@]M@Mjh .4)@M X5ZіR.B L.&!@Le9 E}/CpCcHAE OiqBQ2y*?HI8*%1,$H  JQZK1͏g X3Fl<\sF E BUN;FGX "@00i"60q(^,>H6ؓXЌWL:[3נT 0i!dI $4CI%RbBD4>yU:L $  @d٘ P` ʲ H-*BAHtIIREP @@ @C3R Aq@%TȀBl@#$ThQ0U(!` ~8 8hnAh4Ka@!soN $ʻL0,nD$hbRD8nK` Ɵ T„ r p8ZQyٙPn@$!KQQ΄P 3Ğ@UTcz"A4HjȲkx @UPˈMwJam.PvW99@d(%{+P@9 r'$(Ġ#DR)81 u) BTHPk&[3j@L mEQI*F0 _0DR*&i'@3g1p QTCD@nAT2&4ZB(B Ɇ@ȳMX"2 ) ,cb{sIVI Ae>|X T!tO@l$`ť PhT H`|/FȣNFOóvv;;;;;;;;;;vvS:uO ~=@A A PH" Wy"@$I0x#(%(}P0V ht['zwl(4@NECJ8w"f~4b(0 /?}f~C@tANY Pj0!@t&ܠ ?]=PPQ@$5:@%BUYs1( EPw]@ꀈ<P.I*T) Td(BN tδfħ'S"(q!d@0~@<!@0E ' )K'a0H$L ؀ '!b} >`x0Q1+Z?|+2MHJ wZT 5@u $G - h! e&%Eh8QJ8Xi AW^a.YCZ:-%R Jx9w!WTА0FU, jb3!@,?ؚülM:Fg)0A:_FPS oHR1Ixu|*HC$K#`%S S ‚0kӱ#LQB'NA,`bUq>Zu䀞#)!X4Aж(=J h (hw~%DJV0|$^}  @="0CH b % D3E Ғ3X9 ?.WBXO[JYb!_zu Yqr@A|Fa_TRBWW'nC60mQ>U\C>1G7hiTk+ "Z)ptS 08b paq zĮ橘Љ~@cgs':'e콗2\q&$k$ ""iNJdswM E}4GJH"V%מEF-YںFF Qs5K15 ,UXPdti f>o2He68Y.5Т f8&*ۍ@h44Qoj5FQ̀?@HX" 8-l$k&IN]$EE^\X8BW!EOGͯ Xc&0{П.IJFDZhl D6#Kgu*pg"hNmEum#@0$r WzUf렆VG` =@$٦tUU- AwCuJ(Hi!S- (Z*h)Q j RVI|4(%Jo2SNt%U@ (.]D`UO'E䜓bLI1%ϒbLILc Q|20`1:%!dQՉ1R%?n1+x<.IQ w:LƔUx׉E|)Jro, BJR,`!Al@Pp[ dbA iV(Ђs(BD'm' &Ij3`C@P !Be]?)Cŋ R @E&C Q LЖ^! `2 |jdjM&81ɀu#TWP P@$acjzɋU ,Dɍb@B1e:FTyť* i @D/I`Ig^VJ!H 7G  `ԅi ~:#Hĵ (& ?>JhC?-,^G?Ner?DDHOһEfVm[p9c@(PI#PBFG̒VE"|\xL -A-̀?mخͧo?yCy @bbG!)Ԁp.Ftֹ#?( d|+_dv.m2$)^ M )w+ s?ZSHANhih=]PG&E!74s/1"A<@M / LUP?Ŝo(Di^IN j2nlPFL4`EBAV*1PQ)Z.i$di .sD?.z@YV P FԕKbgiw :`TҖULΆA=\ F0 $!V$[?WW2;1ii">fX\!"'Jp;X2 b*20("%'͒ ]AP( J$h%v.-(@4@`T) !0@RAiQIE1ꠢU}8䘓"f\˙s.D̹"ǀpA!B J j$Nv(b PW!R*Paj(%5Aί/p8>+O@^` ĭO, ~BO!GzX< dXh^ b! `U͋99`~i!܆O3dZ2#̞ Qɂ!I chGBUv]dF1EQ:p9Nt& nZPKB\iB:P$(EtPfABdRipj5Qj4 |@DH(6Eİ$a֠/@Q-RĠ$ɈKR@xR !$cR1KMv (LgL) C;=3 up9P=P9f24T P< P Fn`PF(A~^7 P ijkCDQ:`G%1"[oۧOn=ZyV0P `!@B#Q)$T_Pq~7oRx@SwU-7i=b`~8 xINpH(}Z@_BX ea!Z‡5ea)ap4EpP P-ZOhK??$H+)PC YQhQC07NNGASp,\ $2Pd 288`0<&'c?` 0$7TL@Zv$ʢ364bX Dh~S,ިQA:Cj9K%(Iv ]> C - A'􁢭CZ G a 3P_{:׀{-7GSaC(ĖdqSnꇒQ >: Rf6 zp@8,t;=|>ᲃ&C H\S`a Ŋ@A4nZOl°&ɻz<2$V)C'ʏ@>.X9#0%"GK>֡7Q_Q[PDLBCEQT~MO" Q$ [" tA\,n2ZoY`C( PLQD P|*e0dFAq10`IB ZW1@N@TëG q<~ ;Ljp*OD  Dz$#aɹIPn4qJÒ6lF1DJ $<@!$W(CtQӦ}N;YNvv݇m;q / (~!L e!@Dٖ>RDO`1B0FI $IM}TS%&"uȇ o)_4Y Qh j?K"H*=9&0B0D2Mk^Y M>`App0B D Jip XATuF8)&u+;,VBbT*A /ɧ'u=#ǜD OڨQDŽ""|ET?'W |P($,WT41}9Gc6}'t^I9&$ė= PEs' J4AE EXdZpP-]5+A‚"zS_~tU_P_yWGf8[$?ېFNUVpؒ)'ψ@ G!PB*M= Xt"̨FIB"I/O/r: ,<#0F"@@HDKHpTXA!qu@a0 Cp= xL$@ 1x`} LϤ$+eZ:0̠V((cRR_xP)Ad e?D@2 F7&F"R H+T6)RT_l0[PNh . h!l RhKD>=;H6 4H @(MRk@5@5R!x^_YnSۧOn={t 3'8E`a$m;" x^N'" "Ax|fYl'Gwާz@@v,B1 ?y@j aA .8a(С3HaAEOj|pƦ/lbUzC#,6nJ h!&] k`&Q < I}d"͸J(A@ Vj p r!\%Ϡ U1c@LP#1M B@ F(sųZD91Hc6 "cQ *}A]`Gr.y<WԆu)邟G|!Hz"nlF7(@d/62b1pQAm@-PE+yK:`B_0L$ A@$ 0 TЦ qUUx44 yyb ~adByy0 `b\-=Z_0@ arQ?XJ7= pbp>dFhdJ@-{_D?4 1,hH/@`FA~4ѿ ͌Yl`Ў 0 (XGl4h}c`/y~B|.B/!`rC\m{=g ACRDG(Q]N p$(E'^=eΖ>XLC (d TA 1EPPJ  ,i9N@J5D[e bZdIUą - $jW@@ CHXգB4ϨlS\LpçOA4#jR',q +QwXLG^F 8GbJxa*Ta,C$CXAb!(ȎgȆ>]&0ġF(J4yh2q@@ A Q< 2h:A4_?\|HG7oT;x =tD AP#Bx#,*1?>D$\@?(Eʡjq~ii ;R5[E%ɓ^ht9p%v9j 0&$")l CM^K<ւf(K a#}`Q KG# &q?q MRU@)}feFU<㙃z=/N@H&2CXB LZn}0+d Nе-X`y'kn`i iNmو˘d5<(0X 0BnqPDMm<Ԁ:ҙwg-eA'h|53zY GYOf Z[h‰$D"/GP Ӂݭ%u×ŋ8 T_ΒE yv\} (A@൤7Q_&%aCD&,* ϔ{G / ق:It{ <1Ų?003U;䐏WȀ/1(ruT,0,HE@EBIDЪ!e;;F|ȥx-5$C}EābU@M`S/fAǩУ4PdR ٫*rd1R\xlaGU 7`2 * n9\ҽh('vC]8 C4|<(=5,,!я8ۃǫO:ҧ&:|nNdVUկuץD&ߋxCʕ hA4t0.ҫZ&3Z(dHVhvI J9 @0jPJZ0Pq. QAWG-ZPWֹ X C(GSJj,R":BqBjG(<:dT %%u#)CteKA]V-@MCw9($6h"(AVX>jҙ!/׻mg4`gJYa}kNgz^Dy8Vh K؄9y_kol$p_?q 2G$` @8F!'Np2<` S| _YZ, ONFt@I^m>@yKr5N!ˤHAtĜesI1X[~c \8C{H@JrfB%*Wo"is&@P i ]j EZR&vOCa)Ĭ^Q[J$+! BcJA T_l43O>8\\f/A%8 @>BrvxP q[0>b&P}?9,/]PLFs@[c֫F?|,a#m12q*H5 @@@gN:`>CO t0΀ v/7@] OZ +T0*VR?KL[ T> CXӘ/pz4q$4F$ Q_";H= [y$̎[}xͧ N=`3h ,x N W38ʜ d `D(H~ Ӱ ߰8Ѡ,5iYYL@R#ZEj@ ͭ0>B@zdS Q(? !*{ +\J@8g<$U*JjН 4 bCT @:l *0.5kG I)K IڔM|"|[fWZij]dd rk/` a(wb S( $__ v3 #;wlݳ}zxZtXh F5L%?'&ߏbf 1+ 4|$`Qq>Kʽ`@Dyw<@9TPVܶ@v@u DS[P  b0 4B%9 d }[[_0 8 <jAGAHև`3_`^]Ÿ0` A0)@(c33 +d!gqZ ު`˟/`~haG EG3#oݑ-Gp©FX*Q>:Nc` 7_ !E/@%)^9J,h~&Z9}T1ÑqTPȪl>"Ap`Th D%E)vV@7dH #DCpHz! C$Q@ QBB(Hj.wf>IMRYڨ@B A/EB"FF ABɈSVw/@@ LW|zm m6Ͷw;wlݳG`΀At.iwNr`"+JB7E 9$HS@_`9»cCp0|@(  )J1cAB)P]]*R-@?_WTAGQ"I䕝 (@=\| @P((8.tiIDyA09/zDt,BfATX. 2`T!K6cl6;;wd9eq% $8 Y@a ‰H Q#%Ʊ )#% &JN:tNmBk ^` FT/!Q"B/7@ RDRC(( 0  ̆DkJ~p܌@~G$ PPE*9\X(N;08N K ۂw B Rώ 19lZ2TAR K4pJ?ILZeH1|'(P )0EizX vV%PhM,d yydH6`bn\@\L@  Tg(Nƈ ?? ),QP@`ffw@lY`cL !($v ѯ>ˀ,Wf Hx-PfIc`aɍ.*@ So+-Z@>QA B 0@SWhJ9hn]c0@:1re`Q%tyu-g r w*0,Ei4#I#3 +1%ϫۡ2m |q׈窸1]y\x>3@24`&dJ00AĒ*4m d '<X+ǔHr򢯎~麀sc o;*~rc,JOV@1%(zZd #9rFv}jmMlZb"Ûbl2ts `T _@B?7;, @[((%z;:>?)&^ٱ[HrݦޫsBw?cAsVl@ЉKqN~AP&H- K,Cy BD[*OP 4gӴMKjSaUV4XSd7 OA;38ydi Axڅ.4t 6\>hΧc#,s0٤fMg4JJ-@BIr`["N是|@ъ3cH'@4M%J@T+ME(Bh$UÀX= TA F5h:@(JCh 29C(-QB9 T3 +,bsE5"@Ev&J@u}+ZZ;j9VM8QA@`C8< ']Mw䓣g. `I4"Šӱ~A"tV#\#g:ޭoUHKkr@S3QD Zdba)_A"թ+_(l|>"R4<(+j@ |"L ̀5gx3SlF )$DHsX Ύ%b@ jF )dPzEBԤyL Qި@, <"@uŹ5 R'%L$(Aq(y&(Í JjOE 7$؛g`pƣ#S%KU,tkB)Bj R_,|TT;h23dLnnd$=\E g$Z RTHxODRRQ#F @Q- !5bBCni9"4B[SqaB(>YANЇ-jrG , R_DT%T_|;ڇa}mh0XdAl^D'V.*jm]k톘%"\ $Dj}mu4(s-W(!NI(@_ausF.D+4@"Pi A$Q!`R,8YhKzvRh|+iG:b1ZVIL 7- S!ŴtiI\N}$j)Q4 @P!!AH$SX@!UR:|HVbꤊJ`@C8}SOu]dxpsci* I0ʢ apHex JUSb> R4Vh"#@% PGhij6EI 6*d3D H09gձs 5G(bQӪm񣅑J(wʐa#* $:nx^n m @lH̞R1آMʻ9JʩNZ/p Ⱥ$F Z RaZG,!9U(Bp UH2U6b!E+2.wVHHK!Խ "`cOx #f@!I("\$\A ҴP>=P -P#|$C?"ڿr %CS:5{)"jaE'gA(JHTh=Ia \VN"SZ[/!P@(@ Ddn,7I$Y.i- +rdBe@O"R)ƾXǍhuS5əPt7y :3 vڗyCؐ|C]n"ʠ)(=@I(q ')`$J‹+$5 ' t`4 (Qԉ]'ħ]4V`9R"#*ZE2o |Al *y? yvF@(OC $ # ްy΀H 4Ėt=>$ýBlP44A=B A?,zm% 1!K~^?,۴Ʈ<g !Ä!K̅C+`J?@TPf8}i7OPS?(!8 )}# @ /\f ǺD$jw &m =0 d2 (z⅔ @"3F y:!2%)@(Q( " 0I  *\>L B-$)@":}GF t ";4P'#b@gqL,=kjy!6XAIcf8.0Bpf}n ` C퀈ǺAv4)g}j2[ѳ) 9K?V`s9aH8؞ ]gŚtWG CAHl,0(1薒(FR7M/+Z/=&%5lFZ5+$\vL@˭µXi_?#UAd@xxM?(Ap>`5@fr{SÂ˞$^Dp zxR||䌋OZ$($0X8 ;^OR Ƙ ET? M_JT !HQRNHhDZPVEN?Z{:GzqPH9,I&Dc 2@ ;Zz{R_b!XDH\_帏vu,o@d 6ހr31a!TOabC$#d送!>(xjz|0:"tX҃)*0 G"i`HGDIN cK`$x1|jb+e)Bp_B>EAAR4Tq(AZH"qJ 4@)g (} (Pk(?U ce P%hQrSAL. @0AI 8 ^Z!xncߟ  ;on 4'^<B@x,*0 s!PZwԕAY-lV@Q3=T4> O ˅aIY 0QC Cp YT pUipPkKlXWi۸p>Q"5\blŒyQ0B j^2HT,A`{7ZԠ|x/)] P/ YTyu-6a$C rD$= ` !(\πA{@*(C@+JH, X+J-h(z4P}A |9I!*$xЕ'E47aN9UA)`e{ɁÙB#w1, TCbrAOP}""4_0ut%,&c@s "8hCttX $z^!MH<@:Xč06R"N(GM$@QAOM:MBw<@mAd(rH|Y!@ z"tC)Cל!ey bbIU%*10 (\ T#?- 3PǗ  <@9^BO<EmD?p`Dsb ; !yZNL  *a eFzQb1@? PX&tfР2+ F 9==p7B vJcU Pm A0&Ry0?h2$ w ># ]:GiyB*~vqO!B? {͏x#( ج fU +aOth4-gIFL?.`G W 0U PBi@Q?K"cՐ'n"Ys<"sF+|\+Wwv2?j@+IyP$5g *@#;"2Ec€#K@Wc##^K}⠎~ J'Zx s@%@ z< (^6p zBH.(Pt P@s(dɤLCH΄-Z@Q`J|#BqHMB}9w(P]N^Ǣ( XC"F'Q!PAgy-UFٹB0 nJ#K)|LԘ,_@5RuƘ+1ql\JA6g=m؉T1",Hb@Bt~NPA/!"HLL@$D8D6A T@=@h +$5Hj+A -DǓGHjj5@Q'p9G\Hb A8hZ7B MW~$SQ}p@R)!mE߷+< ˀ"E#G1 tW9 0s#@%FaKH8 qDh-"ar$(nzHPZ`_K.FD H3rdBzrl@LVdwL<H&A &"aFdQrI>Uо~`գ e ZR0PLyƒ) 3@ zDO$B$I$៝A?E#@PJ6MO!ܚmJ .  KLc ~FG b\IJ Ze?K[j1x @ \*dcv`?@h€¨ᰆss0ŀ@Q iG~1Q(h) cqcGԎ$b!~(A5Lm8@i !)ñr  t?@./@t\`Jev/!sho ­B$%ЦP*ų_`,PVӾ[)aZH4X@Z `q 7HGxPm q_61l яhF(la}ckhl7K4>EW 5!x8z4mbxM 5E+! F'#Cj!!!!0PQ  (aa/7߄aKxSc)3a~SȌS̸@ b{X#}~O@i3z@V)FR֘i!tM=:Q G1tCH``4`%O:-v Hk3O*?$@B~H44 sP)D~C"P(c`ؠ2#,0F\%(fvx݉0km*"Q?ϓim0s>U:H/\LA 2 7~f7 8L@ߐ !<^B #t  +;XQy"NXZ(4Y;<P$p<ѪVj6!1oq@" 0Rb/ |b/6} O" % p 2ȏ}BSx*(0ZS9@`B-,+e\@;zp&nZЎB0# NXjAB¨-CCRzѭ ,y Y1R TD r hHP +6)O^IUy܍@(Q,ς(*00Z h4P7(8`$.&AHL Y3ЋGa~C J& m?)˄!T"1yk"k:q)#BҤ0`p+F`BX1=&!Hej  0xyL1E*IH&2I̒DTQ0?%QPJáb= EG]>> > N+P } {ާU" IQ5"+|P7X)k$h̅CAxXK„Pq'd<ՌR|{wSܨ4tpC:TT Dտ7ʺ WS\ 3p@hoтfT ;XzaDF;Vl`0e W Ѕƞ%IY^dYhSh4T"J*XU*B(.M$(hY HXM!#AFC(hƌ~p*n(Ez.Ұ0A׮A[" %<MHH~1}`h:z8 !z$LJWR@Mn G.zZ\J@ Z=PGZIK@ HA4ABbLF_o>MS% lrwUA%1B ?r~ 1Cp^Sɉ&z2H@Aϲ}o EwNp5+QQA#XIQ-/ Hvˆ@HAp&"yihLր%7ʀT?F 44Q[ LD5tBX`S-Ԫ(HBP5>H=+0 @UD?C q+PADFF>9b |(@xXTiT~ЌL:5/:dޱ rDFN0Ę04 FRO .rK"̑"Im߆ժcTbB*$JV~M uY 'VD*2T,&CXbN 26y\"Z (S2g YwU4x,(- CE"xnEE62gA&KJ228kPa&@VR`T ӇK(,UO ԋ:8>RVf S~4*/D 41(M2_MAL3?#G8c@-iJ+-_r8Cɴ % t &4ǖ!y wU\K|%$B/#ȡp($haQ!YKrrBQ U_4 @`E eg@ d %R0X4v$$CPN=xX yc)EGhPH$2TJ$I4@ )T9"r(q  :AH4@He8 PRR@3S) Q(#E! PG, ("C x; Pϑ,@@mBzpGw@ػqK7.1,1бh "9V@0)"/`@Oe  p~jQ2CGˆhq@5(TqZ/4 J0փl?FH!C 8v3*. Zuߤ6A~RzPE_*}$;1HB7:xlgƀ 6@ci(ųĉ \ &H&2^:^8rI )pUp?/\ 'Iih0󁯨wtjPCCQ2%!!?efbR`*Ԛ""j_bʄ2 ZaS?4+L 0 c#YJ 4&A6)vQ8g'eYvF|-H8CǺ~0@t9GEJDiǠ&78F}Ҡ G `Bl#BހQGi#D#Nq J#bgjqJP 6^CB* mX;2@5@d4b$Sހӿ̉ o`Q:aQq A91$[3["َH ŤQV?0`I h8 J%~Y(&$&7}hCZUP*?h7‘ƺ! Cx$#t"y.AEX:&n$8V1#5`F⹡@m9A7+@A) ̀<id">69S`&2օƦt&PE,B)(RB^4P^TUnO5ͱ"cɳ&ҐAS:J:FnNP† Xd@ (OIY WP_QMAjTBv UJU#=p98=ގ‰ `n!hܛB] _`;cgPWQG$0@@@E*ǔe)"4RyybŋThti@]%)d#*@((80$PH )IU]\A$*Nky,@=d"N W_?S X :D HO[Ǜ>0 qp\hLbCŃhI2*y ܰ,A`$ #@Ag] *<I-x0DrK!<""+.@p!;NdT @h,JΩKyYS@8V2R?P8IPCV5fPCU]Q[|+?lN?iȧ4'8` S?݄`cvNLQ 0q EgNF\JJ G0v#IE;QLJ( pWq; #| hxBTFD 5aO˜;(bPDBMb %r* ir_s: aK.VN")Pj14B$*HQЛPJU@6J"A l[()@(*::P$@_WBQ/vłn]h;G GFV P&x̙\1?)i  HI1GQ!]JPZ@5/ABl ^OBL/!.s^p,Fj=! {9(@!"ňJ)BnRR`2KCYVP{Eh#-cڢX(9b0>-A ?N!`o~ v偯R1QBKAV%WbTR1bxQ' X#!{,DDT1#šL @]EVo!U7&\~%&r6< )1v JC JZ#w䬠 !ι!+a/y^svohB5ED]9~%Q*2̕Qk30U/P$ V b_}VR`D? W%:,aETrZ" S Ta VJ 1E$BE"  1c@0DQQ(Q&AgY@ehb JgӘBOJ0R֤BQaD (1$a84V  :$H1"A`z,GP(}BxnIb7ؕ *X1S-8Ua7 sr+QJئLh냸ҁ6"5 pE֔$ Z(Êr-C=JDcD-!]0!ij^,+s]AcjGBD&ƏP/E}** b$dr9? ~c U V#%⨧ (q#G HYL-yz_OY,#:b{MP傺ȌF@| 0KH vFԆ0#uPRVhduGQ )UC]C{4BA"ʌ4(bX>L)"]9I‡*v<HeATbTx $QJ1Ϝ+˦F+X⥋^|ʀQ|pv=*eXqk ¢^0I/ԬH8 @"4q@щ'FJo|2"JJdJ[oKH^ыnW( "."iE;_($]-RrP@eT5 24C#P Mg@]HdW ԖS\U,y+h-d~0 @5U[PA h #CQ4H@DOi`B娇{$D$-*< .Vؘ|J ?m]f>:Eo/uD+u%po1zR(qt^C,`1 SHp&~l SJ*12hIr_N?CmQ@(­#eUۺ0̞S`9נ TWV4s]8LۣKpNXXw1$ s_lq(ӮɈ#N`gN+r88‚I4ߜJq!WDR;ƔaH@W|a[TbGOš`o(,Bkp,3zeaQl H~cx$3 oUɤa ~I9g*Q w}a8`}'^*Hf@ }>P< a6"&D5. Y ňAՊ!8IUAX4="bS~Y~; FD($U#̆(AJb UJ(pM`UH'EKPAzXc ,[?s 9 STj)"b֍\0iRтC 9H,e(@2 zLퟞpL`TlE=i6*%a0d aX00*˃Cf dO#%Xpc 6M**V}_MiirAQQu01(`sCqD$r0 !Z-AL`hh@F2+R8zxu_^$C|?$ 5I2˔K#!iK2g$ CQp&B @\PTWb'ʈ (- $Gz! =` 2pc?L[z ȑ~ 0x##ɐ|x9p6@,WXt藈 To :=? H$= N PqL@K\VEh$1eF "5(A "8;HIa0(״X]vp"Az=@he/d_Cl\R8e -paO(CR ̘ s'px : W$|?S/a  ^Â)!@+0h0ʰSkEBjB? }~y|*! V" E" EBkBEr(gN!SSyKG4Fn%8d_Pj ̈ yPEr4K3hKwMI?Ѹ5'p7 [9sP]9˷ |Ȱ`W[>Q@B*@+>c ju,6x `,@2k$iOHz )U )6G0õ'Vm#|? 7/-ST.Ly! &Y!f>!,9ڕ?Šƛ(ߍ0TH5A4ap G1,w_8yh'nE,`TuIQ|0d0|Pgǀ' 1R)E HH UP &> " yNF `!$RHE*|n!!!!!Ogm!Z \UA & Gʨ$ht"J+9m>X k 1[LSO@( +P"u&$FJ[`@YL,m#  Y`1r9YpwLZ>sAk3C,2`$i  @ t)H5">VN^BDAAA1 z AH P tqf/G:tT=/~n A]rY VI !Ei D.˿B ߏ5@$S7av@I1.z9/T\p, r'qsT))MDq j"~H0{$629wf$l @+`3 ,|XK,!G1G`1siCCP.TChCJ} 45uqꖐ3Y-$ X a+y AHd $|zzgaJ Fʪ]BA'd< Hjd9A fHB"` A ɥw(@XSǢϒ+FD Dt]H$B>X( 'XO@ PD@> =C1,>g ^\ @4F%<ҘԬDFbB餰P"0P!pShJr!RƸu]X0! q @ťN?hqR? ,bK<$P `X@aL` "HZh~ŵ8x8aL | D8 \ F/  "D3Fxe$UꨔhNd (: 9it(@v@*GQR_AIeN,ד J"fx$:!R@g K|0CAA_ P` FupBWA R U0H|GHQ% +'Sۄ=G&@?6K;o&ri@ص1_xQ@\Ɵ(7SX#0l} B 0!H,8ARޟBdHYpZa‚(\ػ0 @w(?$ /f6Ux @' C< D8B\5 W,x( z&'  R@0R SQLL3l2LOz CAĥ (dR?4s֡I] EhA„3"w;ŠdqR,b0WJZ(o =i#6exFXB k4 +'D1(n~'5D$X5pGtH& [ Fb@" 918B#P/?O!styW#xcP!gUf{-0ä"$G(DLDt.Z@¯_gȋQJ#HVy D&ށ8i2bάgM' 4zBz]M& $hpe~&GALiD)xR6@} 8 H1r \$IvQm;*zC 9 0TB( @$ dc FC!XEz^:ـNG-kgL23C*M 쎏o7Ԑ\h ׿ YVu!\@`X !O;dIAYCC@U'܋ (Ae4RB42*@1PP84!ļ.Q1Vz82$R  ~%TE! -U@HZFӗu3ZBA6XM,CKR/Bh4AM_0aZBz ƨά9(:MQLVs%hЖFX}芇 t!)dCMyt A *|X7cU?*VU@nV^j(h;taU?‡ٰ! F]0^V8 6!bݤE? )H<(NfH` plB=!"?"" ܀/ILh8v JH05 - ly(BĠ` e(@`*$W`)v mMZ% ŒGSG b@.OhMO f] -*썢 $jl sGh ނ\w=]@4@`|C/ G)AL? >_X3h4C: h %L0( Q713vupTUD3j؂!kb "ǐ(k7S *[XA'5K<289;3)Wα MF.<!KZ*ҳsX $V$*Q*ViD3(2CDrh $BKA5 }<_)^ b+CЁuU!ږFj yc1%n=$U%D;ZD4!4D(eOa@bFEȔ`l& mg^!TUE#3P-~сtAypAJUNuG\? * Z2Qw0S[BPq20l\cZ%b$(B AB%"le GP9 GZd/(J!Iq*KT!^yu9+O5SS.|*;_@шU R&TA 1Zc$!ǜb0 [$Q+W $A(9JB (.*!J8 1DL8,y 4 6Q!2ȎDK􍆔(BBgI q%(X"3M!#Q `Fp@l(4+ B@h`)ԃHE HxA tl%䌡ePDc)JЌ҈H4UAlv0TVrkG[!|I@Yܤ傴iQv=.#TaDDvjMjR1@K* d!J` X(VJo!60%QL*;3d\i'dNM-UBP&*# &TFP_CaC W CU"()?6=1=\ʱFQI2lӝ&Zcϋ;Pч$HsUT~4 !(Py +4Y-?BET, yiP骴FPa3Z%(B}꾑XaJڕkl2V It~^|9$Q!O`H>3@P"AG0(A*j٦ b6A#L5 AՀdT)GTG8j!&aF@2xX@ʤ :B JT)A`ht|T $b@"X,,$|8 **,%HB S( Sa>O _* h%l*??bO1$ : #/t 5_~B C`f/FH-D#2HEX}o?lS0? (jд$b [A# FT^D_@Q:5$CB©J8]𩀬M$MAE xQÒ2G>O< ,d4 $nV;bd4G8',GNJހ@Ë ^@Oo;179v#\)$$ mGa40WPp0Qwq_ Q.\y* %VX`l> \0`#ДN^i|r_,9V?'i@21eTicF#E(wQ Ezғs33 "!UuR#?@@`~@^#l CUAR *=$M(Aj/#Gt%90@D2(JT 8cTZ4 B=˦Ut;Y!x\QW.CVnTkSc Z N@f$؀ 8,H8TPtRcX(! ŐñRdαQ<)/.W)r $/U;B"nDU (2 ,G#%R!! @+:~@0N!G51pQŒ(A" U]c`1O98}@ `yHZ5JAn8 B(V#$2 !vQ @DXDdz@DJ{)S%c)@rp)<+ʵoג Tu tVL:WtT j-1x  "b;0R0Q b(`Ӕ"z  {CEXI),R?|ULBaBF+LxgG"P`8i-(K|ٔUH_o36(}6FX D> ":Rz 'jh@iHǤPR]OEt sy$6bXb *C&5 $2Ux&tQRRrnAhRY!$p\A%AtXqv`c-5(zd,:O J hH?@* &#Aĩ-4q:!c4bJCRrzWtHV!"ԩ!{*($fA̕.RV:@ %A@QJ! dX;01 S|Xpv/З[k/.c`8qINGS,dZ2^yDɧ^j9clr@( $BD`i+B% pr @t4 o4S%beykx_q e. CG\0 D@8Pm z $  p&/[)1(H @QX/GHKD: C.-TRD! &D2(9Qa4#$4R`lLBM]$"B/ׯh!ICR.lĵ8^Uz9pqɔM Q"2,ZHʢg-ZlF^ ::nNYWI7}o`X!iZtP8.t! EP<@٠DAC(T UIH?A-Zb4<ʡCa&)vH˽nPM=Cnl-r9v0><ApD@E 0$@DRVegh X CNXDxn)f#"R .\$*axD 89ژ o>*UhYv$ 3Ì`]U0$ GNi*,R⃐W)JXPV H} :ꪔקŦ!]&h!:bB#STo7‰ n bk˚HT$3D T pQbTe GHţDL`D "!DaűL Kh`) @M4IQR HE,$PzH $q@ R 2(fáT (FhN Zu箜!r/ 6z<]hzRs ,̆DFOX`lg`2o(HC QkXkH6PdT@LB^ LGU%3K+N ^lS0U0]h(=q6@h!PѤ,(QTB$Ic@E -(@46ȝ .@ @68">a! @tX"gԛH bEA*P2IEADL+83$i @s24P8!XFfu_O]zu:zJrjP4V<<ބt_.$OG 5WX*4\WTU`h1Zf”5jCٴ3CHRyj܇u P/iDf˭qͫz Pw1eM%R/%vKfUt"r|Q h&p!s@!@4C0F!LL١爃l̼hlB!# ☂ D|'A>@o  B!X/j@5%FJ"S;%"4gdb`z)A`{),xEg`MBдV.@BhUQ,Hi@4q#5en@B/  @A?>hx-D단ҏ'FUA!K0r$'RT#aWW؇d D!I@oHt̂G!pK8A-b"MDGzEʿ04Sz&(L=@JVq R%^bH'hSV h (T2$@6 !Dh\*Q %aR4R0B\@JfEV!"qhĂqNх ui/@EŊ$4ՏTh{ge,dH.Gx#1R)R,G5 Iy+E5s(kb9։stw=l%K5 ի[@G6l:(h qA@FJBzQ1"pHLrCFLD:r% aHkLe$W>`6SBxGxY_R\& `)`@'QKMcAZF[y&]ɻ7)i SBjV(v-+XK[ֶJՁȯ1( fA@Pjj : >R*쿢" R5Ȼ:8B|A+x:#gQ!_˶Q(]QU/ԋ$'ΓPpj%kݣn i%h ŢZ|8 z=F[ MEEg-B9GpX@QK|kXK?i-H*4 H( HE   JBj[@4,"EXȭfQ"B4Tu7!|Th"$ F'.:~ RvPl W?}U':.ԟG˯CgѸ2uxpiٰ)@Q- pb71P! ء=c0(wGpǟ ? !"#IX)Й-5vH6.Nxk Q6bRR1x1ꕉ~EuB@C C4 WAY{_$S4` (Ռ: Wzބ [BV)gdaZc2K[ ōAk5pejҥT$hF'ձc%ȹyd%P]*!ꔨ{DžQ-P0M2 I(3r(0Wp61-y9ʻ]pE/{> aD_f.=0i=7i˓k=')~&襡v]"HJ B^iR+B9DBH'(mQvdB(JiLst)s47`,yp%1EYQE=V#5.D`(ʢ\V^K AХX9DV=^A `B<hf;{FA7 d# !bfkX!bQӰY"A$(‚X!L4j*V4@P!HA$IPb $BAdiĊw.SCXhI %h!YQc0(Qd1嫑!nÆFƄƣ@i|j$*e$F$ QceMPO$V@h~($~;xavĐ/fBGQ"g3C؛& H<C8N 8 ,@ @8Ro` 8үcHWͤ<0sV|f(4.&0h@58`IA G!u0= E (2 Aai :PZ~]5߈5^`qgZT-p5Y1Rח-SFKN/}9 >)zr `=ӁM0fw t B&!@!P`o1mPaW bq* , %LD"%lK`,ߜ@" Z@ ( %J"UsUDPoV1*™SHQ_A&ϥHc f P~8dvs1_kOislAif `N J@T҅%銟 )2n&/HRz$Șcm"z44hbd .* b*K r!Sg $#$uKʲ\Ir K⑎5ƛ`F1'^q8,(D%A`iI ST Py -@RZ/W&3 RH%@LT!M:QZ:$&(bB A@5q$I7UͼDYckQK =7 "B<D$k+"+W5ﰿW#raC?S1,4(%rg BSB;lC@e^i>&yn`23@vA\Zgr QV7@@?Br-YJ 2 } (NU@ h]6]>@0H:-MFLe- GJ@^~F@A 8d$=&N-?JLD!D`/@hqvR@8?*`5}jcH($v 5SQ E*>H@vAbp'| aABpnA%B(-j (%!@YWB P@Pm*I@["Z`}L ''l@4P|EIvRPp#DIg95R4 0(.U==E8J?P~9 4Kǥ]3 a!$:śzJ_$nC ӰB rd=J`7  FADA`aF#BZ#,kt*Ki|@k.qFh% CZ$upi\m4 bAG}F$t @6L5|!-ڿ#5撃w^I}jR!.TWdrna8K)*6X/ ĢGDXTb#d@B NXS q"zBaQ8zɤ(@)Hyā2!036 d+A@]9!H":cV݃U]s4+ 1 ǐ-8Ât@Ll)o?!QNL]cW q0)q4yyr n4%N*俯o@Mm =4;ZlQK-k[Y fZGhqb0C@$ 2(ș> /t0 K 0`I*`gKiTE t0y8BE9*8CL4:IXH@Ҍ  " zH3Jh}ر8sTFJ_* m[YHAHAeAD!HN@Щ h̀ W:+F)H`;UG221@JR1JKkm7Pf|.t́5 |M Жztp9@h&4(F}F(V@SA4N.&4SRIƃ$GB tH!A%B4,JRmX@V,X*0:@4f T BBzQ -@d@UAdn"BR@ZD6LQ@DjD*DJ@X= O"CcI2`5P\AOAy35P &-(J:@ JC*`$xP'Z7?PA@͟S@PYAD(˽6@;D6(OA Hjȁ @$@LZ 9HH;XFg y!2 L FH0Kv0)/ .(15T5G X{0?60 A;,bA .G| j'@ &j ©:@ (6}OhH @ q *K]Hӽd2_H#XU$whۑr 6 W@qVtX0G$DEAJ;bZD(B JF0  Tp %k݄W I2FnQ\AG D4k=!d|CuC#Aq8AkI(;9$&Ld،Nu#Rb~HYW"+&@W3D$$A.4 V" l1 q;jq V&39#fF$+{T8Ŋ R1/)yÊBT"TR8; W=rZ2GXb(5kWaiDVF$*;ƊƊV.*p!GPp&>¡(@ҘHbG(.o4(0"}cF!Р;L|),H! NKxd CyS@\ǠJgP CA$.-t"߯$e6 be#a*2IZnKfTDqȦxjÆ^-Y.% )IhGD"X*8G bXE!*btwVMc̱|X.$av" ;Ic^[䱚2: U%d J$cAi,Y*UX#n?-ң8E(QM7:_ؚ*Ğc4\qt̕XZ8\#F 3(Ni-ax Q+FPEֆ1t4N/K &vc? 2Q\쉄2@T!djFH p yvA`"S+ȆR}JNzBH0@ h䂃A vfb4x~Fq 2z4U '0!ȡ.%ƒ+ABժ@\h# ,?{˓7%g)HKf#H1,#mׅ4FC!Y- f߆I&"eC1@@a 1ɐ!baC5X3h}xFd# scp\AR#@ zUO w]܄j?\4v'9A2&/ѢE& f9]r#ʻ m $rZ5"m (a(b dPx<#Y:y#IU*c ") Q4k hr44 QH,ye4\/ @LV`(,Q M!\BdJPPAխKr 8w@HRCHc% Ak1ubpa`Nc5Ueu;JgV&hΚBHt$B)PMqG*00QJ(H1(@iDAB)K򎘬V(2WKraZCiU4B+*Ie br%$l3 2D) .v] lU h e4k4Y@0,A厂_@HSJP5̾]ӤE`B "UJ1kM  jhREDXTQ1BcZ$PBϐk9czR4ϐSjYXH,I!2#S88DF K0%A+BFJ\y`$CbA &P@xT-/]BI%5 #4#TH,ADDTє.jo٢P&J`(qYp6L"t|}aPdt#J  ERU"uqRc;\Pŋ1-^tcJP*4Pfj F9բQC(ҖV0Frg^~GhTBH ;GWhE 1` ](I (] o}DۄĢ$Wz>RD7#X8"O9hf7܇7R$bQ _ (8`()xP F Py(!1@hZB+X  )]""Sv+A(^?׮"y\$yy $|#&""B1mtݖB ji.1kJ.H'Lϛ0D@8#lA UB)qT@x @!PРGnXd:1?(q]S8Caok Z+jc!b@rE@e&-R*M :H4&v0DH@7!\n tPjtE#XHŪ:ӻ;v|wrDtj|6烋5ԫreDNS@lL褪  E? PЫRh,1@M)2B@4Ji %&FQlv)Q M6x ֘o'<#ջ搢:\%+E6%-QD~g r;Tb9ʫaAqO#1*Un%;K"U& 2P4^nXɁQ`  E & i6E:+/,tt:: BE7/HxgpBsjyqYܘL;mVÔCL(@91G@?KVmntt  m 5S3SP`Kju Ÿ@ H J}h* GHC/.F 4{(,IHKɩa^C^֕ϖ+G+ B W_B 1F(ٝbyW D c=]M0a9"+N N,EFY9iHR?g 2| *ФUu#'`r`<D<@5BAp/@b\[ d7usxt-nPsh`6ߧ]>A􅨜 H" 2b""Ł2e$Ġm-UK)1DQR3a5-jDHWngZnj!V#p#D)C/:_VҦeǓq1* (B28C AdtH^UPeRq+LAtd) FS-XZ<9.4Z'0Mӫ 0 Ab(*S jƎ@EaU$@ ꔡRoS`t"PJ2@(: CSIHvE 1A,Kv5 -Av-U\ *hUuu< q%(AC(-CСar1BgC1A(>@ACEqӒa qrAJͧ]Z8Sġ(`:t  @ hĜLAp!uZ$_0HPpd(%/jR@sqS1$D+HvFh1MMV(@8\QnƊW9QG:?X0  @ D>3G308A䴯E|P((%AR朣x&7 9rqST%G]*K$;zQ$ nA"EQR, QP6@kAq'py"!ŽA! ]:&l,.@CJzT<&DJ(P@(t%!!p~% 4B~H5C(a@VS[ _ BAIUF |s`eNY(,AYܢ˜NTR? lC+1R  ,BΕb! ej[ZՂHB({MC^ hv.VeAT'ٓts]S3KDfjX  ( rׯ_UI"D կ ,xoP{lqMd7|i@rgI"܎~׫*wkB:1hXij3: ?<UTœ @J-(A LZ&U!m-5+hwZCB1f w|/H\b;H. )Pp qCI%#Jc!ZR%E*tB_8p(ICLda@6KR4bX2JB:P+MV:HVJ` $@BsHZ05W7R% GVxis8!,G$$]=.1"`>I  i,i,AXKF ԉI``j@h4AHYbaVaJ<̑F@$_4@qopq4+IΨN{qBĂ 05pM7LW3~FsF(HľqXQ#ԴC9%qꊬaňl!gJBVKT1F}LqР x>:!#_XZH!_5@#?7@̓ [lexޠ]@Bh(e-/U8ԌORI( (Z:"7UbAZ@ 5@i]q#+ !nk9NCoCU0A`DŽEs+&D*:Ox31tVWB (WHPXhQY+C.pHK#߀,15_k:,%~_ 2N% VqBlT[r jB\ ZT!POK-mAWxHe"!Py EdơG4 L\R@ ?6P<h/LFMT r $=]vmʿӂ`<6O,A$A X@b4B%|S3D; g86 E PIj J>#CWI+ 1S@.a(,?d>U~OѼk40 (07)XH!*^@z&L!K7(^PfꁠR[8T)cD+3,$Q)!ֿȐK*:EHA!C*Q* nsbLr*AT&_ 2@nNrbBK%0_̫zz",=-*sq3<2S™"ÁӨiWk2i >oPmG ;C ?{ P`PFל, 5.M\ȝI-؋E[ϊ 5Oa  ʣ,\PÄ(H]B  _$@FBvF,qmH ,w@N(B1PI]Pvv!} :A$D݁(@ J`q(- H X J@q*2JUS%LT xdg!B AA I!: !^H\9wP˒-?1H;GѣbG6"/y !u(x(\W K_pqBwgR@jewAƔ,N,%U;@fѐ(EE(a`F\ hfD(OC/a}~hy¥K*3:2bQ L8CՒKGi+ G B]/hg")N)!h+[HdAaV- LH AĖ |1B:_rU[p-(xdZ`d~Rd|AHJ,cO(4 _i<K2{|&!KG_BsЩRKP,Hur bLA pд0Y-$ =@=pPQ\jZX2? 9 1 R'O@QJx2%7[uJAftqDE5'PL%kU"{w N\(hgvXjhBe$4~<0!o rQ OQYn $zHpRd $yr)% B J:B>T399gPCVЂ-  K|K`Lh@P0VY9k# If@ @R+ r^HfW\),NPv+ "c F;F|tɜP. 53šasT$dE$bk`Cr!PA aJ|%KVzT9+#E+A]h6U)p8b;H;lHNB+Ph dbgeⴄ]|F!}81dA0> /B贚9ljPay@-ez$ IFZҢzd[ 3sT$ʷdU,QM]XJEV<OH,"L^i@5V$8<4TdR(( Mq^H(JDA(y 7hA@A UJ Pb  PH Ti(*2$[UV !_.+D/h+4Q5.w ='_Zr/<"#gF<\iUs1+HM9Acя==lñ(MVPgjV)p}bs|@>  (k[KGy'E&J)d`[I-PgEIxJd,JCG/kkߝME*3U5 }/ OP^V((6L4!@r:THaEPhm 4cBZEe0ĭ(=PCA@:_MA0h5ttւ+RQ+ڵTpGxT|N C DACAxP6~*ј"|XpEx8R'!c9Ad"wDڰooojʆI#h@a)zy" ("dG$y^#ULzjJ2oB 3#M 0ބQ. AA;JHf!zag*TM!grHHT>zN$B8A*荬 "!TPE%$4}(@#Nl +K}JDɹ]_ 09O °"`Dr V{":W†do )>zDO@v]= Z]i", UN)hqY"!/bbM1LQ܁-1 "2&R"05BA^(\R Bݿ{e7 v(fRd)>$ WzHM+fR"0,5)gEY`DIEOX㲌< 80R zN>q%q i,?G c_ e7e_Q\xU3D";׮P .t)!STsrD%Bc(aiAn$% rBP p"1aI:5/)XƣP,U]j,JnӤYQ}/R H9F<!,"\1 ҍkh 0*< khx`S1DM jП/< "!o Q3$ Ogg#H- G 8WL JJD&Է򎽂gJ 2RWQX``)G"b+m춈E &48@d`L:GQLmj[\~0YǑm@p)J"wئ̺ǐ1ȄbJ:yjgPPVգEwI-(J}4+ʝNLRHD%)E/s  *ϳj5*d] hDd1, %w".pW $Jj0 @i тF" ƯҚ)'dy Ў?LT!~:$hJB4bЎ@j*sadV0*DR刅Hb`t^}X'@gExwwt45w*@I52T0#.(Ѧ` GJ="r-.&EC~FjJ@ 1ZP9bRC#R0͋HWDӒbbƚ:4)V QQZ(]t)5i7!Tbxtlx T.jrPǓ[, (g&[$2PҌхDsdhhU?ɐ8*q>Fux]x% \##p.MMO Q*܇deA"Sn)\Y̼26%Ghf =\щCO+(#̐NÙQ)>iV(Un|A6RMbhn>[^*,!&bW4 1^8#za1B 3`pV-* `\s}B9dfL#1xZ ga !'(O"46"m|/@:JAA7Jd'b!^Z@0R$@Xg  -YY ~ZEiV<4 5 'UZH!Bi*y0kkCʇXe5wHȌf.,|+ơ+|-2P̋&%H"Kk2pfkp 17wZ @` ):D% XRDְ(JM)Lf38fxgN8+JD%(ybDc¶BҪjMP ),$e0S`%А&m-7$<{jz9-bY-YR0is7˘+ h50YZ?Y"T-~ _:_7#fb  IxG"K(' !`e(E'JFOv Nf}CE $PKQPjzщa $ $bD8qkG?(@@MYx&`c0 ߨ9wC'yIp֠+K L? F4 BY Y $_2H rp?‚zC@#8@@D @9N” '`c@P -XAd$vUAj~F$!nw.r, Hw:L#_Yf!;f!(h$$ QphPe)"4V !&}ɂJ.rZI0'j*JR m+G!֊ R(\>QLiE܀HI.  L 5bq Q*̌~))$S ~h= _&@(wdX0T1H R Y@cD@M'+J @]@TM:P`tPaH2DIeQNPЊWʱ^<Q`S[JWPX#j$-~ q&D(a$q li0 b #ǰ EkVP:zHaGP 1P{YlwhEW4 = AܐJ@CE_Lb q M4 r`MSJ7,@ C4P 44k GRX,1^  b H$% TŌݫ6~'嬒X U,'UJp> EB4#acc$Pm PA*ІMj!BH[\BZ#hz mD%CE rSs Hge0+H~b=_ޑkqY TU;<`_zD9$QAOJX"NPyAp*DG͈[F+`D/Mz1m}fAD p[KU _%1EKgKL$ytJbhZcO) ;HǠc~'.YI;B0ΎVp*+ZtɪqDEtѢ;@c @]HZ+,jPP7L("PhG&;$,tz` !Q:IvxIy@j09U R R h%A R Ph BFH6 3B4C֎,6 Qj(j3IumkF\O*Lb.B>*wuHYMJU?i )Ef$2L$j1 dcH\ $KxYi9 HɦfS ?ՠh)Ҕ;+  ӫSBDLQ>DO" \qH 7D Ăj]9wvBh}B`B.F>E FWț $)JdQ ?ԥ@<8T7WԿ'Z݉̚Jdk%2IjL"H۬ES@y:@`(yEJH_S0P*KP 8t" -+Y\AOAQY'GqZl6_[P,[,zm !Rf `@ r ʦy@,HXE"$ &ӁŔ$. ddY J$GƠ b=l |  ,kXFS0̌3cTjc;1W#F%hH"C.(q!00Ae40ILJ$XKJq#L):HOUβ- Pa&!z8jcHbHΘ Odsg㌔Tw&,(IOw`4KreH5 zi:JGF(2HV QZu? Bp@ʡ ]0A&~ )&;G/T1 :P(Lf{&L2s¥ҏ ,&uEtB|jѦHi1N5P1$5gh3##$}=@MR]x]V PCKxGP![nvh/,FD"]g{:!G 2PKby !CJ 41Y0!T *1`+*g$` ,<$D?wo<(Q@ G 0dm2i b0c uڠ'Ggh 3U F  @4ED1Xiԯ I,4Y͐E_44ZI?А*,1 R,XDҥnl<:lW <( !d$P'4Ag~eZ^ʣ[,i1$Ua%B5ADo:O< &xV.N9HA]N`l6 ~`jnx_ n=[S/hTR`&j))RP% X/~(q6_B@ hbzu*$ Hb ]XL"3@Abή*|fؓ@.Q;T@ϰ `!_`p64Q^tjd (LP0'l"SkG%{ U @?Y`H ( ,0  APe }~ d,J* q8k֊b&-24Ap`q)i@6qvJ2\SA BzYQ "B#ajCtajCtBԆ RD-Hm!!*@wA_B:_nL<-Ps,t~KVY:THQ@4@nj鳠~>? ʀ#4Bi> c]? vR?ҝH'tˤvC1Vs2c?G%e, r\ÀI,D@@aP`U hAZ3B2Jv 7#!_<0JYox`ࠠ ,dC/^"\^ ,!nC0(AƎ[g`$ %@hHOr19 AO~F@8`Ü,Q ^`Ţh )}8J $ QiQ#A_E~ Q$ P%GC %! _zH )j} 4\-7|j)_O31~]4 ?ӳE(4~NwMGlKcDY NaVuߧhHLEs`(Dt JQ/.4kӅ$A~c>_,$kP!Qr 1ZzF,oG`6w @ Hd H$^1 *=!D0E'HDrICw"n*c[qB?oV K/$P[JH/݌a=ʀ傅0`#s $EK  Be?VۀP,Pc0F~C0 R"(x#Cn"&b%$T %=?2$($[Pb I XhP>8+0=!!C J= }em+ +ϰwG"W@%RkeF˘΅ :bӄPSix)%GװE`p(q:C@rl?@/{pAB]($ٌ:.HP,3dxHه`Fi`%FqBI05p8r,HGDpZ3+#ѠS" jNG_L+O*1 7䣋-\("=`& ^ ]p0^% t!3v@e/ij!d@QSJ!Za0ڌA54`Mo 6F#I.K  L*.HJTONL ^6@r? FV4 P!QPGD}|.4_pz~B(BJ(E3|W'g2?0 G8_B쓜4B?|@:!' 3ViH e"Yv%DUHkvG^H+@( k_f"*A<P&,a!An &xjAk" Jgv$BC֩&ݣ֑2Ȳ 9<, 9oHQ/bhLFrrp{pW;F O@ 6MH98w ?' Wm!Bt0? dA*^\*q-Mq#7pP}!LUfbim?1%#T_i<R Ѱ4 P֐@ @dSk(,8%HȢ@zѡF.,$aK yB@PUt4RF#`jT2 +` #)P(& !^yP|Hx BRz&}ӧU$Hրh01M6Z/ZGꀖg6q48Bk?E}D5S @E)26B|1Zމ:~T)%JH=/A^:Uj԰OzY"?}p:{ "tr~3A #t1X"zQVCH<S<- YD0L~uXrui EbN/jHmOI0((`$ H PmA O[AX, i53/E@,FDY0O)ɍ K.Q!B !!JaS)߂b lAFԔ@ /f A0$K|fEbҟ, I {'A A rvF g@ HUǑMH т ˍw8`vE^FȐ1/i(:j 18`$LQՅPQ+(EbaN&S(GXE=ɍh\vEY s<|@}4XUyHGCnyT%q$w4I@A24QĦ6TZ t %ڀ- ;eurh=rP)ɠa I JJ!BAh"?͂t|BbYVhtR4Jd!X|- &Mm@ eQ !X-B<i*>A(?!K%O dԼZ@d:߇]sx@a ᱉E3 | c@soS$Ul1Wa(6a @dx)6*I<g!'Za4o VJW=Fk}Xl($ADJN#`ELaotJY7@1lHDp y3z e(k_'gʇaY&(\(+LkQ!Ƴ0J(BD 00Z!N TywLubW-\u\9[Me(Y1TF֦.V0LN9BykO(ATH#AjoN) v $ Od`_uFQJ:u qHOYyQi肝^]`S2TbGR@Tt޵8xC,D8JDF>HQ'?i0^8O.(!Bj0էrg)W#t9P30LY>HMQM=EO6z$4P%WY(i!1k.0h6Lr$Ve3W𡮰c.1jm$bɀl8p }!rgFQ`$agQeM5K}#« B е+ ŏ!Uu,LBN`в P"h"A !8n!JZ mv(䡑̹fF砶x7iHW$!F#lhLkH[Z%DBHBWGXV?e,Eb> b KNLEǕ,;I#Q@J++fs+ΌƦ@-ЎNV%%:$LㅊPv~j1T*bU\Tf))qKa=@ /o(p#( qcb@701]7)c\8@RB-<! _ P ¡yZ>|= xS3BPfi0h PH`Pb-` $FxHT`j42!xd^:/ *:@TTXt]Nq K*ȡ(Q$2,FPX@Ih @V L!E@;F P&@6< V<:x3-@P\"Aˀjɝ@"qd,S4B@kTmP->SEiʯk^R 5$"#kSdB4팸"CzAŪQ-x*%9P( lAH d] ܠE/7E ~.%; T!@rBd\iE)^B )A e0mV^NJiU? )~ `4HbA$c)H3kw P+S@u1w h$@ PDl7VxErBԏ/hnA@ { ߒ4}/ ]xOq!Di@8B %  D@1K($1^AJgg)ߠ [ A@[ `Ly/ #D xt+ӣ1&+Xb(;Av+E+U{0(pu`(`<+&Br fph$8:Fhr4p3@DЀPܦڎZAJ=Fhp#z ЧKl3?RK2(x&"& K9h6NMPhE $}P(JRIq*f:(PH1D{rP1J +S" PZ ^kNB E# TaƫB(e1LD?D1We|ZI@\ᒡꑟBܠ *ˌH`(C򊉂S@bÕh[(M, 5|u҂=1f_1wR+@/uh O9(,&z3;^"hY)QF#G|+!k p@DUe2c ANRQ MK Ii1Q I0&WJg"&գT  'V)*,!A=?4@-܈`_Ԫ!yȂufAoX$l-J,+c>w&zQK@(tCb!OIGQ( `2 sHSt' `sׄ`aG&Ң~GUӚl?Nk0MXjM24)G Heˬ wVdPNGш\.Yc\r:LF i,'~ j9ƳEe%li($ p( qj E'Ql2R\Ik{ejCJNjY$?P|w!? 4Ru6>C)GnFh"(L䑥DT0s8 }YFI)/.3S3b" X (1#E ,BA1p& =c;eN Ú8˖|Q|0p}/N1UtCw{ .B{&b56Q{0y 5 `A%5ΐ%)DHA#r2>۠ DkUA{-h.ցX{ׇ &r U D :BcA(fx.Ri+M]`ygXuI5-s?H9D"b%YȠ  K9@ji(AM%2,W#֜4Ult|#?E<9?E]>S@+By-l Bk_RD+zcB> r8}x3oIH]<=CKh pbX<%*BLt1KCCm>=HDo'~\M$ P ޮKwsڰSH+ &M(ZY tK^YvDхR) /"]( wC 6ؖ9۵;dʆvs3 2"!bDŽ2@SaBt J$IR:Dڱpe"£!!x)G4sf B+"Tgd2+H RM?Ő(B?`hp+" 8~1"g<ɠand3҅Thx8y1d>&~ba 0G̖ <(L#Bt[y0W[|^J̟ZC\Y#INO"PV^x&"!,$=i?3-s>CCqTxRI'qq**Q"hP`ŤsbH o^FaLS-~b d>Oz!X )$[T#%bzf2Y4& }̹4>&EKDOtCYCJ_(caL %9H жW9x ; 'lO'gǁQ(& kr}aI0j5eB Q &2С $E{PuU,`up[\RV!E!MdoZ"=2Q auJv´GE13ȣ [?̵Rz3ȤNizE=٭d*~NHKuWW Fb+4 I22BC: BS0:-OL9\!-4`bj)e#Kke]HIc$]|*+u,l7%J%1%pOSĬ%#ۼj[BzbZnJT0@  HrF! scȚbXJ\ yX}Vej8Yd*? ]esn.&wePTSp;}!n[pAkkQ&*_"A; ]B!,j3$DcI(RolS@4N1C.FIP {P z0 hSK3CE!Cơ?:?ai5<@ XnɊ !k4 *rFRJ @4Qū:¡RJ(꠲y%ED$dǘiJQΰ8i*2 IhPxQJ$ +J8(QGDFA 9T5 IQE'!Z)H,%;@P4;谦`kBr<)r%AQu1 ?la҂"!aIJGZt֓C^gf.`ٜ˝ VYx?-$%dT$?iDb8 =3 ȃ!à K% \0 tw11b!r|(:CRd'$C'} ɰQVNnY$pP2qȷ*$D]Io( E]`Swh_՘huaO:v`Är B} [ !!jY٧;Qᔚb3E-*_D܉AEPt@yE3 `$vJVeQH_U⶛?»R%]wh %/.,P1I[ %R%Q*r5ВZ瞿_>)u[DԱyvE"{0DG8#D!b?,fR ֙?\vsu͜v0ʏ$D "MY#P/-IE8VAS2v%*3)S!5.G1FZ)!Z{OFy' IQ0'f՚%@0B F+*a 25#(ZJ-J24H$͂)@ BiFqe&J{}0,tׅ0MhP  )hJycPojbUň Fm1l};%+K"ZfcA('hiEIf,"--a$!OQCBn'H[=u"ŲE)Yd{4Io@{o| 26 Z旄fS$Z ˢUM24ތW`.Kq)68i2 `, PB  A,h?usXnU8C$wCiƎPyIVӨR)|pG[敓FO{Lc#%Kq&%A:,DZ!"/c( nm SW|pzisjT*jQ7f)AcYA!踖U;Ul\>2JQ`AzZO(yp>>;1+'k7$Hs< -O\ :$㕮t{㌼QVIn L EJ5l( BD, XK1#TXBQBSUHQga,ո f|&8:ejԊ ÙJ8Q!@2@x[E"R@m$JBѥUgPKQ$`v*Χ#"TU0`AMj\9D!VsbxΊK, K֌ *0a EZtQ⃋p;ST J3ȏ!PX`%ҩ,` ?6?9,&X$B?c1h#bPG=O!iXE$ =ƿAJܞ8.S)(QԎ0x(d2#}<-jŪTMbp'c“! 0XԼ:P餠!ap c./&#'V/D ^mzb!\)e/oN)RC8tpȂ8S ɉ@o'(L`]oE`*Rc@HZ+p5J)bH$H %E]|d@ؘ%cz a օ"x)da^}Dw3ȋd!sN&n͙`m*殷2pW_DI8 Y6癈pxJ,M/3qKN'a~ǫ2!6 (`9# 6_!">r-‹Q Zڅ"35ɤX&1{g))̣"}6)o> =gP-g i#` xeI5 zG* )QqOKGC3eɗedڐC $$lj  5.:(-==)s`s棡 (|ײrp +rgQ;IR[ffF(f?j"yMryhּtM;.L{͑Hc =*Q$RP9|I, b\v+s6 =,;Fw{NCf.*#1m#s&ֹIM& ՚ 0) #CJɡ<J*R5:@b!6z `Y.,4l)D1E,җP. h U X5fP+E!JBU%D!f$D!8ATW!jC$ fp!F<^!UAf<b)*T/iQhc'B_FWE|%{KrzPd+^u֎H;Lֆ"EZF#aXf_]tLU1h! ^":N/WsrFLHbLVtP0:* tTCBQs2ϊBƏ_VJ$!UJT& +> ZdڒDϘp>ZR q 5!mLbʨ, ??cELbJ ,4&WB P:eL9Hf`a1'Tf ـ" q,R8ȕKԓ$ %Hg$ZLS6mR'2JN$b SuA#iPx3R!C!;XBAV= Vz ٠PCf`$Ha*5SG Kp (} e|>@q!r<8 8ONe!5t,FU$RS$MO+5EJ !Q$8$@B2HD ) H0{8[cCRHPe5c,y@B B:Mi 3ծұ/Ys xZp9qG2u5Yv-_`E/v%` @ RQDY8 7&ʻ Pj<J*IYzJT=* H*`:ƠzHya*`UEiuLAeq9' *dtxA# z9Xxe|[,^4\Ӣ+TG @2v!)0vu3F5[ 3 1"cWR)C%D1Q^"b,NDB(̀!$étjA CeΆdH3Ll 9##LEbrC)mp< TxEp%n 60*(%xnPF^e!N:HSSU"su2w 6~D{\JA .b/+#cCsA6c[ȅl M2o;) 4%iaCh"3%l;K hq`|b$88BuOlC xaèt=*! O*kC$!P &(!$ 1u' <[[V IsZIηAFs @zj $cFJ*]J Y6e.]^K <@0M~AJR+k ֑RDZaVB-Z;-zBNĚqi3Jx?($Bv^<#hRȑCVKA+` BKȖ "B/b4xvqhMUV )B]@*Lҁ ЉHB"4dEy v @%HH%]8=Axj RqU ^_G^@(o\#QHHbRZ^JEiłU0%B1q' AC DR0 HAY_"|#x$5u!f<fXlAgXb D~^򪸓(0¿N+tme›.o d J_I|<So`hQ\K|l0@QH !*WJ@ I@w`!puuu>N" H;`DLr2b P:xifaIaFqZH!IW E  Q䅖N>""Jd5@| :*/> [%g` h|e26H%H" ! |dB(`GB:_HSғAc,hiha[0Aޥ3 j{IKx@G "Xу` ؼd"Ù%/Fޘ+Pyv@ `)G(,ʄ҂Wu3y v?R>:4/:sM&E/G$@Q89*򤯊yA:BR)iPB<w>`A,J $0<&HB#A;@@2@@C/1Y'IS (y`%AFUIb`L.:|;8Hh)6i Q%UB窉R)8k.|t֛P`pbDluCk] ,Pq% !Nmѡytz @[-#Xhb~T 9T <Ձ'Ѣji0UB EҎ= Jz "`؂DށűD,[i@X!yŃ/.,(AC(jIAׇ`ԣBD,Hij&ZUU/XLO 9/p ɉaPkL!3R91 v;1\XE,\,X;Ò@pƊ' 9Ble5QA F1^>r!`Ụ FcI@BXkS!BE"QDr3Ɯ ӥ0YW !΢:3d9 2!%2+͇JU*@.DH!%2Ū#"|/@$  YW:vǙxQ$-8d඄Z[V KA5Bѐ4F0KSya1g%{yYO^xOf 9!vWIq'#ʂI .*,HP$B#AI{{aiamDC4կ_ 2Rx.$~8W! T]#Rg@I,!W bK@hFIE*d(AA2+7qdP3uĴ-qi N|&~:I"ZkH΀?u0PБr7 0Lt#@t`"#%!*$4zJ:j,Xuf)ñ !5f1j#IJ$h`Y$HuS R%@ɴ!Ԇ; `f/` 6 DUC02mL%X'i dT!bdL3ꎚGiADR*.MI T `ZؖIq@ {LHe[E "Jj(鎄e?Ɋopt 4ED`c@<إ@qiwʛq bHK0?T䦖LC`Ve:!H^^ u=1aI(QK2-w0wPH $‰`)R<W42@Du8YtGṑKE PpRŒ*sZCWF)}}&N`R? OUNOUv@H]$#-Rw mnw_L0rPn`quÜ?DF N$ C9(er;b4aݩˀ",H$C _b вF HB? H1Qe>1oOT/l  a0 Jp[\Z): l`+F<`)xJ<@2~`4ETbG`X]xwLВE?},KF3h,4 @ tJPЬJnQr[㒄 TW3"ɜz,Q-xZ aآBH-,h@H>ÔC{xcDW0 Xq$@Ďzr~A| B8Z60x0k`Od@G_΀0v r?ʑ!D#M1@ 8V?U>jG~bpPjDHX҂rt-N>@)=>WP%QE/FgFX 7XQdQG̜# ߋHTJ1 $# pHp·*aւi "DI*?7YYrX+@)D)I<ch#+06?,ӥ.C|DQ(3  U>׷+J)# ɼoW0|/KgN#|Qx)mEJ$nXcg&0 N5נ za5~5>5ßdkyPٲ$ Bp "= MV R5]AS܀e-QXi@MUҕJ(tZ`ii:EFӫNKԀXiKFbkTQ zpDd`@hO 7 >0 mPIa%H?T@zb`/05@, %_$|yBAgыG/81!srqRMPF=ӌa@hV"J-#|CH?+?@YAؠJґ _xᙃE6a-)!BD@e..,%@cާ MB(\ u\boE(x d9U bAƒ 2CJ!҈iD4-XWPIڳBE 2 gBvT>Q""]@B` paŐr!HJ#@[`cL~ADATB0$3![hԑH 1"u0`O=NA* t} J hS Ϩ 3 +xCNPe+E"T;MjT"ؠT|X *0BV(! h y+p= a RHe!:!AńVH +`DhPB*dҧ(MlZ%U䜒髤$cB2&HBH)$ L|U"Ml*lb`h(@Ő,JD)Ϗf,4TAjLHOjH)eň@CCBd (Cx&b`F~MP^AL#J@]%?J?BxI'ա $ -/&h+wLrDf o6eDJ&L? p07́3@ L)5 7ǂ;'a~NxD`!(.ғe骵Wo A@Rt߇`gPbd"4b) ,R ?V]U9 rF^F $@P [f&iVP8n͂(TIG"#B e)q& 8- A24[܀e,.++A51AM_[ۮu@#OlGa.R3M\ a0fV0&@Μ(A&5<sl&t@_)xI 9<,_>M.:: I@&4+C ,xi]4Н  hev!dx|8Qͅ`*02C( ::t>/Ҁ:!T Ȩ. Pi7 Qi0"tL4Q@$b(PQ44/ @ & 8cHAtІLO0O4 ε[`0/Z&R?h! qR$QLKY kPt}r VOc <O"ІXP(!S2Z8|#`HH`3Au5`U7:\""4d;HaX, E!J#|> Py@,r^0C4غPCp&~Pl)Y8zZZAU/ 4XB^ZGh*_(d+<`^$CyB!P& @lACAXnZ] *20Q$C )>E?R%7ҐF"UGJGZP ;/`ODo5&o˿bfDɄüw$_-11c@sЀh̟CC4Q4tDdqk0řH/-J&~dߴGgD?-$F"@15ZFz;J,(*ihkII $  h*hZ.iOP! $M^dd ZA rAJCDP:c? DD4Q$qeb=hf~ B\_5!* Nƕ QFVj#Lq.b*S,keBVjLĠ,~X%r1@J]cA' 5gV00ha X фAUP  @z@PT AUt@gn ė PKbH5Nh\P0/P 1eBmxxŌ!疞K1t**;Ÿf][? q S}w@4\^^^"0 ~G"XY YwM裓  yD%Bk/pl\yPf#$5k2@`N]Q":i)Tq.E~)h)P`2_ h I )ESSDt^BtZm gfFZb A~Ø|AEYP RJS$+ShH$FJ*D6D9X H2%J*T$t5HH",\ԠQGT-PK&s ,.@$"BfHFh %`?vCyCa `9H*i<_/t 쀲m4W~ 4H4i!Bۿ PSLzͽpsb@w K_2bT0֯e Yu@ PrЂ'=ATI `| 5 L%< 1$99$2%[ DLxJК0?"A9Dx@I'ࡀ'E DI K  $C =0_~q耞7 @-EVw` PPheh]oC BB#U4iQxM5mϋ^mH`=@=ba˕.} (QIV*uO%,Aw$𐡈 jA^ } \y^03D(P /+j4x,P\"P_}$AzE$Z@ ?IhicqCFcO3(" DP++oqϙ_g`$3D0f?M`UtK_ 8g0ץ42_}% YQ`R38$ 9eA ʡyA//) ];Т GVZv2EװRZ8RIqV9F 8B;9>3/'Ӈ8ŏ㔄Nf!lӺ*4PNXB4CqXrԨV<u8$A B,Gh`DD (*0d`dYsCBZ 2$Jiѭv@@BГ"h(=Tcx3+K&$d7_UJZ{ViDIVQ*HzVg*g8I jptGCijYŚH\{II2l.SR=W5#@P˞_S<\}KҐ 3S)$8-e&DF2w1:7:*rUDBl/#F=}/!p 6g* "(A CV-P:ihHuLLp Qh(@u (Ys1@2h #b2"+>}1Xa 6( h;>DtRE ʈ4ς v>E_J yzPGBXBU#FEB

B U!;^N"tҏ0WkU4 *]`s-VSCoѐWN#CԈ(ԓhQ"k2G̳iA[2 B ~aNҟuri06C FrA$5h<JWz62Wҟ)g8~Y0~ !k}pKwЧ3"(ξ. z7%:WXWJ% :k%R r : HD(bl, $ `QU;IT0pQ$Zq̌Xd&rI Ә <ՙ!n20\ z\`TG ksNE , !Ӱ Z  @ )JcH CQ@J%W"9˗ ֬PK,WP VTb* jҥ_"B1@,q$$ ( yc s kW/)t%Y$i gE1$z%@!T!dmҬF4f3iIlMID<)ykCb/ ]1\M$F#Q k1%8L8CTL/ C % AMdr!U X@ S=EXAvG: BcBD+#|n#3 s/RU%,9J9+CoCLKgPqPI qr)&i_< )CgkZ: B{ҘtLS*<<{AiW[aw.ha MJZ 5*IMGGQT預DU0KFI$%HInA(ɊZJPU Fym#Lr8PP y%#^(JoÀS;Ta^~QÅ.W&q0#1%/3@$`PRI:氥AG2 <8vtȣõ,љp& Hc2fSFAMC*aTT*24Ѧ#%Lv%G788D2U;!QO@BC + !✣%Y[\E`(4IP.x |3>5!YTf!Д!LC aKr ]a/}'$䜓`LIu6HOPp/Ac@ ^A .CaPV%dl"%zuB8ɐ.?Nxh%+sh)rh,֖֡![8%@-T}OpP|uIDFhZ"\PFȔZ+ݣ#Jp|\KdR 'Ȍ7 CL'0,T6ʚ)= uMo$u`E~NGh*> by=P*OS0R6Ki?" 0y'Z':yjRX//,CJ;4P3EV]nW_$V@!&>LS?]Űʓ瘻#FF2{ UA_d59 A#"IHBUюKYx*)!l [*3!xaE$*/LXDq*0("ѥȼF(1 vШ-YxpI$$?؟Е#GQ\bxIa%KM P(`PA! a102S ~8b<*|Oe7C,"<>*ľRP\)T^%RmѲ$ "frO A?ځTYxSD7~M!%L4AdHYI$p}-db^}Yh2kDQj>a'!#$pnfkIMhI QՍA2dSWD fH$")<[hȐEӱ׋JY YL`x}C("O\Ǒ]چc(@9I<b!=1YqΎבFk1N+"`ZYň;!]~;I2( uwR$|KOپQ;2 :QRH+̬@i68fByq!1",aU P%Ug*`EROѲP"k]~:&@<>4U}WִƱB܍8?`¿ځ];HH$sCq F`C2,JPТ*QuJFDѢ(!ryHgNTB)DItז$\BuR<Ɉ "ǐRgҪ!)Yͽ3$!C<F\ fFvSyhc1RVcȂYEYhJ/X8B5RA "%4 QG<()J: Vg#`Hi3&"RIl  X :-S>d #\eҕYΊ))4rB2UӰB2MP #9~-ZIKEJ+$84BqRo+xF=ҔbW)`3cHd0,%RON> `j60J i%,nqAٌ4SQ5 j9Ā# 5r@ 0HY5@@d# PY"H .@`U@ u lȹJ @ER$\tQD 1KR44:CJu $ҴRe1cŀ *@ew Qi ZDaT1 %JԿ/$ƺLĺQkybXZFq,c)/HBZC%DOE]<2G R"?JP"E&=-ӄJU+hXlD%vvo%P*YOd@+:[i8^QN VÂ5 !DH[13/PKB3`^H8jb0BU!kFSJqg˥7PJCW^BT(A2VyXg0M@)QXv, C(&Tca+@,ÐAN%Uq9G r` Ar 4Џ M$JHGZ^]dGhƜ%qWca_ IC"`b{ )u(*Hm0P „rRIEukN@Qbqe*Hi",DגG.O906A#sB TcWNcDF58qPEQ4BEDpJbjVjXrK]9l)R;~OTJdDɇI%q9g2/!j*Y'K ) w((2mgh3l [&DNjGWF@׼tQh3LTW90c :(cu}'gB`vQM @> .H@ V "Dv.(J$ B1)NGrFJ %!(3Nv0[pQƵ5QZ@R+ǐ0 $B aVrDgM&peOr%LօDa!٣EC tESG%ULjfR5JDF0e(JȤtXJ*3TJWcYH%,@A"-ȗk\(²xaF 0{Ư=+rE*8Z<*C- +5MFzFR& -CGǗ!…WOZ0q2)- cEdBZ5Z)#!$"ڽ\2d".HPRBQ&X"5 J(P,GN Zܥ+7$Ў)P$D=i1N:Ɋ+@+LMN%U`Ir.-+QIQi@$`2{~frQ(jTvƒˤa'5fACN@ "Yd8 Z HB Vs1c8U"B""!tZX`J^CJS( !aK&8]cP1aj8XZ*1UԾ"JAjj bHArF.|(lb.FܑВ-IQ~D?AĂlX (+UF\glHɊ%!EUm0lBnVbH]L">d<ǥ$ie 2 ,8CF+jRgbq3)rO:=;.H9̉0l^N_ôٿ_ E#K!5JAb cBC.5 I$C!\֘K0$Y?Hm&cѕ }$g 25ni ۓU+/R5Υ9[Nq6f夘/a/a&@gOc8aF zQ#]i5L+\@2>xJagjUim `}A4Bj&K!JH(:\*y.4ΡWR VHчd9ԋ9G g\K"`cW J5UЗ+0)9HYJ8$E@P'QHQT%GV1E2gp  AF iW4buD!֔92J5_-JgTkɩsQ,Ƅ #M04(XH$M$ B !M b2+ZcLJ.45WAbXʭkJō@hCcF[[ -H08G5 @X,>5Dņ%q@©j%Z޷89&ȂJ i" @%4 ^HTҠh[\b8ElZW:ǎnvHjOq vl4MD)(ff0!ZGNgTx߂bL Y`8FR]bJc6;;lī(J+Vvm!\^m r(tq(ƙ51Z*$PL(L!=A`DDH9Z4 QBer,I sU Q* H+ZWM q"s:Yg aPN&eցP&T hPIgE( 5cjz$xKVgDBR cRP@S˒$ uc2b|ctbBQ]u5aG(qJ09'r/ 6b,%ڬ4qe0fyK$^5!7tkʹTcX4N<,i%Xԁ !a.C(J@YL #Pi*Gy(J >aR#!C_ # QJΧټ;}h,N^qEV@4"=3uO9^S @z*)- @jLT3$9Rz5!?C6T|7Zjb0 W*Je$gM8#0`z|Է3 ЬeG@NW>p\Ffcrȳ,V Plj$;ij%!1qGye@^r1j•JalwAi̟\.΄'%r3K-] 4MPHXG 2X0DMݓu NRJDExpeեSQ7 Ű0فNČVVg8~BTC&1PHry~\\XL&MA DJ+`H"Z p|Uǖ%E;HR e8RDkFV%c9Vks :2 / 5P&9򓔬bb B>\S36ٱ!O r1r =(A/~!aIBZLaR WAdpɼ` =HkBM`f]&}EnԄ3($iBIy&E cU) Ań0Yjɖ$PbPD`Mb44A‚D `q&!t$f(B qف#K \v8U(ys`*E#+]9L|r(SH!% agWDw;Cne">6(,P4Œqa **b+0X\[/Q"*$R~ܒ 廵b02pvoYđfMWBBбBbfyc 3Yf;Xx@3AHp{m߅PUp dGϤ¢*AC:q *r l55 qVc(dΒL5@ @/|$ː$u* ! !:M BVPqj4XmBHE E+C$=S8y`DBJ`J hZLLG"y+[5c R!Z;/-1  3G#y8y~XBR(XHXE( cYBP&Hc 6)H!PM RJŏ&j҉N6,ȄMbj"):WP"XPCPR#-qϚk / !#֐0ےu$tBdN2i:2^A?WZ[QHX(8cp~ 2Td`in AF FL-> Ȧ8):Wk%\ lvPW%=&H`j P .uaCl7QR$:A QBx9 ;CѬpkD# Ibg9c1@ @( @$8QEp EiBjGZC `rWCE9^JQFkFV'V]jy+y*B*c! J/ˈKGfǵAFDd!*i T?O SV!oa*i ̘KGujh4BX1'ԪF U`B\ eDhe8T]3ʪ 9kA4谅Ad )CIsTˡaE(+BE+-0$rf. p¡uSCPMsuRX dc<D'^PCWy#LƊ Ek v1N @r3T,. <@tBVsEb TA0IVh#*\Dy0c$O'B$ 4С1+pDD]1oY(PJ9@1k!J.fS\VUJF4ljO*Yɯh'IFHSbMCp|Y?"d`cHp8 8:03Y ڇ mIԀQDŽ](2L{}ڭڞ+,jPx= !(^Ԫba8XSKҤPӔpԡ% R % ( TB@Qƫ&2K0R,(GJv/)`LtOP&IfƑaHֱƘhL_(U<K$ObfuW 4 d3ibRN@ "TH4Y& H"r!RC TPkU1c$UZD,"P.Ee1´$r %H`,@0G3ZQ*E51L^egJX' Z#&>bcٞ`g= " Dô",[uK]cG%%Qek?C3`XPҵx Jfd7rr(1I [ HJ'@T!a4(x?l(r VI&Q6i 9 ̋ 8FE 64,Ak ѭE4S\$yPށY b:`xY hNYfh qJԉS0 xaeC$Ĕxс E6b?j8{XQ3`BlP3P(A@JBA%VCif5C E(@&]BRJ U QL//L$&"@F> 7 ЂqwhA̘`$*ţ)L!Z q,FQ:$`HuuבH==!%uZ"U,Y j3J⡱H\zy8 ̹B9UWrf߶/,!ۄwa2!ɪ !9 x^P)؆^_F/R!bYp??Q2h^b, EBD1ψ@vB}( h.nH@l~>F QXPHH\R9^c1!@SnQTK+*8԰$ZhfN?(%P[NW,`gV!ESr8+,b5sv@^A5d\I `0 XAB}'dr@ӡ`Te䲻תK]&l̽0V, ehHʜ UMTZz,j@D \.CK@*,)hhZ U @߅# yP\ªE#ѭaY I b4- VBGE8yg#i ƂoyJ"4 UJZ(, K"m*QEQWX Y!yL`%UAN$.A2 Dr9HPBߞ5ŶXZceH %AO"@l0 ,AACSx>j?8@g6_a"]Q氲DCIl,YMWVvX6c N0`= (HPJk7Y/IGL;H,-)xobTe x1hUf!Bo"$^=2;t"d$P$ @HDH #^XF"C"d L8\PbbȢ $H$V-cY(B*eXJDr0 Z,p+&A-e$@RB_xYh 6d2Qh'B] Q#! :@kSKpq b@h/<@AiTaljˆH#<(@aBt~/NВAMy@1X%B5^9!P!@c4( 5Ԥ!H` w/-A*+fQ@*؁CȴyQQFK5q+ jT0`F<`YUFSzDc'8N"qD'8LX BF'@)p? CGA v?"$8JD q#nÜkx$9Za'D0 % Eæ!F}v5V";g2 6iJpJiPVXj)QKLcHW18f8e[%X x'bLIb1 @±0pRQ(T?% <&2*G&'V@I-KIr| R%B_Z"ZfOtBs(e T(Aq<uRPco(rF FXVL-n 8FpG) F1%CfD^_2`ÀBs.cZȪ$ e4QRP(PP9^c  @ EA!l#%*% ,fbVļq@:ybb FdPJ@( B%jseJUFjJe^P!NB3BX_~M晰( AɃDs-rn@a@@"F$+~A@ @$P(( @ P{4@B`73@m2%$uDJ;JAACE)nFZ(j"@>8 H\aٳg`!D |'wo !!`408  aH'5P PPE*<藍k}@DX@ B#@&$P((Q@h[9.熺տpAth `fN#I K5Il AD@$ ""Ēk0gՏ ْ9B8G ;Aħ%= ak@"OE01q$0 Af< {P (U*AF݀;zY$ Рױ " P  zC NI4X@CDm7 F`G|@ 0h@F"aJX1 F#|'ޏd 8Aq3Z\? A@AQ @`,E @@@!^XJQO@E)V| C, P$ 5PZ>B@ב F(|ztJM'OXA$ۄ!4T@@< 3ZbBP̉bJBRZp&x2>N>[ #JPA$dI@Qœz48@`X"$>4B ZBFa (( :es@P4M>4R͋Ĉ9@a$}G% HC.cxPD YZ>J@@BUYɠ( M:5#ɐJ J&I=d 1dcԤŪ51HJBP@ B ;Cs%W+W#A ( G<3Z~0 ('E @0 @PU3*PD{PPPE)FXX1 !poJ  A @P(((QJVύʋx 4;"Y?'d.O:$$"@3@ f`bQ(dK"YԤ'1)hI)@0 ` : b''S G1 [;uK|P E2_1l@$ P((E*ÍAxPPP'R!P zC"/ D@!Io@HN"y?#@(  )Js@Pb5}@.BIG1+T9p|0pF%%[ŷ- HRB>`@! B"F ~`2̖O_̯in(@@` `@,ڶ7@A9d!8$ QKYP xP(4#>6d PCbHPp"D?TdS BDhu((*r 8:iH84Q6((?`7P1!FGl`K-!D| BA`Dh_9H1X<(  xg} <<` X2@)'43 @M4ƻ$A@ P((QE/rqdxL't_ԡp`q9L/B_2<$6@ qEKGtw7.2 D9E`T@( T F$@Ph(UxPCh@P %//BȆ%` AzAABR@P4: O^10 O8@kX@@>@n`fQ(oЧd%!E|1@ 0AbDL `g A$1E?RE{ @<@ $ pKaIi?6@P mJ{8 * p@`|(@F՜f%JHBP QK'VU0 G)*50BB1)hKB !(I !1BD|@Acd,>$v C#D TʑQ"ELP A@!:u̦V?%}̜0!D?q5M6 ,!O@ A AABRoT:4֠Enр'$ t J.$@D`= Fi%8i.#r0"bd+[+fh3&T Ab!0s01l}'8bA4@;%$V_F0 (@P((PVhAѣJ )U (8@ B3@&$@P N  W$-$- -.,QP@`,ffw.  #.  #.  #.  #.  #.  #.  #.  #.  #.  #.  #.  #.  #.  #.  #.  #.  #.  #.  #.  #.  #.  #.  #.  #.  #.   #.   #.   #.   #.   #.  #.  #.  #.  #.  #.  #.  #.  #.  #.  #.  #.   #.   #.   #.   #.   #.  #.  #.  #.  #.  #.  #.  #.  #.  #.  #.  #.   #.   #.   #.   #.   #.  #.  #.  #.  #.  #.  #.  #.  #.  #.  #.  #.   #.   #.   #.   #.   #.  #.  #O@F|``s9cf6>';$(QJ$x|X,`X,,X#` @`` Ĉ ?O@F|``s9cf6>';$(QJ$x|X,`X,,X#` @`` Ĉ ?O@F|``s9cf6>';$(QJ$x|X,`X,,X#` @`` Ĉ ?O@F|``s9cf6>';$(QJ$x|X,`X,,X#` @`` Ĉ ?O@F|``s9cf6>';$(QJ$x|X,`X,,X#` @`` Ĉ ?O@F|``s9cf6>';$(QJ$x|X,`X,,X#` @`` Ĉ ?d=+6đ8d:? Y>BYp&D1@FеPR@ &J$$R[vID'4z%gIz@`en>`3~O2y̜d'8Lx^ 3d7i Cʷ¤@PgĒU`<# Xdp)3_Z  pl8i!b11bǤ䜓@`IƖN.@E?78 C, '3yל`ZO߻b ,._;,-p R`"/@'P2 . f(-u͠+  , i@Y)|,2 !&Y~.KdY,t A$MU)$BxAuG=B5V`#AMk~^2܂ZM_(ӐsITR̚W*„ސ u(4e0]D$D2E4p%QpwRp iMI|Rr@hc4&§wtejAY&a  `X ,<#0F"@\*@!Kh)'^ _w 5g+@o@BD*D>`E3M|& ( (O dPy QA^>@4o@0(PȒ~ ,@-(r@ a "Kh4 `RP!1k!ֵ:@$(pU|>BoR_+T$s$+w1հ>4;kKP [t>. n?k֖=°8[XMijEOq[,ֺ ]JJLz uzDT?\M*%uaM[pjTw$$-gWf'Ք@_C8A/]`Ul[㥠[D(Ț }\St ?S,[~ξJtRO*@WΌN0Ҿ?~NJ c1cf6>O2y̜d'8N2``!PBt4w'nѨ@9K2He, | E]*Q=$W `eož"j'Fl~g?mXs KM7B!*hsVB=&bWH) B7Hpr"8|x ,p H@5_v5&@8nƉ uDB4Yd@BhAnXdge$$$J'$䜒C'% o=)՝,"Oܮ`Μ`2J ,H5-yIpA_+M|ĤsZcR _An6𓔙$UʉAw PA$aгgST:cV8M#e#k={&Ht<[CZp kFmǷ9)zvHB,Bs ,`=06k `JPMnO9 2 !&Y~.KdY,2#BL,hF#_ U)f[ke]x"Cker3ŀ40 J !e.1B}K:00%t@t s [[ HBW1I*KG0U1+{TI@`b ߟDT,^mȒA|]>E!' O9Or?xXd.oPH@H,$2UP2HR?!-7.DxFN9/DLʰ˒>$I]` ,?@,Iv:(-e_46iz,~p !IYP*\˱ud*9Ÿ@>Hu>.&$ht0`,,YxG`0D" BAQ@H%1$@ҬJal+P4S J( AyWEDi2"K)FbJVLJR)S<8/H9AO][5N6 ۿnW" g'Yμc1'D\ b+[E R0<:tG(k]{(=4DTJ ?=l 2 ~L B? I_@@4JIP_9պ)@ʹ5D(G'Co13ts! /r`?4 iN |V`[`uO[58'kJkT՘M`J ֔֨5#u%%֔޸78@eF' Hk 6p(Qyu`0Bm@}CհxG/`\5ڠE G |. |kdRjG[rP :/m8^&PdaBH_ZiRB*yяj9s ` ac1'd'&L k3 + ] Ph "b^Rׄ1yu3W&@"F+̂Bz *dVDt!,KdY,J؜ RCDX @ PP&]~4r1*;H%BhiLHB\@p (h*o)o (`Np}1Ȳ/44h[M&80Jw BhU_qD9R}z KWc B@X x1e % JR@t abŗGxF#@ @$|#~`LRŋ/y Ѽ!D. (/xL  dfOGc@ :q(h#(  O@F|``s9cf6>';$(QJ$x|X,`X,,X#` @`` Ĉ ? O@F|``s9cf6>';$(QJ$x|X,`X,,X#` @`` Ĉ ? O@F|``s9cf6>';$(QJ$x|X,`X,,X#` @`` Ĉ ? O@F|``s9cf6>';$(QJ$x|X,`X,,X#` @`` Ĉ ?O@F|``s9cf6>';$(QJ$x|X,`X,,X#` @`` Ĉ ?O@F|``s9cf6>';$(QJ$x|X,`X,,X#` @`` Ĉ ? x8x8 b8/58QP@`8ffw.  #.  #.  #.  #.  #.  #.  #.  #.  #.  #.  #.  #.  #.  #.  #.  #.  #.  #.  #.  #.  #.  #.  #.  #.  #.   #.   #.   #.   #.   #.  #.  #.  #.  #.  #.  #.  #.  #.  #.  #.  #.   #.   #.   #.   #.   #.  #.  #.  #.  #.  #.  #.  #.  #.  #.  #.  #.   #.   #.   #.   #.   #.  #.  #.  #.  #.  #.  #.  #.  #@ce+@!x&Ο`d@$=le%MUAM0.ȈIpɅ%e @tooB- QĉWୄ3ýGS D&D j 'p ІP\` - h1``lx`4 anС( S٠ Ї*@Th( ѧx@L|{4 Gs4=)Q2@mP`&%HX @ IP!Ԁ%Ē(P8j @>EBPx =UH9 I.Bƨi WA Uf]1&,@ h(툀hA!8as$ 8] -K $hOOp9QT,HH%@HPo.  #.  #.   #.   #.   #.   #.   #.  #.  #O@F|``s9cf6>';$(QJ$x|X,`X,,X#` @`` Ĉ ?O@F|``s9cf6>';$(QJ$x|X,`X,,X#` @`` Ĉ ?O@F|``s9cf6>';$(QJ$x|X,`X,,X#` @`` Ĉ ?O@F|``s9cf6>';$(QJ$x|X,`X,,X#` @`` Ĉ ?O@F|``s9cf6>';$(QJ$x|X,`X,,X#` @`` Ĉ ?O@F|``s9cf6>';$(QJ$x|X,`X,,X#` @`` Ĉ ? &&2?@ `vV{1 Ab7A$‚==OH0IדE==](MQ`($6UW@bB ap?ԁ9! Q+XqX,E%$@ψ!@gNp|ԝ g!=OcCKzc`0܁9+I[whE] |@Pdˆ@.' R⑀0jSXB`BH @%08R{N(c@JE;jXT_B hɕPi3`"Enr2߳"Op\a!@3*gJ0p`as1'd'rNIP F!tu@n;a Gь& {A;!k4𥃠qq 1;*1@@S ut] P?6Xj{i=` H'eH`;+~L֓QF" gx!I ` z}q\eXx.rȡD]U_z5g]辑KPJ\*3 ~t q!ZǀwɂAuIBA.(b8;!CjZP> J%,'J?K(ڙ 0D B) H{(t5yR 6t,KdY,J(0 j@ aQ?< ٌ9=h~rQ_a|@ld `nSPM;B T@_!:e<K{k=8sk\P ,X[Ld,pܔ|j.7!FGC@ȆY"*Xwxב.'Rf"@ [Z1`mTۭePPʹ8SUUGudY¥c}ֵkW28ư Iaw)x_*N6mkK2Ҝ\:rڥw.(L']8c[cJg4E(,\CfqBSL+@AHβA+2lzV@'>At8rl?MbjYA=^$z9b_}@|Q$ @* Gv8Ȑ6Ð  ID*:(ӈ6A0 vxP 1M#(G+}Z?𹳙f I͜z37b)QƳWe̳=L7 m]Hv٦`\ł ̗ޓH) Ĉ<1VIF84 =>fsrBLz2bc@K;$,,]XQ@_`s03d̞d'8N2qs N1  !yK82I,2ryit>_I ",J"ЉCs4ݧH$>LP-/W?_Ȟ$J z'a 1 0g11' z5#= ]>FV5#l:zOsu>ybA>h3m[,Ē!>iuM@^&G]pTbnpLl})2U`[H}CoTп1EJ LX#L{( ~(.Ku=H@H%R oa>s)q ( q1,a'19'$䘒01ڿh( |.\pd[eԄH LGDE4rc1Faf#"FAَ}$H*8GfH;B8Ґ tXbn,t>LH|Adpp-ea͟ ѵ;kP;Se)8c0 ĖC4M]gZ;h Q88vyҔEnAE4) ͎"jb-銱X: [jiNZV5sSZK(Vl3^ TP-"]!@)j`pۊe2q@B(X]J(g|$"h  QJN"</Hb!,L/"ֺzk#MA˜c]]0tC,].K%dY*#@f)% )Vyo̧4|T7UۈFVN_Ȉ_d P`B Z^`iB' 8M|4sP0rBj@< ChQ1@ 44h[造H,a#DFhGb<"JSiRFﯥn1&P (0E Y!o~{D)~ѤDbD4dqg@h+hӼ{aGi;!qDp)*CHJ Qq&G,tB-QI'*~ /RzK+[iʽf:SKW\r>oDP׭HU1,@ $>޾CI N?M0; 4=@UH E$j 3fW͏@ 'THHG9*Z+wGp" h%Łз_8]>hkk0 8%ٷg%`(YA*Pr7:ŋ/0F"@@q0BlE&W1t"˻|NpEV$_9X-' s2V*3 I8?+F1<VF 9y 'g-7C2$D`@܄cz_#r I Ѵ 0H4KFJAY(P<ՕV`Mf-C#wEH}+~3$sj G_NiIDg}x'aAi@! X>QlI1A) =.I#1=J$z|5$.!@6ܨTC#%LP2O*6|Ak^¸+kn$n)$|a ,K8s3Pq4cN4~[@/tY,K%D "hke< plMn*ЪRaFih8,A=7Gͮ_iF'u4:fQ@)a1b_Ϗ0$+ C:#j 4F~~!H Xtx P"I)%M QlQ3 ?SXZPuf/עBPxQ`B.#Z_vJdn^%X*ÞAOX1}A_R#b05 } !Ht"/T 4vLi`v(\3 FCUL({JQ)\@)t+ܝw`, abŗGxF#@ @3 B&lDÊ+fS'3\-gePlŽ@W z C$Q>}S(WDuB W$H}\|`F a0#_e06nyAF@D/O-_7[3Jv(OzgԎV1@ A)mtGES2y% UAM2L0!P SRޟP弟Ob]VH{-Yj)Ж$]+;Fhr}03XSb|0j.F(X+f\c3f& b8>Gzd{f t.H``͜ 4>&P f g Ad%9Gł:?4ouǃ"0e$SV0U0dPa10c01l}O2y̜d'8N2`x 5a]6jWVG 0#]i\h46@h^u3_Jϲ!:> 0;GSa>0.- ZE .[Q/9 G3z011T|O=@$(PL@a؍?`(pI  A N'E$F|I _ذR(F  j$cD?D541PP_W%5w0{@x !fz_h R1ve0:읅$HF% `&HA4cIj٪dqkU5cA PȊRlk|Gۀ(*kQm 9=J݀ X!t(Sӈ!^` 8A n}l0Iaii/gxPT`(Uay* ow~`abŗG` D"@T#&!&4" Zv0RDA!!A+'@(իB҄O:E1|0fZ/Ni<-x}l(,1HQSo0';$(QJ$x|X,`X,,X#` @`` Ĉ ? O@F|``s9cf6>';$(QJ$x|X,`X,,X#` @`` Ĉ ? O@F|``s9cf6>';$(QJ$x|X,`X,,X#` @`` Ĉ ? O@F|``s9cf6>';$(QJ$x|X,`X,,X#` @`` Ĉ ?O@F|``s9cf6>';$(QJ$x|X,`X,,X#` @`` Ĉ ?O@F|``s9cf6>';$(QJ$x|X,`X,,X#` @`` Ĉ ? nn X0+QP@ffwSFEd 2 DDHW´VR*EH"@ Ì `1cll}`L{w gx3@gn,O @( ABa0H$ $8j@d@2 ehpǹ@xq,@hCF5>>:tӧN+,``, Ŗ_1j @ A(J$SFEd 2 DDHW´VR*EH"@ Ì `1cll}`L{w gx3@gn,O @( ABa0H$ $8j@d@2 ehpǹ@xq,@hCF5>>:tӧN+,``, Ŗ_1j @ A(J$SFEd 2 DDHW´VR*EH"@ Ì `1cll}`L{w gx3@gn,O @( ABa0H$ $8j@d@2 ehpǹ@xq,@hCF5>>:tӧN+,``, Ŗ_1j @ A(J$SFEd 2 DDHW´VR*EH"@ Ì `1cll}`L{w gx3@gn,O @( ABa0H$ $8j@d@2 ehpǹ@xq,@hCF5>>:tӧN+,``, Ŗ_1j @ A(J$SFEd 2 DDHW´VR*EH"@ Ì `1cll}`L{w gx3@gn,O @( ABa0H$ $8j@d@2 ehpǹ@xq,@hCF5>>:tӧN+,``, Ŗ_1j @ A(J$SFEd 2 DDHW´VR*EH"@ Ì `1cll}`L{w gx3@gn,O @( ABa0H$ $8j@d@2 ehpǹ@xq,@hCF5>>:tӧN+,``, Ŗ_1j @ A(J$SFEd 2 DDHW´VR*EH"@ Ì `1cll}`L{w gx3@gn,O @( ABa0H$ $8j@d@2 ehpǹ@xq,@hCF5>>:tӧN+,``, Ŗ_1j @ A(J$SFEd 2 DDHW´VR*EH"@ Ì `1cll}`L{w gx3@gn,O @( ABa0H$ $8j@d@2 ehpǹ@xq,@hCF5>>:tӧN+,``, Ŗ_1j @ A(J$SFEd 2 DDHW´VR*EH"@ Ì `1cll}`L{w gx3@gn,O @( ABa0H$ $8j@d@2 ehpǹ@xq,@hCF5>>:tӧN+,``, Ŗ_1j @ A(J$ SFEd 2 DDHW´VR*EH"@ Ì `1cll}`L{w gx3@gn,O @( ABa0H$ $8j@d@2 ehpǹ@xq,@hCF5>>:tӧN+,``, Ŗ_1j @ A(J$ SFEd 2 DDHW´VR*EH"@ Ì `1cll}`L{w gx3@gn,O @( ABa0H$ $8j@d@2 ehpǹ@xq,@hCF5>>:tӧN+,``, Ŗ_1j @ A(J$ SFEd 2 DDHW´VR*EH"@ Ì `1cll}`L{w gx3@gn,O @( ABa0H$ $8j@d@2 ehpǹ@xq,@hCF5>>:tӧN+,``, Ŗ_1j @ A(J$ SFEd 2 DDHW´VR*EH"@ Ì `1cll}`L{w gx3@gn,O @( ABa0H$ $8j@d@2 ehpǹ@xq,@hCF5>>:tӧN+,``, Ŗ_1j @ A(J$ SFEd 2 DDHW´VR*EH"@ Ì `1cll}`L{w gx3@gn,O @( ABa0H$ $8j@d@2 ehpǹ@xq,@hCF5>>:tӧN+,``, Ŗ_1j @ A(J$SFEd 2 DDHW´VR*EH"@ Ì `1cll}`L{w gx3@gn,O @( ABa0H$ $8j@d@2 ehpǹ@xq,@hCF5>>:tӧN+,``, Ŗ_1j @ A(J$SFEd 2 DDHW´VR*EH"@ Ì `1cll}`L{w gx3@gn,O @( ABa0H$ $8j@d@2 ehpǹ@xq,@hCF5>>:tӧN+,``, Ŗ_1j @ A(J$  000>0b a$01a$̂0QP@ g0ffw`MTD2@DD"""G¾VR*EHВ%J( @ A(J%-a"I$R d !//y¼B>D @P(( сC|i " ߰moFc۾ky$Ⴤ*p>`kB* 'm]spd( ݈@ o@q&GFheX@ ~4( 5@*&5>L&p^؀(b ' 8} sP yOhD"#_ Z+EH"TR)T t#)S#q.d]}BZp4 $ @?_nşTApI/X|`<`gGxc0B@+P@4j*bZ#l``E@íI wBȠ1 ^12hRQ)/ضŦ-1e$H$H֣0/ho>8RW$pT#1A\+ a#&9VOd n`% S;1O6b-RR.Lj9^r)P=}`?+U\o3 D~/.8$pm(T_X0HtD,ȿ*+qPee_!BDUH[!LQB\ucҀ5qAA"]5 qd\\)CVENI"` )0L& A 8eY@DFOy0q/  5.M`8@vEx@OF*HT@,tkFOnQ@@d.@)GB)W/T'!C0X=R$~g$cQBuA I"fSc]BrV Ie!p)J(XJ(6?4 K;-{ӝvplrQ#CAH bR_miR*kI4(!HR}kBD(?GLER5/NiSRAFCF5>:tӧN:tI^PɡQ4h 5D*8pM؏ $bSC Ĥ$0m 08-l -;˘/J)@h3-N\I9'$$HB @o$K),zaBj!8`Õj ! _3n]T^.|C(c0.<0:"!L"|ԭc8V36,ApP~$4tk_ ⚹Ɣ "j ҈sİ{%@|Vv?V^aVW?5GEÈ$ 2sZ'i@{{sFSYQte @_2t0ZMg7Z &pb(% q'wg/!2ωOasY"0~Q%q }ش)Bܰdjͩ] V,m!CHtԭ͟u#6r,ns,*㌇ip(@H B!>VR*EH"TUCb8P~E 2-4PH9t8/M!y7@1jxU#`_$@  awhAFAlZelZ%f4BBMKo7sFhd` R) ?983spXQcY#K. n81/2,0,dd _gC9H It VfbXF)XH7_x$1ؽcoDF:=%ed`ѣMoώ:tӧN742@6Tݚ`jLB1`KB F  (M?{/5)C rߒYb2[c@XA"`,ol[#2܂>{.Qp`0{؉-u(&xVBԮ`( tZʂ 8uN`ih -D r+CI rbR~Ah,"9furb*M%8 F~1E V%?(y>2a;o=D|Wp㣫( =OijPD$#Z+Eh"TR*EHP&Ѐ "\dP&!^\9&X|Y1/"<QJ( C_ )~\c $_"ȿA ^ ă*gPeb^diO3"^.…O2MNnJ0'H$I`G'"Whu+ߡ4zK^a5?su C0fVi<2@ sNBA<@ o!EB-mlZb^DI$Y[=D?ک}RU^9s;-w}^X$ՏDQ Q#MQCiGkT AA<@\չTv2\"W/9y˯p 'PtjƯ[J|c>RcAܝtшDB#k [Ur (1vS,Q:fCc@@p,(f-P)LC҄+x[ ־Z!Zd$*X)&=4p cLɢmrD=:bRzIF8ƍx!>:e{a t25Cj WǩPCSG̠5 )a0H$ A hH"t\P r@!*E ׹amRI} ݳ#0` @0 \wJ= wUWyBHeOj5@ !NX1*:D?#($X8x@u,'ADe pǂ.Z\Eĺ~0 ok`i,`G \(ɨ( C 4E`CU!+!] pm#3d3 3|Nx\zP) ` IT Z"z зKW#82!H :LcHZ_[d:b%?.!,,X[N:tӦ! BJ :A-‚,@(4iEg[-6}ܺaSag)W.9mIn<*NZA26?/q2[63^&,zO䜓bJ$HB; H*}vkW 4-LULPQr^p6AR 2zUڕWѱ|1M5`*uH`a }hTL)`$Apf] 7 ?3PP05(0]V ڍBBL[[;ؑ| Z.RA%}/G@+ZI$ԨC9=2X5S6@ 0z}y36b89Mc ? >D2#~HAu3r\`cC>NĕܰL`PĤ`NgV_JAAf+@G`ò c @HDDhTR*EH"@03N%V_ ,2x0OPim5\w/2 .ȿ\?Y`WJ{l `N{B<\1@Tr}]<L“I!*!/|V]8w̷R_=p*ԤY!PEPT*+bضŦ-1e$H$H:l=z Y@P >*Q(PI8Q!E HjQ<` 81Bt"ڐ-zWy9y^rB+cܬCXE-6 xf &Z}.i?zwی#NN>Ub@ k 'H}-2i蔳M;:{)luށwLJq&]~~0PC;-ƍij =ݎZ#FGx2b)4JiMW &ɐ_6 4ӧN:tx6"*hH@44h6=O## dZJPc bdR Z n( L. f3pIWɋ9'$䜒D(P( RR~ zc)%I t[-ElF\K Q3Z3 ngCp 8<.^Ȏ#S TIvɵhȠ*D7p"$$~7#WHDs_Yջ-R0[i -jmЮH50Z0'ЛB`hV\al^ZATUSSsXڂkX-S6@N)ikPymf !v`VZ( 3h1!@` p ֳTo,pF$H +1^5!P_r9MťI\ A-6+,bP,Js@-&YE dD"#Z+EH"TR*EHP( @"9!chi61[PDßg!LaMISi k]?p+(TQt70Ox bc  !%i$s/r_SvYŸ+ L[:Bp b,HP)ƨBp 2B5cg];h̨hCYgJ\1ޮ*zGpd&='4ź J%%[bŦ,$Im?,.$GC5 r0Pȣ!Cď"MJlA~gz|ZE 9& 02~[8aڇ6i^r󗜺(AE^E˾s9aW @BY]mDG)k찎n&=8.2XM;tC4[Aia;d&r>=Xn(S/åku3X%e_ dJf/3$4 AEDX׍@,F'8U<j2j^Xžg K@ (O A H$ H5!eB"ΊPQo QY n, *R@j9twBK(@ƅnDOnF6F,d՞ !Gb TDh/ދͰ94 !X$n@eLFv:{=K16"Ơ؇q+C8{F$;$?}.3TJ5]SfCSjh[3zzS H X! zpu E5L=c@*t)ݭ]s_ LC!ύ|$@d_*q`M6eN㧑%  4ӧN:tx'J ¢h bkA'.  geX` bnӘ `4Fn"D^{Nc&@.Nqs" t&@@ТxB7rn-aN`Id G~R) u,Zݍ|X=v0\].+k~||tӧN:tRd, *P( QK -c"l</Phze2Ff=NrCtZg-:Phg lAȽ1fgOf|GSVQŇ^R0oEbOZ+rNI1%r$PBPc I|o RX0Wh0 %ڷ@%WO@q%(wm(ɗ*?g+Mw] 18 jg4h2O20!  -\[#~z+>mWX ^~" h ?)&Q}S0u#:J4a O |Ә- C[ۅιDW?[(qfaep%М JN[`%(͐k J SkFGKĹ8(;ݙ(o RCgq7"k0G䁑?nYqj/.`FilX)LL06{j*N=V?EAf @z`Aah |8`D|1`VUӄP&R"}&XB@H$DhTR*EH"@F! ɘR#9Y!!O!>D7WT -E 0bYDt9YʽBO!%MB@"VR*EH"R_ADDQ (AA {qҭ@S^<,5JKml[b $HI$^*2`! @kf@ P&e+.D\$- 0 F.. C|`((Ӣ_:*ՀРPPE/x& A H$ C D$:b@A@E ( i?n C@ >@X }1?{8hBo s30@ K04 I4CF5>>>:tӧN7!4΃< &*$ u!$~rNI1$$HB^,-݆,_382@| I5 \Zm@o\ __|? /@DD"""G¾ @:\u msjj BQ(pH)-=fD>Ĝ[4!vLȐt !J{3SA4 |__?|/ P PPE/x?#~O/; A!"D;cQ!$o$rfYLۃdFܚZLl< !t]O]>t.E ѣMoϏĀ2:@d=!H0d#F@#pC,@9ՀkaLxj|@oсJsC#I,P_g(-C #` 00 N 2̛QP@`ffw,  ,  ,  ,  ,  ,  ,  ,  ,  ,   ,   ,   ,   ,   ,  ,  ,  ,  ,  ,  ,  ,  ,  ,  ,  ,   ,   ,   ,   ,   ,  ,  ,  ,  ,  ,  ,  ,  ,  ,  ,  ,   ,   ,   ,   ,   ,  ,  ,  ,  ,  ,  ,  ,  ,  ,  ,  ,   ,   ,   ,   ,   ,  ,  ,  ,  ,  ,  ,  ,  ,  ,  ,  ,   ,   ,   ,   ,   ,  ,  ,  ,  ,  ,  ,  ,  ,  ,  ,  ,   ,   ,   ,   ,   ,  ,  @ 3̛QP@`ffw,  ,  ,  ,  ,  ,  ,  ,  ,  ,   ,   ,   ,   ,   ,  ,  ,  ,  ,  ,  ,  ,  ,  ,  ,  ,   ,   ,   ,   ,   ,  ,  ,  ,  ,  ,  ,  ,  ,  ,  ,  ,   ,   ,   ,   ,   ,  ,  ,  ,  ,  ,  ,  ,  ,  ,  ,  ,   ,   ,   ,   ,   ,  ,  ,  ,  ,  ,  ,  ,  ,  ,  ,  ,   ,   ,   ,   ,   ,  ,  ,  ,  ,  ,  ,  ,  ,  ,  ,  ,   ,   ,   ,   ,   ,  ,  P 4QP@ffw,  ,  ,  ,  ,  ,  ,  ,  ,  ,   ,   ,   ,   ,   ,  ,  PFreeRDP-1.0.2/server/test/server.crt000066400000000000000000000020051207112532300172370ustar00rootroot00000000000000-----BEGIN CERTIFICATE----- MIICyzCCAbOgAwIBAgIJANbqtAWwlQZuMA0GCSqGSIb3DQEBBQUAMBIxEDAOBgNV BAMTB0ZyZWVSRFAwHhcNMDkxMDI5MDA0MTQ5WhcNMDkxMTI4MDA0MTQ5WjASMRAw DgYDVQQDEwdGcmVlUkRQMIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEA q7mxFgRbS2FYJZX7BzpNd4T/n4nEVDBY6YaObLjGpaB1TptzXTcmfDrDslTGwcEY hTFAC4ZvY6yOURExqbph4LSgvkoa6J722RjVPfshGa4mlh2SXvTiaV26VPPxddGb o6fbs2u029lbtBlpIVbhx5RN9vstNkll26oSZ6wfEdBNHQJLd2SU4ItWHj8zjz1f eGxjgChHihUlwcBYKDJsKFkzHZmLrMgB37KsGlXi/WV+eEsjgvz4yP7I3TL8+GsN MjV8fRGVEKTbKSmgunO67d5u+IaqUQb0Ad1ha1jzDQ+a6hdymrulJSIhoOVfKkwi ptTe43FgwxVRIygJP9HjHQIDAQABoyQwIjATBgNVHSUEDDAKBggrBgEFBQcDATAL BgNVHQ8EBAMCBDAwDQYJKoZIhvcNAQEFBQADggEBAIOdEDhOX2kbl02znltd9hCr nV4kRPKm979RKwBNkrEuwYSlcsjAHg5MZ5itH3wFOUo2s5pjt7/vMOAg+6rOBbIa nqr22/gKBtOmuaJLG1yjxDC2vfez7f3B26pKgxa/krM8oxiFdT9n8QbdxdkN7/D9 3RLU/aCfgrMzXxRus7eq3kR00jnSs6ggnAfE1E9gric3vFgr1wCzdcriRXmXDfUb hRq+4VG+ZWk16TwCofV5GVU39XWCv5HNO2swAdjkNXgI5e3tQbV3wWLZLqqYzBco iWulAXtoCGmE81+u1Ms7hLLzpXitLZSGPu1r+sDdkKPLCmOvkAaljDQ4nBz7fIA= -----END CERTIFICATE----- FreeRDP-1.0.2/server/test/server.key000066400000000000000000000032131207112532300172410ustar00rootroot00000000000000-----BEGIN RSA PRIVATE KEY----- MIIEogIBAAKCAQEAq7mxFgRbS2FYJZX7BzpNd4T/n4nEVDBY6YaObLjGpaB1Tptz XTcmfDrDslTGwcEYhTFAC4ZvY6yOURExqbph4LSgvkoa6J722RjVPfshGa4mlh2S XvTiaV26VPPxddGbo6fbs2u029lbtBlpIVbhx5RN9vstNkll26oSZ6wfEdBNHQJL d2SU4ItWHj8zjz1feGxjgChHihUlwcBYKDJsKFkzHZmLrMgB37KsGlXi/WV+eEsj gvz4yP7I3TL8+GsNMjV8fRGVEKTbKSmgunO67d5u+IaqUQb0Ad1ha1jzDQ+a6hdy mrulJSIhoOVfKkwiptTe43FgwxVRIygJP9HjHQIDAQABAoIBAAVv5K54xtc1JtBR 1lfdPbSqDlnjx8aOnVIPg5TnqMp3sR8jBt0NsPc/+RA9ZOmfjoIxFAEJaZ9zSDJC 5BqmnxC5R1mfCQkSd2haQ+4pdFvWyrv4Bblh8YU6hXrJGn0LfO0KlIcywtAvKpsi LtTyZkWmaW2HeF/+pO32jYygw38R1wd8Tl6GwjOXwTF6lFACJXOT4YAzcfp3FKSB AiKBIGuMzozoSND7KPFNRrhGhNumJpdS5A8Fb8D2c/ZMv6Cq5IbwOgTfKun+Bz+s mFbnzeb1uWRqQbsVXOBBW/zHfuG3SU5qeZsaAyuu4DTy+LE1oAHF9uhBSHuT5C6i vCJ8A8ECgYEA1iaOmiEJYBrs25iAc4SjCKqhY0mwR3wtu3I06vmgUoML5fhPMv36 SvYQIqDyNw3p7TE6mZtw9+G+kK3PqhuJhogwSwg0a6o51RdKnhXH3/68oNWtKCLC 1AmR8q/Gd3FwAR3b49CuOIZ9uOiJrc/ejzKdFEJTDR1/TX1frWfZznECgYEAzUiz XxFf7YrGel7JgmfRD2eZRYngOoteFlg5Tee42UjeAY2Pt2aiDLk+2TqQEdI9+Xg7 LcFdBqcSNd8bh33xSzgNthIkX+lTDzx0SmKGfyxfFBJcY8nzsLvvnNt3YeuMeaJQ CPszwoZ0jcD46jTCjbrKhaLyEWmUkDp1O71NTW0CgYAXKF49Xpsz8FVyvcAOPeaf dkwzf3F3mX8ciRId4taqdY9g1AREgGCDoK5IAF2RBIkqZCtxFvUVaS0BWjpdq9Ko YKvQQVfh2KueVoF0LOjLWTGutsydzXyCD3Lf6pAstHCnPkJcFWHxrOGFkGfrCtKH a7K+0RlIDsuIZqllCBjukQKBgA31+MTpYJW+D1t5IMkumEgs6n6RLt+sZLyuSU9k B+03CGogn3qAj1rAKmcJlYywuKhDpfqpoNL3/8QMJUokpYlRCZWtTC39pzltCheY 9b6mXNz3lrLupBUL4vLO9iKBq28GO90wgEelbz3ItuTuq6CJ6IYIG+BVRtY8M4bZ i+1NAoGANXZjYnJYDnh8Je9SDxDSc5byzK7ddkQoId64RCIfNHqNKH63P81vjgnH YBIPtagY75ZVVNxujCF7m8Rety+d8tEFwfQKDin2EVI7PD2rOJra385/izp7HuBR vqxvLzG9Xv3cNOU2l7PttVw4Pa2i5E37atKi3V3Zp2kMW+KaKPQ= -----END RSA PRIVATE KEY----- FreeRDP-1.0.2/server/test/test_icon.ppm000066400000000000000000000525701207112532300177400ustar00rootroot00000000000000P3 # CREATOR: GIMP PNM Filter Version 1.1 29 64 255 160 160 160 160 160 160 160 160 160 160 160 160 160 160 160 160 160 160 160 160 160 160 160 160 159 159 160 135 154 160 85 141 160 82 141 160 159 159 160 160 160 160 160 160 160 160 160 160 160 160 160 160 160 160 160 160 160 160 160 160 160 160 160 160 160 160 160 160 160 160 160 160 160 160 160 160 160 160 160 160 160 160 160 160 160 160 160 160 160 160 160 160 160 160 160 160 160 160 160 160 160 160 160 160 160 160 160 160 160 160 160 112 148 160 74 139 160 75 140 161 75 140 161 155 158 160 160 160 160 160 160 160 160 160 160 160 160 160 160 160 160 160 160 160 160 160 160 160 160 160 160 160 160 160 160 160 160 160 160 160 160 160 160 160 160 160 160 160 160 160 160 160 160 160 160 160 160 160 160 160 160 160 160 160 160 160 160 160 160 160 160 160 160 160 160 114 148 160 74 139 160 74 139 160 75 140 161 91 143 160 160 160 160 160 160 160 160 160 160 160 160 160 160 160 160 160 160 160 160 160 160 160 160 160 160 160 160 160 160 160 160 160 160 160 160 160 160 160 160 160 160 160 160 160 160 160 160 160 160 160 160 160 160 160 160 160 160 160 160 160 160 160 160 160 160 160 160 160 160 136 154 160 76 140 160 74 139 160 74 139 160 75 140 161 137 154 160 160 160 160 160 160 160 160 160 160 160 160 160 160 160 160 160 160 160 160 160 160 160 160 160 160 160 160 160 160 160 160 160 160 160 160 160 160 160 160 160 160 160 160 160 160 160 160 160 160 160 160 160 160 160 160 160 160 160 160 160 160 160 160 160 160 160 152 158 160 79 141 160 75 140 161 74 139 160 74 139 160 83 141 160 159 159 160 160 160 160 160 160 160 160 160 160 160 160 160 160 160 160 160 160 160 160 160 160 160 160 160 160 160 160 160 160 160 160 160 160 160 160 160 160 160 160 160 160 160 160 160 160 160 160 160 160 160 160 160 160 160 160 160 160 160 160 160 160 160 160 160 160 160 90 143 160 75 140 161 74 139 160 75 140 161 75 140 161 105 147 160 159 159 160 160 160 160 160 160 160 160 160 160 160 160 160 160 160 160 160 160 160 160 160 160 160 160 160 160 160 160 160 160 160 160 160 160 160 160 160 160 160 160 160 160 160 160 160 160 160 160 160 160 160 160 160 160 160 160 160 160 160 160 160 160 160 160 125 151 160 74 139 160 74 139 160 75 140 161 75 140 161 74 139 160 111 154 167 158 160 160 160 160 160 160 160 160 160 160 160 160 160 160 160 160 160 160 160 160 160 160 160 160 160 160 160 160 160 160 160 160 160 160 160 160 160 160 160 160 160 160 160 160 160 160 160 160 160 160 160 160 160 160 160 160 160 160 160 160 160 160 154 158 160 88 143 160 75 140 161 75 140 161 75 140 161 75 140 161 74 138 160 99 170 189 134 171 180 160 160 160 160 160 160 160 160 160 160 160 160 160 160 160 160 160 160 160 160 160 160 160 160 160 160 160 160 160 160 160 160 160 160 160 160 160 160 160 160 160 160 160 160 160 160 160 160 160 160 160 160 160 160 160 160 160 160 160 160 126 151 160 74 139 160 74 139 160 75 140 161 75 140 161 75 140 161 73 137 158 63 124 147 108 181 198 152 163 165 160 160 160 160 160 160 160 160 160 160 160 160 160 160 160 160 160 160 160 160 160 160 160 160 160 160 160 160 160 160 160 160 160 160 160 160 160 160 160 160 160 160 160 160 160 160 160 160 160 160 160 160 160 160 160 160 160 80 141 160 75 140 161 75 140 161 75 140 161 75 140 161 75 140 161 73 138 159 21 72 99 78 143 164 126 180 192 159 160 160 160 160 160 160 160 160 160 160 160 160 160 160 160 160 160 160 160 160 160 160 160 160 160 160 160 160 160 160 160 160 160 160 160 160 160 160 160 160 160 160 160 160 160 160 160 160 160 160 160 160 160 129 152 160 74 139 160 75 140 160 75 140 161 75 140 161 75 140 161 75 140 161 73 138 159 25 77 104 12 60 88 105 176 194 145 167 172 160 160 160 160 160 160 160 160 160 160 160 160 160 160 160 160 160 160 160 160 160 160 160 160 160 160 160 160 160 160 160 160 160 160 160 160 160 160 160 160 160 160 160 160 160 160 160 160 160 160 160 98 145 160 75 140 161 75 140 161 75 140 161 75 140 161 75 140 161 75 140 161 74 139 160 27 80 106 6 53 82 57 117 140 121 182 195 160 160 160 160 160 160 160 160 160 160 160 160 160 160 160 160 160 160 160 160 160 160 160 160 160 160 160 160 160 160 160 160 160 160 160 160 160 160 160 160 160 160 160 160 160 160 160 160 160 160 160 83 141 160 74 139 160 75 140 161 75 140 161 75 140 161 75 140 161 75 140 161 76 141 162 30 83 109 6 53 82 28 81 107 108 180 197 154 162 164 160 160 160 160 160 160 160 160 160 160 160 160 160 160 160 160 160 160 160 160 160 160 160 160 160 160 160 160 160 160 160 160 160 160 160 160 160 160 160 160 160 160 160 160 160 155 158 160 80 140 160 74 139 160 75 140 161 75 140 161 74 139 160 74 138 159 73 138 159 75 140 161 37 92 118 2 48 78 19 69 96 100 171 189 147 165 170 160 160 160 160 160 160 160 160 160 160 160 160 160 160 160 160 160 160 160 160 160 160 160 160 160 160 160 160 160 160 160 160 160 160 160 160 160 160 160 160 160 160 160 160 160 149 157 160 79 140 160 74 139 160 74 139 160 76 142 163 82 149 169 96 165 184 106 178 196 111 185 202 114 188 205 114 188 205 97 168 186 107 179 196 150 164 168 160 160 160 160 160 160 160 160 160 160 160 160 160 160 160 160 160 160 160 160 160 160 160 160 160 160 160 160 160 160 160 160 160 160 160 160 160 160 160 160 160 160 160 160 160 146 156 160 80 141 160 74 139 160 86 154 173 102 173 191 111 184 200 111 184 201 110 183 200 110 183 200 109 182 199 110 183 200 111 184 201 110 183 200 113 179 195 138 170 177 160 160 160 160 160 160 160 160 160 160 160 160 160 160 160 160 160 160 160 160 160 160 160 160 160 160 160 160 160 160 160 160 160 160 160 160 160 160 160 160 160 160 146 156 160 77 139 159 93 162 182 110 183 200 110 183 200 110 183 200 109 182 199 110 183 200 110 183 200 110 183 200 110 183 200 110 183 200 110 182 199 109 182 199 110 183 200 138 169 177 160 160 160 160 160 160 160 160 160 160 160 160 160 160 160 160 160 160 160 160 160 160 160 160 160 160 160 160 160 160 160 160 160 160 160 160 160 160 160 146 156 159 99 165 182 112 185 202 109 182 199 110 183 200 110 183 200 110 183 200 110 183 200 110 183 200 110 183 200 110 183 200 110 183 200 110 183 200 110 183 200 109 182 199 110 183 200 150 165 168 160 160 160 160 160 160 160 160 160 160 160 160 160 160 160 160 160 160 160 160 160 160 160 160 160 160 160 160 160 160 160 160 160 160 160 160 138 168 175 110 182 199 109 182 199 110 183 200 110 183 200 110 183 200 110 183 200 110 183 200 110 183 200 110 183 200 110 183 200 110 183 200 110 183 200 110 183 200 110 182 199 107 180 197 107 168 183 160 160 160 160 160 160 160 160 160 160 160 160 160 160 160 160 160 160 160 160 160 160 160 160 160 160 160 160 160 160 160 160 160 156 161 162 117 179 194 109 182 199 109 182 199 110 183 200 109 182 199 109 182 199 109 182 199 109 182 199 109 182 199 110 183 200 109 182 199 110 183 200 110 183 200 110 183 200 111 185 201 83 149 168 7 52 81 101 119 130 160 160 160 160 160 160 160 160 160 160 160 160 160 160 160 160 160 160 160 160 160 160 160 160 160 160 160 160 160 160 144 167 172 110 183 200 110 182 199 110 183 200 109 182 199 61 125 148 47 91 116 58 95 118 43 88 112 64 128 151 108 181 198 110 183 200 110 183 200 110 183 200 110 183 200 109 182 199 112 185 202 98 168 186 125 165 175 160 160 160 160 160 160 160 160 160 160 160 160 160 160 160 160 160 160 160 160 160 160 160 160 160 160 160 160 160 160 126 175 187 109 182 199 110 182 199 111 184 201 55 119 143 108 136 153 230 234 237 186 198 205 234 233 221 51 89 113 68 133 155 109 182 199 110 183 200 110 183 200 110 183 200 109 182 199 109 182 199 110 183 200 123 176 188 159 160 160 160 160 160 160 160 160 160 160 160 160 160 160 160 160 160 160 160 160 160 160 160 160 160 160 160 160 160 114 179 195 110 183 200 110 183 200 103 175 193 66 114 136 247 248 249 240 243 244 57 95 118 22 66 93 40 80 106 64 113 135 108 181 198 110 183 200 110 183 200 110 183 200 110 183 200 110 183 200 110 183 200 119 177 191 156 161 162 160 160 160 160 160 160 160 160 160 160 160 160 160 160 160 160 160 160 160 160 160 160 160 160 160 160 160 110 182 199 110 183 200 110 183 200 100 172 190 106 143 161 249 250 250 251 252 252 132 155 170 51 89 113 145 165 178 79 121 142 108 181 198 110 183 200 109 182 199 110 184 200 113 187 203 103 175 193 104 177 194 117 180 195 154 162 164 160 160 160 160 160 160 160 160 160 160 160 160 160 160 160 160 160 160 160 160 160 160 160 160 160 160 160 112 180 196 110 183 200 110 183 200 107 180 197 74 124 145 250 251 251 254 254 254 250 251 251 238 241 243 220 226 230 67 122 144 109 182 199 110 183 200 110 183 200 101 171 189 38 91 116 154 176 179 94 128 141 99 165 182 153 164 166 160 160 160 160 160 160 160 160 160 160 160 160 160 160 160 160 160 160 160 160 160 160 160 160 160 160 160 120 177 190 109 182 199 110 183 200 110 184 200 81 152 172 113 144 161 242 244 245 242 244 245 235 239 241 92 129 148 87 157 177 110 183 200 110 183 200 115 189 206 37 91 116 8 55 84 0 46 77 55 117 140 118 186 201 152 163 165 160 160 160 160 160 160 160 160 160 160 160 160 160 160 160 160 160 160 160 160 160 160 160 160 160 160 160 134 171 180 109 182 199 109 181 198 109 182 199 113 187 203 88 159 179 83 140 160 105 152 169 76 134 155 88 159 179 112 185 202 109 182 199 110 183 200 110 183 200 109 182 199 81 147 167 61 122 144 113 187 204 113 179 195 153 163 165 160 160 160 160 160 160 160 160 160 160 160 160 160 160 160 160 160 160 160 160 160 160 160 160 160 160 160 152 163 166 110 183 200 109 182 199 110 183 200 109 182 199 110 183 200 109 182 199 108 180 198 109 183 200 110 183 200 109 182 199 109 182 199 110 183 200 109 182 199 110 183 200 106 178 195 74 138 159 110 183 200 117 178 192 155 162 163 160 160 160 160 160 160 160 160 160 160 160 160 160 160 160 160 160 160 160 160 160 160 160 160 160 160 160 157 161 161 121 177 190 109 182 199 110 183 200 110 183 200 110 183 200 110 183 200 110 183 200 110 183 200 110 183 200 110 183 200 110 183 200 110 183 200 110 183 200 110 183 200 95 164 183 77 142 163 110 183 200 123 175 188 158 160 160 160 160 160 160 160 160 160 160 160 160 160 160 160 160 160 160 160 160 160 160 160 160 160 160 160 160 160 160 160 160 139 169 176 110 182 199 110 182 199 110 183 200 110 183 200 110 183 200 110 183 200 110 183 200 110 183 200 110 183 200 110 183 200 110 183 200 109 182 199 110 183 200 70 133 154 103 173 191 109 181 198 136 171 179 160 160 160 160 160 160 160 160 160 160 160 160 160 160 160 160 160 160 160 160 160 160 160 160 160 160 160 160 160 160 160 160 160 159 160 160 115 179 194 110 183 200 110 183 200 110 183 200 110 183 200 110 183 200 110 183 200 110 183 200 110 183 200 110 183 200 110 183 200 110 183 200 108 181 198 95 164 183 110 183 200 110 182 199 156 161 162 160 160 160 160 160 160 160 160 160 160 160 160 160 160 160 160 160 160 160 160 160 160 160 160 160 160 160 160 160 160 160 160 160 160 160 160 149 164 168 109 182 199 109 182 199 110 182 199 110 183 200 110 183 200 110 183 200 110 183 200 110 183 200 110 183 200 110 183 200 109 182 199 110 183 200 111 183 200 109 182 199 136 170 177 160 160 160 160 160 160 160 160 160 160 160 160 160 160 160 160 160 160 160 160 160 160 160 160 160 160 160 160 160 160 160 160 160 160 160 160 160 160 160 160 160 160 137 169 177 110 183 200 109 181 198 110 183 200 110 183 200 110 183 200 110 183 200 110 183 200 110 183 200 110 183 200 110 183 200 110 183 200 110 183 200 119 178 192 159 160 160 160 160 160 160 160 160 160 160 160 160 160 160 160 160 160 160 160 160 160 160 160 160 160 160 160 160 160 160 160 160 160 160 160 160 160 160 160 160 160 160 160 160 157 161 162 120 176 189 110 183 200 110 183 200 110 183 200 110 183 200 110 183 200 110 183 200 110 183 200 110 183 200 110 183 200 110 183 200 109 181 198 148 165 169 160 160 160 160 160 160 160 160 160 160 160 160 160 160 160 160 160 160 160 160 160 160 160 160 160 160 160 160 160 160 160 160 160 160 160 160 160 160 160 160 160 160 160 160 160 160 160 160 143 167 172 110 181 198 109 181 198 110 183 200 110 183 200 110 183 200 110 183 200 110 183 200 110 183 200 109 181 198 109 182 199 126 175 186 159 160 160 160 160 160 160 160 160 160 160 160 160 160 160 160 160 160 160 160 160 160 160 160 160 160 160 160 160 160 160 160 160 160 160 160 160 160 160 160 160 160 160 160 160 160 160 160 160 160 160 160 160 160 116 180 194 110 183 200 110 183 200 110 183 200 110 183 200 110 183 200 110 183 200 110 183 200 110 182 199 109 182 199 153 162 164 160 160 160 160 160 160 160 160 160 160 160 160 160 160 160 160 160 160 160 160 160 160 160 160 160 160 160 160 160 160 160 160 160 160 160 160 160 160 160 160 160 160 160 160 160 160 160 160 160 160 160 160 160 160 132 172 181 109 182 199 110 183 200 110 183 200 110 183 200 110 183 200 110 183 200 110 183 200 110 183 200 124 175 187 160 160 160 160 160 160 160 160 160 160 160 160 160 160 160 160 160 160 160 160 160 160 160 160 160 160 160 160 160 160 160 160 160 160 160 160 160 160 160 160 160 160 160 160 160 160 160 160 160 160 160 160 160 160 160 160 160 138 169 176 109 182 199 110 183 200 110 183 200 110 183 200 110 183 200 110 183 200 110 183 200 110 183 200 115 165 178 160 160 160 160 160 160 160 160 160 160 160 160 160 160 160 160 160 160 160 160 160 160 160 160 160 160 160 160 160 160 160 160 160 160 160 160 160 160 160 160 160 160 160 160 160 160 160 160 160 160 160 160 160 160 160 160 160 134 171 180 109 182 199 110 183 200 110 183 200 110 183 200 110 183 200 110 183 200 110 183 200 110 184 201 96 165 184 133 152 158 160 160 160 160 160 160 160 160 160 160 160 160 160 160 160 160 160 160 160 160 160 160 160 160 160 160 160 160 160 160 160 160 160 160 160 160 160 160 160 160 160 160 160 160 160 160 160 160 160 160 160 160 160 160 119 177 190 110 183 200 110 183 200 110 183 200 110 183 200 110 183 200 110 183 200 110 183 200 110 183 200 107 179 197 90 141 158 156 159 160 160 160 160 160 160 160 160 160 160 160 160 160 160 160 160 160 160 160 160 160 160 160 160 160 160 160 160 160 160 160 160 160 160 160 160 160 160 160 160 160 160 160 160 160 160 160 160 160 156 161 163 111 181 197 109 181 198 110 183 200 110 183 200 110 183 200 110 183 200 110 183 200 110 183 200 109 182 199 110 183 200 82 149 169 127 151 159 160 160 160 160 160 160 160 160 160 160 160 160 160 160 160 160 160 160 160 160 160 160 160 160 160 160 160 160 160 160 160 160 160 160 160 160 160 160 160 160 160 160 160 160 160 160 160 160 143 167 172 111 182 199 109 181 198 110 183 200 110 183 200 110 183 200 110 183 200 110 183 200 110 183 200 110 183 200 109 182 199 96 166 184 77 138 160 158 159 160 160 160 160 160 160 160 160 160 160 160 160 160 160 160 160 160 160 160 160 160 160 160 160 160 160 160 160 160 160 160 160 160 160 160 160 160 160 160 160 160 160 160 160 160 160 131 172 182 110 183 200 110 183 200 110 183 200 110 183 200 110 183 200 110 183 200 110 183 200 110 183 200 110 183 200 110 183 200 103 174 191 77 142 163 99 145 160 160 160 160 160 160 160 160 160 160 160 160 160 160 160 160 160 160 160 160 160 160 160 160 160 160 160 160 160 160 160 160 160 160 160 160 160 160 160 160 160 160 160 157 161 162 121 176 189 109 182 199 110 183 200 110 183 200 110 183 200 110 183 200 110 183 200 110 183 200 110 183 200 110 183 200 110 183 200 109 182 199 82 149 168 74 140 160 126 152 160 160 160 160 160 160 160 160 160 160 160 160 160 160 160 160 160 160 160 160 160 160 160 160 160 160 160 160 160 160 160 160 160 160 160 160 160 160 160 160 154 162 164 111 180 196 109 182 199 110 183 200 110 183 200 110 183 200 110 183 200 110 183 200 110 183 200 110 183 200 110 183 200 110 183 200 111 184 201 91 160 178 74 139 160 82 141 160 148 157 160 160 160 160 160 160 160 160 160 160 160 160 160 160 160 160 145 166 171 128 173 184 122 176 189 129 174 184 160 160 160 160 160 160 160 160 160 144 166 171 109 182 199 110 182 199 110 183 200 110 183 200 110 183 200 110 183 200 110 183 200 110 183 200 110 183 200 110 183 200 110 183 200 110 183 200 103 174 192 74 139 160 74 140 160 94 144 160 156 159 160 160 160 160 160 160 160 152 163 165 120 177 190 109 182 199 109 182 199 109 181 198 153 163 165 160 160 160 160 160 160 160 160 160 128 173 184 110 183 200 110 182 199 110 183 200 110 183 200 110 183 200 110 183 200 110 183 200 110 183 200 110 183 200 110 183 200 110 183 200 110 183 200 110 184 201 74 139 160 75 139 160 75 140 161 95 144 160 160 160 160 158 160 161 114 180 196 110 183 200 110 183 200 110 183 200 110 183 200 151 164 167 160 160 160 160 160 160 160 160 160 115 179 194 110 183 200 110 183 200 110 183 200 110 183 200 110 183 200 110 183 200 110 183 200 110 183 200 110 183 200 110 183 200 110 183 200 109 182 199 112 185 202 77 143 163 74 139 160 75 140 160 74 139 160 104 145 159 134 169 177 110 183 200 109 181 198 110 183 200 110 182 199 109 182 199 122 176 188 160 160 160 160 160 160 160 160 160 110 183 200 109 182 199 110 183 200 110 183 200 110 183 200 110 183 200 110 183 200 110 183 200 110 183 200 110 183 200 110 183 200 110 183 200 110 183 200 112 185 202 79 144 165 74 139 160 75 140 161 74 139 160 74 138 160 92 155 174 110 183 200 110 183 200 109 182 199 110 183 200 109 181 198 110 183 200 160 160 160 160 160 160 160 160 160 110 183 200 109 181 198 110 183 200 110 183 200 110 183 200 110 183 200 110 183 200 110 183 200 110 183 200 110 183 200 110 183 200 110 183 200 109 182 199 112 186 202 75 141 162 74 139 160 75 140 161 75 140 160 74 139 160 74 139 160 87 154 173 111 184 201 110 183 200 110 183 200 109 181 198 110 183 200 160 160 160 160 160 160 160 160 160 110 183 200 110 183 200 110 183 200 110 183 200 110 183 200 110 183 200 110 183 200 110 183 200 110 183 200 110 183 200 110 183 200 110 183 200 110 183 200 110 183 200 74 139 160 75 140 161 75 140 161 75 140 161 75 140 161 75 140 161 75 140 161 93 162 181 110 183 200 109 182 199 109 181 198 109 182 199 160 160 160 160 160 160 160 160 160 113 181 196 110 183 200 110 183 200 110 183 200 109 182 199 109 182 199 110 183 200 110 183 200 110 183 200 110 183 200 110 183 200 110 183 200 110 183 200 104 176 194 74 139 160 75 140 161 75 140 161 75 140 161 75 140 161 75 140 161 74 139 160 76 141 162 103 174 192 110 182 199 110 183 200 109 182 199 160 160 160 160 160 160 160 160 160 121 176 189 109 182 199 110 183 200 109 182 199 119 187 203 110 183 200 110 183 200 110 183 200 110 183 200 110 183 200 110 183 200 110 183 200 110 183 200 97 167 186 74 139 160 75 140 161 75 140 161 75 140 161 75 140 161 75 140 161 75 140 161 74 139 160 80 145 165 111 185 202 109 182 199 143 167 173 160 160 160 160 160 160 160 160 160 133 172 181 109 182 199 110 182 199 109 182 199 140 198 211 111 183 200 110 183 200 110 183 200 110 183 200 110 183 200 110 183 200 110 183 200 111 184 201 87 156 175 74 139 160 75 140 161 75 140 161 75 140 161 75 140 161 75 140 161 75 140 161 75 140 161 74 138 160 117 157 169 159 161 161 160 160 160 160 160 160 160 160 160 160 160 160 147 165 169 110 183 200 109 182 199 110 183 200 161 208 219 113 184 201 110 183 200 110 183 200 110 183 200 110 183 200 110 183 200 110 183 200 105 177 194 77 142 163 75 140 161 75 140 161 75 140 161 75 140 161 75 140 161 75 140 161 75 140 161 75 140 161 75 140 161 94 144 160 160 160 160 160 160 160 160 160 160 160 160 160 160 160 160 154 162 164 114 181 196 109 182 199 109 182 200 181 218 227 114 185 201 110 183 200 110 183 200 110 183 200 110 183 200 110 183 200 110 183 200 95 163 183 50 106 130 75 141 162 74 139 160 74 139 160 75 140 161 75 140 161 75 140 161 75 140 161 75 140 161 74 139 160 81 140 160 160 160 160 160 160 160 160 160 160 160 160 160 160 160 160 158 160 161 125 175 187 109 182 199 108 182 199 201 228 235 116 186 202 109 182 199 110 183 200 110 183 200 110 183 200 109 182 199 110 183 200 77 141 162 36 88 115 48 104 128 69 133 154 74 139 160 74 139 160 75 140 161 75 140 161 75 140 161 75 140 161 74 139 160 83 141 160 160 160 160 160 160 160 160 160 160 160 160 160 160 160 160 160 160 160 139 169 176 110 182 199 107 180 197 204 230 236 137 196 210 108 182 199 110 183 200 110 183 200 110 183 200 109 182 199 110 184 200 46 101 126 38 90 116 48 103 128 61 120 143 69 133 154 75 140 161 75 140 161 75 140 161 75 140 161 75 140 161 75 140 161 97 145 160 160 160 160 160 160 160 160 160 160 160 160 160 160 160 160 160 160 160 158 160 161 113 181 197 107 181 198 191 223 230 176 215 225 105 180 198 110 183 200 110 183 200 110 183 200 112 185 202 81 146 166 35 87 114 57 116 139 75 140 161 75 140 161 75 140 161 74 139 160 75 140 161 75 140 161 75 140 161 75 140 161 75 140 161 127 152 160 160 160 160 160 160 160 160 160 160 160 160 160 160 160 160 160 160 160 160 160 160 140 169 175 107 181 199 171 212 222 218 237 241 101 178 196 110 183 200 110 183 200 110 183 200 105 177 195 42 96 122 44 98 124 71 134 156 74 139 160 75 140 161 75 140 161 75 140 161 75 140 161 75 140 161 74 139 160 75 140 161 88 143 160 160 160 160 160 160 160 160 160 160 160 160 160 160 160 160 160 160 160 160 160 160 160 160 160 160 160 160 120 176 189 144 200 213 251 252 252 108 182 199 109 182 199 109 182 199 109 182 199 53 110 135 37 90 116 46 101 127 72 135 157 74 139 160 75 140 161 75 140 161 75 140 161 75 140 161 75 140 160 74 139 160 82 141 160 146 156 160 160 160 160 160 160 160 160 160 160 160 160 160 160 160 160 160 160 160 160 160 160 160 160 160 158 159 159 146 160 164 108 179 196 248 252 253 151 203 215 107 182 199 108 181 198 69 132 153 5 52 81 5 52 81 11 59 87 45 102 126 73 138 159 75 140 160 75 140 161 75 140 161 75 140 161 74 139 160 81 140 160 142 155 160 160 160 160 160 160 160 160 160 160 160 160 160 160 160 160 160 160 160 160 160 160 160 160 160 141 147 150 70 98 115 41 77 99 41 95 119 120 157 173 157 187 198 67 131 154 46 103 127 4 50 79 6 53 82 6 54 83 6 53 82 3 50 79 28 81 108 52 111 135 61 123 145 77 132 151 94 139 154 116 146 157 154 158 159 160 160 160 160 160 160 160 160 160 160 160 160 160 160 160 160 160 160 160 160 160 155 156 157 61 91 110 19 62 89 6 53 82 6 53 82 10 55 83 19 62 89 44 81 104 47 82 103 11 56 84 6 53 82 10 56 84 28 68 93 50 83 104 71 98 115 97 116 128 126 137 144 145 152 155 150 155 157 155 157 158 160 160 160 160 160 160 160 160 160 160 160 160 160 160 160 160 160 160 160 160 160 FreeRDP-1.0.2/server/test/tfreerdp.c000066400000000000000000000416411207112532300172070ustar00rootroot00000000000000/** * FreeRDP: A Remote Desktop Protocol Client * FreeRDP Test Server * * Copyright 2011 Marc-Andre Moreau * Copyright 2011 Vic Lee * * 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. */ #include #include #include #include #include #include #include #include #include #include #include #include #include #include static char* test_pcap_file = NULL; static boolean test_dump_rfx_realtime = true; /* HL1, LH1, HH1, HL2, LH2, HH2, HL3, LH3, HH3, LL3 */ static const unsigned int test_quantization_values[] = { 6, 6, 6, 6, 7, 7, 8, 8, 8, 9 }; struct test_peer_context { rdpContext _p; RFX_CONTEXT* rfx_context; STREAM* s; uint8* icon_data; uint8* bg_data; int icon_width; int icon_height; int icon_x; int icon_y; boolean activated; WTSVirtualChannelManager* vcm; void* debug_channel; freerdp_thread* debug_channel_thread; }; typedef struct test_peer_context testPeerContext; void test_peer_context_new(freerdp_peer* client, testPeerContext* context) { context->rfx_context = rfx_context_new(); context->rfx_context->mode = RLGR3; context->rfx_context->width = client->settings->width; context->rfx_context->height = client->settings->height; rfx_context_set_pixel_format(context->rfx_context, RFX_PIXEL_FORMAT_RGB); context->s = stream_new(65536); context->icon_x = -1; context->icon_y = -1; context->vcm = WTSCreateVirtualChannelManager(client); } void test_peer_context_free(freerdp_peer* client, testPeerContext* context) { if (context) { if (context->debug_channel_thread) { freerdp_thread_stop(context->debug_channel_thread); freerdp_thread_free(context->debug_channel_thread); } stream_free(context->s); xfree(context->icon_data); xfree(context->bg_data); rfx_context_free(context->rfx_context); if (context->debug_channel) { WTSVirtualChannelClose(context->debug_channel); } WTSDestroyVirtualChannelManager(context->vcm); xfree(context); } } static void test_peer_init(freerdp_peer* client) { client->context_size = sizeof(testPeerContext); client->ContextNew = (psPeerContextNew) test_peer_context_new; client->ContextFree = (psPeerContextFree) test_peer_context_free; freerdp_peer_context_new(client); } static STREAM* test_peer_stream_init(testPeerContext* context) { stream_clear(context->s); stream_set_pos(context->s, 0); return context->s; } static void test_peer_draw_background(freerdp_peer* client) { testPeerContext* context = (testPeerContext*) client->context; rdpUpdate* update = client->update; SURFACE_BITS_COMMAND* cmd = &update->surface_bits_command; STREAM* s; RFX_RECT rect; uint8* rgb_data; int size; if (!client->settings->rfx_codec) return; s = test_peer_stream_init(context); rect.x = 0; rect.y = 0; rect.width = client->settings->width; rect.height = client->settings->height; size = rect.width * rect.height * 3; rgb_data = xmalloc(size); memset(rgb_data, 0xA0, size); rfx_compose_message(context->rfx_context, s, &rect, 1, rgb_data, rect.width, rect.height, rect.width * 3); cmd->destLeft = 0; cmd->destTop = 0; cmd->destRight = rect.width; cmd->destBottom = rect.height; cmd->bpp = 32; cmd->codecID = client->settings->rfx_codec_id; cmd->width = rect.width; cmd->height = rect.height; cmd->bitmapDataLength = stream_get_length(s); cmd->bitmapData = stream_get_head(s); update->SurfaceBits(update->context, cmd); xfree(rgb_data); } static void test_peer_load_icon(freerdp_peer* client) { testPeerContext* context = (testPeerContext*) client->context; FILE* fp; int i; char line[50]; uint8* rgb_data; int c; if (!client->settings->rfx_codec) return; if ((fp = fopen("test_icon.ppm", "r")) == NULL) return; /* P3 */ fgets(line, sizeof(line), fp); /* Creater comment */ fgets(line, sizeof(line), fp); /* width height */ fgets(line, sizeof(line), fp); sscanf(line, "%d %d", &context->icon_width, &context->icon_height); /* Max */ fgets(line, sizeof(line), fp); rgb_data = xmalloc(context->icon_width * context->icon_height * 3); for (i = 0; i < context->icon_width * context->icon_height * 3; i++) { if (fgets(line, sizeof(line), fp)) { sscanf(line, "%d", &c); rgb_data[i] = (uint8)c; } } context->icon_data = rgb_data; /* background with same size, which will be used to erase the icon from old position */ context->bg_data = xmalloc(context->icon_width * context->icon_height * 3); memset(context->bg_data, 0xA0, context->icon_width * context->icon_height * 3); } static void test_peer_draw_icon(freerdp_peer* client, int x, int y) { testPeerContext* context = (testPeerContext*) client->context; rdpUpdate* update = client->update; SURFACE_BITS_COMMAND* cmd = &update->surface_bits_command; RFX_RECT rect; STREAM* s; if (client->update->dump_rfx) return; if (!client->settings->rfx_codec || !context) return; if (context->icon_width < 1 || !context->activated) return; rect.x = 0; rect.y = 0; rect.width = context->icon_width; rect.height = context->icon_height; if (context->icon_x >= 0) { s = test_peer_stream_init(context); rfx_compose_message(context->rfx_context, s, &rect, 1, context->bg_data, rect.width, rect.height, rect.width * 3); cmd->destLeft = context->icon_x; cmd->destTop = context->icon_y; cmd->destRight = context->icon_x + context->icon_width; cmd->destBottom = context->icon_y + context->icon_height; cmd->bpp = 32; cmd->codecID = client->settings->rfx_codec_id; cmd->width = context->icon_width; cmd->height = context->icon_height; cmd->bitmapDataLength = stream_get_length(s); cmd->bitmapData = stream_get_head(s); update->SurfaceBits(update->context, cmd); } s = test_peer_stream_init(context); rfx_compose_message(context->rfx_context, s, &rect, 1, context->icon_data, rect.width, rect.height, rect.width * 3); cmd->destLeft = x; cmd->destTop = y; cmd->destRight = x + context->icon_width; cmd->destBottom = y + context->icon_height; cmd->bpp = 32; cmd->codecID = client->settings->rfx_codec_id; cmd->width = context->icon_width; cmd->height = context->icon_height; cmd->bitmapDataLength = stream_get_length(s); cmd->bitmapData = stream_get_head(s); update->SurfaceBits(update->context, cmd); context->icon_x = x; context->icon_y = y; } static boolean test_sleep_tsdiff(uint32 *old_sec, uint32 *old_usec, uint32 new_sec, uint32 new_usec) { sint32 sec, usec; if (*old_sec==0 && *old_usec==0) { *old_sec = new_sec; *old_usec = new_usec; return true; } sec = new_sec - *old_sec; usec = new_usec - *old_usec; if (sec<0 || (sec==0 && usec<0)) { printf("Invalid time stamp detected.\n"); return false; } *old_sec = new_sec; *old_usec = new_usec; while (usec < 0) { usec += 1000000; sec--; } if (sec > 0) freerdp_sleep(sec); if (usec > 0) freerdp_usleep(usec); return true; } void tf_peer_dump_rfx(freerdp_peer* client) { STREAM* s; uint32 prev_seconds; uint32 prev_useconds; rdpUpdate* update; rdpPcap* pcap_rfx; pcap_record record; s = stream_new(512); update = client->update; client->update->pcap_rfx = pcap_open(test_pcap_file, false); pcap_rfx = client->update->pcap_rfx; if (pcap_rfx == NULL) return; prev_seconds = prev_useconds = 0; while (pcap_has_next_record(pcap_rfx)) { pcap_get_next_record_header(pcap_rfx, &record); s->data = xrealloc(s->data, record.length); record.data = s->data; s->size = record.length; pcap_get_next_record_content(pcap_rfx, &record); s->p = s->data + s->size; if (test_dump_rfx_realtime && test_sleep_tsdiff(&prev_seconds, &prev_useconds, record.header.ts_sec, record.header.ts_usec) == false) break; update->SurfaceCommand(update->context, s); } } static void* tf_debug_channel_thread_func(void* arg) { void* fd; STREAM* s; void* buffer; uint32 bytes_returned = 0; testPeerContext* context = (testPeerContext*) arg; freerdp_thread* thread = context->debug_channel_thread; if (WTSVirtualChannelQuery(context->debug_channel, WTSVirtualFileHandle, &buffer, &bytes_returned) == true) { fd = *((void**)buffer); WTSFreeMemory(buffer); thread->signals[thread->num_signals++] = wait_obj_new_with_fd(fd); } s = stream_new(4096); WTSVirtualChannelWrite(context->debug_channel, (uint8*) "test1", 5, NULL); while (1) { freerdp_thread_wait(thread); if (freerdp_thread_is_stopped(thread)) break; stream_set_pos(s, 0); if (WTSVirtualChannelRead(context->debug_channel, 0, stream_get_head(s), stream_get_size(s), &bytes_returned) == false) { if (bytes_returned == 0) break; stream_check_size(s, bytes_returned); if (WTSVirtualChannelRead(context->debug_channel, 0, stream_get_head(s), stream_get_size(s), &bytes_returned) == false) { /* should not happen */ break; } } stream_set_pos(s, bytes_returned); printf("got %d bytes\n", bytes_returned); } stream_free(s); freerdp_thread_quit(thread); return 0; } boolean tf_peer_post_connect(freerdp_peer* client) { int i; testPeerContext* context = (testPeerContext*) client->context; /** * This callback is called when the entire connection sequence is done, i.e. we've received the * Font List PDU from the client and sent out the Font Map PDU. * The server may start sending graphics output and receiving keyboard/mouse input after this * callback returns. */ printf("Client %s is activated (osMajorType %d osMinorType %d)", client->hostname, client->settings->os_major_type, client->settings->os_minor_type); if (client->settings->autologon) { printf(" and wants to login automatically as %s\\%s", client->settings->domain ? client->settings->domain : "", client->settings->username); /* A real server may perform OS login here if NLA is not executed previously. */ } printf("\n"); printf("Client requested desktop: %dx%dx%d\n", client->settings->width, client->settings->height, client->settings->color_depth); /* A real server should tag the peer as activated here and start sending updates in mainloop. */ test_peer_load_icon(client); /* Iterate all channel names requested by the client and activate those supported by the server */ for (i = 0; i < client->settings->num_channels; i++) { if (client->settings->channels[i].joined) { if (strncmp(client->settings->channels[i].name, "rdpdbg", 6) == 0) { context->debug_channel = WTSVirtualChannelOpenEx(context->vcm, "rdpdbg", 0); if (context->debug_channel != NULL) { printf("Open channel rdpdbg.\n"); context->debug_channel_thread = freerdp_thread_new(); freerdp_thread_start(context->debug_channel_thread, tf_debug_channel_thread_func, context); } } } } /* Return false here would stop the execution of the peer mainloop. */ return true; } boolean tf_peer_activate(freerdp_peer* client) { testPeerContext* context = (testPeerContext*) client->context; rfx_context_reset(context->rfx_context); context->activated = true; if (test_pcap_file != NULL) { client->update->dump_rfx = true; tf_peer_dump_rfx(client); } else { test_peer_draw_background(client); } return true; } void tf_peer_synchronize_event(rdpInput* input, uint32 flags) { printf("Client sent a synchronize event (flags:0x%X)\n", flags); } void tf_peer_keyboard_event(rdpInput* input, uint16 flags, uint16 code) { freerdp_peer* client = input->context->peer; rdpUpdate* update = client->update; testPeerContext* context = (testPeerContext*) input->context; printf("Client sent a keyboard event (flags:0x%X code:0x%X)\n", flags, code); if ((flags & 0x4000) && code == 0x1F) /* 's' key */ { if (client->settings->width != 800) { client->settings->width = 800; client->settings->height = 600; } else { client->settings->width = 640; client->settings->height = 480; } update->DesktopResize(update->context); context->activated = false; } else if ((flags & 0x4000) && code == 0x2E) /* 'c' key */ { if (context->debug_channel) { WTSVirtualChannelWrite(context->debug_channel, (uint8*) "test2", 5, NULL); } } } void tf_peer_unicode_keyboard_event(rdpInput* input, uint16 flags, uint16 code) { printf("Client sent a unicode keyboard event (flags:0x%X code:0x%X)\n", flags, code); } void tf_peer_mouse_event(rdpInput* input, uint16 flags, uint16 x, uint16 y) { printf("Client sent a mouse event (flags:0x%X pos:%d,%d)\n", flags, x, y); test_peer_draw_icon(input->context->peer, x + 10, y); } void tf_peer_extended_mouse_event(rdpInput* input, uint16 flags, uint16 x, uint16 y) { printf("Client sent an extended mouse event (flags:0x%X pos:%d,%d)\n", flags, x, y); } static void* test_peer_mainloop(void* arg) { int i; int fds; int max_fds; int rcount; void* rfds[32]; fd_set rfds_set; testPeerContext* context; freerdp_peer* client = (freerdp_peer*) arg; memset(rfds, 0, sizeof(rfds)); test_peer_init(client); /* Initialize the real server settings here */ client->settings->cert_file = xstrdup("server.crt"); client->settings->privatekey_file = xstrdup("server.key"); client->settings->nla_security = false; client->settings->rfx_codec = true; client->PostConnect = tf_peer_post_connect; client->Activate = tf_peer_activate; client->input->SynchronizeEvent = tf_peer_synchronize_event; client->input->KeyboardEvent = tf_peer_keyboard_event; client->input->UnicodeKeyboardEvent = tf_peer_unicode_keyboard_event; client->input->MouseEvent = tf_peer_mouse_event; client->input->ExtendedMouseEvent = tf_peer_extended_mouse_event; client->Initialize(client); context = (testPeerContext*) client->context; printf("We've got a client %s\n", client->hostname); while (1) { rcount = 0; if (client->GetFileDescriptor(client, rfds, &rcount) != true) { printf("Failed to get FreeRDP file descriptor\n"); break; } WTSVirtualChannelManagerGetFileDescriptor(context->vcm, rfds, &rcount); max_fds = 0; FD_ZERO(&rfds_set); for (i = 0; i < rcount; i++) { fds = (int)(long)(rfds[i]); if (fds > max_fds) max_fds = fds; FD_SET(fds, &rfds_set); } if (max_fds == 0) break; if (select(max_fds + 1, &rfds_set, NULL, NULL, NULL) == -1) { /* these are not really errors */ if (!((errno == EAGAIN) || (errno == EWOULDBLOCK) || (errno == EINPROGRESS) || (errno == EINTR))) /* signal occurred */ { printf("select failed\n"); break; } } if (client->CheckFileDescriptor(client) != true) break; if (WTSVirtualChannelManagerCheckFileDescriptor(context->vcm) != true) break; } printf("Client %s disconnected.\n", client->hostname); client->Disconnect(client); freerdp_peer_context_free(client); freerdp_peer_free(client); return NULL; } static void test_peer_accepted(freerdp_listener* instance, freerdp_peer* client) { pthread_t th; pthread_create(&th, 0, test_peer_mainloop, client); pthread_detach(th); } static void test_server_mainloop(freerdp_listener* instance) { int i; int fds; int max_fds; int rcount; void* rfds[32]; fd_set rfds_set; memset(rfds, 0, sizeof(rfds)); while (1) { rcount = 0; if (instance->GetFileDescriptor(instance, rfds, &rcount) != true) { printf("Failed to get FreeRDP file descriptor\n"); break; } max_fds = 0; FD_ZERO(&rfds_set); for (i = 0; i < rcount; i++) { fds = (int)(long)(rfds[i]); if (fds > max_fds) max_fds = fds; FD_SET(fds, &rfds_set); } if (max_fds == 0) break; if (select(max_fds + 1, &rfds_set, NULL, NULL, NULL) == -1) { /* these are not really errors */ if (!((errno == EAGAIN) || (errno == EWOULDBLOCK) || (errno == EINPROGRESS) || (errno == EINTR))) /* signal occurred */ { printf("select failed\n"); break; } } if (instance->CheckFileDescriptor(instance) != true) { printf("Failed to check FreeRDP file descriptor\n"); break; } } instance->Close(instance); } int main(int argc, char* argv[]) { freerdp_listener* instance; /* Ignore SIGPIPE, otherwise an SSL_write failure could crash your server */ signal(SIGPIPE, SIG_IGN); instance = freerdp_listener_new(); instance->PeerAccepted = test_peer_accepted; if (argc > 1) test_pcap_file = argv[1]; if (argc > 2 && !strcmp(argv[2], "--fast")) test_dump_rfx_realtime = false; /* Open the server socket and start listening. */ if (instance->Open(instance, NULL, 3389)) { /* Entering the server main loop. In a real server the listener can be run in its own thread. */ test_server_mainloop(instance); } freerdp_listener_free(instance); return 0; }